Skip to content

Instantly share code, notes, and snippets.

@Duologic
Created April 4, 2024 18:15
Show Gist options
  • Save Duologic/f4d2ac962dd706a3ce448acf5be4eb8a to your computer and use it in GitHub Desktop.
Save Duologic/f4d2ac962dd706a3ce448acf5be4eb8a to your computer and use it in GitHub Desktop.
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