new built-in variables for each type

This commit is contained in:
cozis
2022-08-14 13:04:53 +02:00
parent d24877c5f3
commit bc516f470a
26 changed files with 300 additions and 36 deletions
+171
View File
@@ -0,0 +1,171 @@
fun isSpace(c)
return c == " " or c == "\t" or c == "\n";
fun isDigit(c) {
u = unicode(c);
d = u - unicode("0");
return d >= 0 and d <= 9;
}
fun skipSpaces(context) {
# Skip zero or more whitespace characters.
while context.cur < count(context.str)
and isSpace(context.str[context.cur]):
context.cur = context.cur + 1;
}
fun parseNull(context) {
assert(context.cur < count(context)
and context.str[context.cur] == 'n');
if context.cur+3 > count(context)
or context.str[context.cur+1] != 'u'
or context.str[context.cur+2] != 'l'
or context.str[context.cur+3] != 'l':
return none, "Unexpected token starting with \"n\"";
context.cur = context.cur + count("null");
return none;
}
fun parseTrue(context) {
assert(context.cur < count(context)
and context.str[context.cur] == 't');
if context.cur+3 > count(context)
or context.str[context.cur+1] != 'r'
or context.str[context.cur+2] != 'u'
or context.str[context.cur+3] != 'e':
return none, "Unexpected token starting with \"t\"";
context.cur = context.cur + count("true");
return true;
}
fun parseFalse(context) {
assert(context.cur < count(context)
and context.str[context.cur] == 'f');
if context.cur+3 > count(context)
or context.str[context.cur+1] != 'a'
or context.str[context.cur+2] != 'l'
or context.str[context.cur+3] != 's'
or context.str[context.cur+4] != 'e':
return none, "Unexpected token starting with \"f\"";
context.cur = context.cur + count("false");
return false;
}
fun skip(context, test_callback) {
k = context.cur;
while k < count(context) and test_callback(context.str[k]):
k = k + 1;
return k;
}
fun parseInteger(context) {
assert(context.cur < count(context) and isDigit(context.str[context.cur]));
buffer = 0;
do {
c = context.str[context.cur];
d = unicode(c) - unicode('0');
buffer = buffer * 10 + d;
context.cur = context.cur + 1;
} while context.cur < count(context)
and isDigit(context.str[context.cur]);
return buffer;
}
fun parseFloating(context) {
assert(context.cur < count(context) and isDigit(context.str[context.cur]));
# It's ensured by the caller (parseIntegerOrFloating)
# that now the strings contains two sequences of
# digits with a dot in the middle.
buffer = 0.0;
# Scan the integer part.
do {
c = context.str[context.cur];
d = unicode(c) - unicode('0');
buffer = buffer * 10 + d;
context.cur = context.cur + 1;
} while context.str[context.cur] != ".";
assert(isDigit(context.str[context.cur+1]));
# Scan the decimal part.
q = 1;
do {
c = context.str[context.cur];
d = unicode(c) - unicode('0');
q = q / 10;
buffer = buffer + q * d;
context.cur = context.cur + 1;
} while context.cur < count(context)
and isDigit(context);
return buffer;
}
fun parseIntegerOrFloating(context) {
assert(context.cur < count(context) and isDigit(context.str[context.cur]));
# Is the first digit sequence followed by a dot
# and then one or more digits?
k = skip(context, isDigit);
if k+1 < count(context) and context.str[k] == "." and isDigit(context.str[k+1]):
# It's a floating point value, then!
return parseFloating(context);
else
# It's good old integer!
return parseInteger(context);
}
fun parseValue(context) {
if context.cur == count(context):
return none, "Source ended where a value was expected";
c = context.str[context.cur];
if c == "{":
val, err = parseObject(context);
else if c == "[":
val, err = parseArray(context);
else if c == '"':
val, err = parseString(context);
else if isDigit(c):
val, err = parseIntegerOrFloating(context);
else if c == 'n':
val, err = parseNull(context);
else if c == 't':
val, err = parseTrue(context);
else if c == 'f':
val, err = parseFalse(context);
else {
val = none;
err = strcat("Unexepected character \"", c, "\" where a value was expected");
}
return val, err;
}
fun parse(str) {
context = {str: str, cur: 0};
skipSpaces(context);
val, err = parseValue(context);
return val, err;
}
val, err = parse('3.14');
print("val=[", val, "]\n");
print("err=[", err, "]\n");