new built-in variables for each type
This commit is contained in:
+4
-16
@@ -9,11 +9,8 @@ fun isDigit(c)
|
||||
and unicode(c) >= unicode('0');
|
||||
|
||||
fun skip(ctx, test)
|
||||
while not ended(ctx): {
|
||||
if not test(current(ctx)):
|
||||
break;
|
||||
while not ended(ctx) and test(current(ctx)):
|
||||
next(ctx);
|
||||
}
|
||||
|
||||
fun ended(ctx)
|
||||
return ctx.i == count(ctx.str);
|
||||
@@ -167,13 +164,8 @@ fun parseString(ctx) {
|
||||
|
||||
buff = '';
|
||||
|
||||
while not ended(ctx): {
|
||||
|
||||
if current(ctx) == '"':
|
||||
break;
|
||||
|
||||
while not ended(ctx) and current(ctx) != '"': {
|
||||
buff = strcat(buff, current(ctx));
|
||||
|
||||
next(ctx);
|
||||
}
|
||||
|
||||
@@ -191,9 +183,7 @@ fun parseNumber(ctx) {
|
||||
# Number (int or float)
|
||||
|
||||
parsed = 0;
|
||||
while not ended(ctx): {
|
||||
if not isDigit(current(ctx)):
|
||||
break;
|
||||
while not ended(ctx) and isDigit(current(ctx)): {
|
||||
parsed = parsed * 10 + unicode(current(ctx)) - unicode('0');
|
||||
next(ctx);
|
||||
}
|
||||
@@ -212,9 +202,7 @@ fun parseNumber(ctx) {
|
||||
return none, "Got something other than a digit after dot";
|
||||
|
||||
fact = 1;
|
||||
while not ended(ctx): {
|
||||
if not isDigit(current(ctx)):
|
||||
break;
|
||||
while not ended(ctx) and isDigit(current(ctx)): {
|
||||
fact = fact / 10.0;
|
||||
parsed = parsed + fact * (unicode(current(ctx)) - unicode('0'));
|
||||
next(ctx);
|
||||
|
||||
@@ -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");
|
||||
Reference in New Issue
Block a user