Created
April 4, 2024 18:15
-
-
Save Duologic/f4d2ac962dd706a3ce448acf5be4eb8a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local xtd = import 'github.com/jsonnet-libs/xtd/main.libsonnet'; | |
local cp = std.codepoint; | |
// "1" "9" | |
local onenine(c) = (cp(c) >= 49 && cp(c) <= 57); | |
// "0" | |
local digit(c) = (cp(c) == 48 || onenine(c)); | |
local digits(str) = | |
std.length(str) > 0 | |
&& std.all( | |
std.foldl( | |
function(acc, c) | |
acc + [digit(c)], | |
std.stringChars(str), | |
[], | |
) | |
); | |
local fraction(str) = | |
str == '' | |
|| (str[0] == '.' && digits(str[1:])); | |
local sign(c) = (c == '-' || c == '+'); | |
local exponent(str) = | |
str == '' | |
|| (str[0] == 'E' && digits(str[1:])) | |
|| (str[0] == 'e' && digits(str[1:])) | |
|| (std.length(str) > 1 && str[0] == 'E' && sign(str[1]) && digits(str[2:])) | |
|| (std.length(str) > 1 && str[0] == 'e' && sign(str[1]) && digits(str[2:])); | |
local integer(str) = | |
(std.length(str) == 1 && digit(str[0])) | |
|| (std.length(str) > 0 && onenine(str[0]) && digits(str[1:])) | |
|| (std.length(str) > 1 && str[0] == '-' && digit(str[1])) | |
|| (std.length(str) > 1 && str[0] == '-' && onenine(str[1]) && digits(str[2:])); | |
local number(str) = | |
local expectInteger = | |
if std.member(str, '.') | |
then std.split(str, '.')[0] | |
else if std.member(str, 'e') | |
then std.split(str, 'e')[0] | |
else if std.member(str, 'E') | |
then std.split(str, 'E')[0] | |
else str; | |
local expectFraction = | |
if std.member(str, 'e') | |
then std.split(str[std.length(expectInteger):], 'e')[0] | |
else if std.member(str, 'E') | |
then std.split(str[std.length(expectInteger):], 'E')[0] | |
else str[std.length(expectInteger):]; | |
local expectExponent = str[std.length(expectInteger) + std.length(expectFraction):]; | |
//[str] | |
//+ [expectInteger, expectFraction, expectExponent] | |
//+ [ | |
// integer(expectInteger), | |
// fraction(expectFraction), | |
// exponent(expectExponent), | |
//]; | |
std.all([ | |
integer(expectInteger), | |
fraction(expectFraction), | |
exponent(expectExponent), | |
]); | |
local parseIntegerFromString(str, strict=true) = | |
local s = ['-', '+', '.', 'e', 'E']; | |
if !(integer(str[0]) || str[0] == '-') | |
then '' | |
else | |
local aux(index=0, return='') = | |
if index < std.length(str) && number(return + str[index]) | |
then aux(index + 1, return + str[index]) | |
else if index + 1 < std.length(str) && std.member(s, str[index]) | |
then aux(index + 1, return + str[index]) | |
else if strict && index + 1 <= std.length(str) && std.member(s, str[index]) | |
then error "Couldn't lex number, junk after %s" % str[index] | |
else if number(return) | |
then return | |
else ''; | |
std.trace(str, aux)(); | |
std.map( | |
parseIntegerFromString, [ | |
'15', | |
'1.5', | |
'-1.5', | |
'1e5', | |
'1E5', | |
'1.5e5', | |
'1.5E5', | |
'1.5e-5', | |
'1.5E+5', | |
'15e5garbage', | |
//'15e', // fails on strict | |
'1garbag5e5garbage', | |
//'1.', // fails on strict | |
'garbage15e5garbage', | |
'+', | |
'+1E5', | |
'.5', | |
'E5', | |
'e5', | |
] | |
) | |
/* | |
'next are true', | |
number(parseIntegerFromString(a)), | |
number(parseIntegerFromString(b)), | |
'15', | |
'1.5', | |
'-1.5', | |
'1e5', | |
'1E5', | |
'1.5e5', | |
'1.5E5', | |
'1.5e-5', | |
'1.5E+5', | |
'+1E5', | |
'.5', | |
'e5', | |
'E5', | |
] | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment