adjusted examples to use ->
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
|
|
||||||
|
|
||||||
fun sayHello(self, other)
|
fun sayHello(self, other)
|
||||||
print("Hello ", other, " from ", self.name);
|
print("Hello ", other, " from ", self.name);
|
||||||
|
|
||||||
|
|||||||
+58
-62
@@ -3,11 +3,7 @@ scan = import("scan.noja");
|
|||||||
|
|
||||||
newScanner = scan.newScanner;
|
newScanner = scan.newScanner;
|
||||||
Scanner = scan.Scanner;
|
Scanner = scan.Scanner;
|
||||||
hint = scan.hint;
|
|
||||||
consume = scan.consume;
|
|
||||||
current = scan.current;
|
|
||||||
isDigit = scan.isDigit;
|
isDigit = scan.isDigit;
|
||||||
consumeSpaces = scan.consumeSpaces;
|
|
||||||
ord = string.ord;
|
ord = string.ord;
|
||||||
cat = string.cat;
|
cat = string.cat;
|
||||||
|
|
||||||
@@ -43,15 +39,15 @@ fun isPChar(char: String)
|
|||||||
|
|
||||||
fun parseMethod(scan: Scanner) {
|
fun parseMethod(scan: Scanner) {
|
||||||
|
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
if char == none or not isUpper(char):
|
if char == none or not isUpper(char):
|
||||||
return none, "Missing method";
|
return none, "Missing method";
|
||||||
|
|
||||||
method = "";
|
method = "";
|
||||||
do {
|
do {
|
||||||
method = cat(method, char);
|
method = cat(method, char);
|
||||||
consume(scan);
|
scan->consume();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
} while char != none and isUpper(char);
|
} while char != none and isUpper(char);
|
||||||
|
|
||||||
return method, none;
|
return method, none;
|
||||||
@@ -60,19 +56,19 @@ fun parseMethod(scan: Scanner) {
|
|||||||
fun parsePort(scan: Scanner) {
|
fun parsePort(scan: Scanner) {
|
||||||
|
|
||||||
port = none;
|
port = none;
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
if char == ":" and isDigit(hint(scan, 1)): {
|
if char == ":" and isDigit(scan->hint(1)): {
|
||||||
|
|
||||||
consume(scan); # Skip the ":"
|
scan->consume(); # Skip the ":"
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
|
|
||||||
port = 0;
|
port = 0;
|
||||||
do {
|
do {
|
||||||
digit = ord(char)
|
digit = ord(char)
|
||||||
- ord("0");
|
- ord("0");
|
||||||
port = port * 10 + digit;
|
port = port * 10 + digit;
|
||||||
consume(scan);
|
scan->consume();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
} while char != none and isDigit(char);
|
} while char != none and isDigit(char);
|
||||||
}
|
}
|
||||||
return port;
|
return port;
|
||||||
@@ -84,7 +80,7 @@ fun isHostname(char: String)
|
|||||||
|
|
||||||
fun parseHost(scan: Scanner) {
|
fun parseHost(scan: Scanner) {
|
||||||
|
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
if char == none:
|
if char == none:
|
||||||
return none, "Missing host";
|
return none, "Missing host";
|
||||||
|
|
||||||
@@ -94,8 +90,8 @@ fun parseHost(scan: Scanner) {
|
|||||||
name = "";
|
name = "";
|
||||||
do {
|
do {
|
||||||
name = cat(name, char);
|
name = cat(name, char);
|
||||||
consume(scan);
|
scan->consume();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
} while char != none and isHostname(char);
|
} while char != none and isHostname(char);
|
||||||
|
|
||||||
port = parsePort(scan);
|
port = parsePort(scan);
|
||||||
@@ -105,11 +101,11 @@ fun parseHost(scan: Scanner) {
|
|||||||
fun parsePath(scan: Scanner) {
|
fun parsePath(scan: Scanner) {
|
||||||
|
|
||||||
path = "";
|
path = "";
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
if char != none and char == "/": {
|
if char != none and char == "/": {
|
||||||
path = cat(path, char);
|
path = cat(path, char);
|
||||||
consume(scan);
|
scan->consume();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
} else {
|
} else {
|
||||||
if char == none or not isPChar(char):
|
if char == none or not isPChar(char):
|
||||||
return none, "Invalid character in place of path";
|
return none, "Invalid character in place of path";
|
||||||
@@ -118,14 +114,14 @@ fun parsePath(scan: Scanner) {
|
|||||||
while char != none and isPChar(char): {
|
while char != none and isPChar(char): {
|
||||||
do {
|
do {
|
||||||
path = cat(path, char);
|
path = cat(path, char);
|
||||||
consume(scan);
|
scan->consume();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
} while char != none and isPChar(char);
|
} while char != none and isPChar(char);
|
||||||
if char == none or char != "/":
|
if char == none or char != "/":
|
||||||
break;
|
break;
|
||||||
path = cat(path, char);
|
path = cat(path, char);
|
||||||
consume(scan);
|
scan->consume();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
@@ -141,13 +137,13 @@ fun isQuery(char: ?String) {
|
|||||||
|
|
||||||
fun parseQuery(scan: Scanner) {
|
fun parseQuery(scan: Scanner) {
|
||||||
|
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
if char != none and char == "?": {
|
if char != none and char == "?": {
|
||||||
consume(scan); # Consume the "?"
|
scan->consume(); # Consume the "?"
|
||||||
query = "";
|
query = "";
|
||||||
while isQuery(char = current(scan)): {
|
while isQuery(char = scan->current()): {
|
||||||
query = cat(query, char);
|
query = cat(query, char);
|
||||||
consume(scan);
|
scan->consume();
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
query = none;
|
query = none;
|
||||||
@@ -163,13 +159,13 @@ fun isFragment(char: ?String) {
|
|||||||
|
|
||||||
fun parseFragment(scan: Scanner) {
|
fun parseFragment(scan: Scanner) {
|
||||||
|
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
if char != none and char == "#": {
|
if char != none and char == "#": {
|
||||||
consume(scan); # Consume the "#"
|
scan->consume(); # Consume the "#"
|
||||||
fragment = "";
|
fragment = "";
|
||||||
while isFragment(char = current(scan)): {
|
while isFragment(char = scan->current()): {
|
||||||
fragment = cat(fragment, char);
|
fragment = cat(fragment, char);
|
||||||
consume(scan);
|
scan->consume();
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
fragment = none;
|
fragment = none;
|
||||||
@@ -204,19 +200,19 @@ fun isSchema(char: ?String)
|
|||||||
|
|
||||||
fun parseSchema(scan: Scanner) {
|
fun parseSchema(scan: Scanner) {
|
||||||
|
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
schema = none;
|
schema = none;
|
||||||
if isSchemaFirst(char): {
|
if isSchemaFirst(char): {
|
||||||
start = scan.i;
|
start = scan.i;
|
||||||
schema = "";
|
schema = "";
|
||||||
do {
|
do {
|
||||||
schema = cat(schema, char);
|
schema = cat(schema, char);
|
||||||
consume(scan);
|
scan->consume();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
} while isSchema(char);
|
} while isSchema(char);
|
||||||
|
|
||||||
if char == ":":
|
if char == ":":
|
||||||
consume(scan);
|
scan->consume();
|
||||||
else {
|
else {
|
||||||
schema = none;
|
schema = none;
|
||||||
scan.i = start;
|
scan.i = start;
|
||||||
@@ -227,7 +223,7 @@ fun parseSchema(scan: Scanner) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun followsAuthority(scan: Scanner)
|
fun followsAuthority(scan: Scanner)
|
||||||
return current(scan) == "/" and hint(scan, 1) == "/";
|
return scan->current() == "/" and scan->hint(1) == "/";
|
||||||
|
|
||||||
fun parseURL(scan: Scanner) {
|
fun parseURL(scan: Scanner) {
|
||||||
|
|
||||||
@@ -241,14 +237,14 @@ fun parseURL(scan: Scanner) {
|
|||||||
return none, error;
|
return none, error;
|
||||||
|
|
||||||
path = none;
|
path = none;
|
||||||
if current(scan) == "/":
|
if scan->current() == "/":
|
||||||
path = parsePath(scan);
|
path = parsePath(scan);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
host = none;
|
host = none;
|
||||||
|
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
if char == none or char == "?" or char == "#":
|
if char == none or char == "?" or char == "#":
|
||||||
return none, "Missing path";
|
return none, "Missing path";
|
||||||
|
|
||||||
@@ -271,22 +267,22 @@ fun parseURL(scan: Scanner) {
|
|||||||
|
|
||||||
fun parseVersion(scan: Scanner) {
|
fun parseVersion(scan: Scanner) {
|
||||||
|
|
||||||
if hint(scan, 0) != "H" or hint(scan, 1) != "T"
|
if scan->hint(0) != "H" or scan->hint(1) != "T"
|
||||||
or hint(scan, 2) != "T" or hint(scan, 3) != "P"
|
or scan->hint(2) != "T" or scan->hint(3) != "P"
|
||||||
or hint(scan, 4) != "/" or not isDigit(hint(scan, 5)):
|
or scan->hint(4) != "/" or not isDigit(scan->hint(5)):
|
||||||
return none, "Invalid version token";
|
return none, "Invalid version token";
|
||||||
|
|
||||||
consume(scan, 5);
|
scan->consume(5);
|
||||||
major = ord(current(scan))
|
major = ord(scan->current())
|
||||||
- ord("0");
|
- ord("0");
|
||||||
|
|
||||||
if hint(scan, 1) != "." and isDigit(hint(scan, 2)): {
|
if scan->hint(1) != "." and isDigit(scan->hint(2)): {
|
||||||
consume(scan, 2);
|
scan->consume(2);
|
||||||
minor = ord(current(scan))
|
minor = ord(scan->current())
|
||||||
- ord("0");
|
- ord("0");
|
||||||
} else
|
} else
|
||||||
minor = 0;
|
minor = 0;
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
return {major: major, minor: minor};
|
return {major: major, minor: minor};
|
||||||
}
|
}
|
||||||
@@ -319,59 +315,59 @@ fun parse(src: String) {
|
|||||||
if error != none:
|
if error != none:
|
||||||
return none, error;
|
return none, error;
|
||||||
|
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
if char == none or char != " ":
|
if char == none or char != " ":
|
||||||
return none, "Missing space after method";
|
return none, "Missing space after method";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
url, error = parseURL(scan);
|
url, error = parseURL(scan);
|
||||||
if error != none:
|
if error != none:
|
||||||
return none, error;
|
return none, error;
|
||||||
|
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
if char != " ":
|
if char != " ":
|
||||||
return none, "Missing space after URL";
|
return none, "Missing space after URL";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
version, error = parseVersion(scan);
|
version, error = parseVersion(scan);
|
||||||
if error != none:
|
if error != none:
|
||||||
return none, error;
|
return none, error;
|
||||||
|
|
||||||
if hint(scan, 0) != "\r" or hint(scan, 1) != "\n":
|
if scan->hint(0) != "\r" or scan->hint(1) != "\n":
|
||||||
# Request with no headers or body
|
# Request with no headers or body
|
||||||
return newRequest(method, url, version);
|
return newRequest(method, url, version);
|
||||||
consume(scan, 2); # Consume the "\r\n"
|
scan->consume(2); # Consume the "\r\n"
|
||||||
|
|
||||||
headers = {};
|
headers = {};
|
||||||
while (char = hint(scan, 0)) != none and (char != "\r" or hint(scan, 1) != "\n"): {
|
while (char = scan->hint(0)) != none and (char != "\r" or scan->hint(1) != "\n"): {
|
||||||
|
|
||||||
# Header name until the next ":"
|
# Header name until the next ":"
|
||||||
name = "";
|
name = "";
|
||||||
do {
|
do {
|
||||||
name = cat(name, char);
|
name = cat(name, char);
|
||||||
consume(scan);
|
scan->consume();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
} while char != ":" and char != none;
|
} while char != ":" and char != none;
|
||||||
|
|
||||||
if char == none:
|
if char == none:
|
||||||
return none, "Invalid header (missing \":\" after name)";
|
return none, "Invalid header (missing \":\" after name)";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
consumeSpaces(scan);
|
scan->consumeSpaces();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
|
|
||||||
# Header body until \r
|
# Header body until \r
|
||||||
body = "";
|
body = "";
|
||||||
do {
|
do {
|
||||||
body = cat(body, char);
|
body = cat(body, char);
|
||||||
consume(scan);
|
scan->consume();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
} while char != "\r" and char != none;
|
} while char != "\r" and char != none;
|
||||||
|
|
||||||
headers[name] = body;
|
headers[name] = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
if char != none:
|
if char != none:
|
||||||
consume(scan, 2); # Consume the final "\r\n"
|
scan->consume(2); # Consume the final "\r\n"
|
||||||
|
|
||||||
return newRequest(method, url, version, headers);
|
return newRequest(method, url, version, headers);
|
||||||
}
|
}
|
||||||
|
|||||||
+67
-71
@@ -2,23 +2,19 @@ scan = import("scan.noja");
|
|||||||
|
|
||||||
newScanner = scan.newScanner;
|
newScanner = scan.newScanner;
|
||||||
Scanner = scan.Scanner;
|
Scanner = scan.Scanner;
|
||||||
hint = scan.hint;
|
|
||||||
consume = scan.consume;
|
|
||||||
current = scan.current;
|
|
||||||
consumeSpaces = scan.consumeSpaces;
|
|
||||||
isDigit = scan.isDigit;
|
isDigit = scan.isDigit;
|
||||||
|
|
||||||
fun parseString(scan: Scanner) {
|
fun parseString(scan: Scanner) {
|
||||||
|
|
||||||
assert(current(scan) == '"');
|
assert(scan->current() == '"');
|
||||||
consume(scan); # Consume the opening "
|
scan->consume(); # Consume the opening "
|
||||||
|
|
||||||
temp = "";
|
temp = "";
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
while char != '"' and char != none: {
|
while char != '"' and char != none: {
|
||||||
temp = string.cat(temp, char);
|
temp = string.cat(temp, char);
|
||||||
consume(scan);
|
scan->consume();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
}
|
}
|
||||||
|
|
||||||
if char == none: {
|
if char == none: {
|
||||||
@@ -26,7 +22,7 @@ fun parseString(scan: Scanner) {
|
|||||||
err = "Source ended inside a string literal";
|
err = "Source ended inside a string literal";
|
||||||
} else {
|
} else {
|
||||||
assert(char == '"');
|
assert(char == '"');
|
||||||
consume(scan);
|
scan->consume();
|
||||||
val = temp;
|
val = temp;
|
||||||
err = none;
|
err = none;
|
||||||
}
|
}
|
||||||
@@ -36,22 +32,22 @@ fun parseString(scan: Scanner) {
|
|||||||
|
|
||||||
fun parseObject(scan: Scanner) {
|
fun parseObject(scan: Scanner) {
|
||||||
|
|
||||||
assert(current(scan) == '{');
|
assert(scan->current() == '{');
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
obj = {};
|
obj = {};
|
||||||
consumeSpaces(scan);
|
scan->consumeSpaces();
|
||||||
if current(scan) != '}': do {
|
if scan->current() != '}': do {
|
||||||
key, err = parseValue(scan);
|
key, err = parseValue(scan);
|
||||||
if err != none:
|
if err != none:
|
||||||
return none, err;
|
return none, err;
|
||||||
if type(key) != String:
|
if type(key) != String:
|
||||||
return none, "Object key isn't a string";
|
return none, "Object key isn't a string";
|
||||||
|
|
||||||
consumeSpaces(scan);
|
scan->consumeSpaces();
|
||||||
if current(scan) != ':':
|
if scan->current() != ':':
|
||||||
return none, "Missing ':' separator after key";
|
return none, "Missing ':' separator after key";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
val, err = parseValue(scan);
|
val, err = parseValue(scan);
|
||||||
if err != none:
|
if err != none:
|
||||||
@@ -61,111 +57,111 @@ fun parseObject(scan: Scanner) {
|
|||||||
return none, "Duplicate key in object";
|
return none, "Duplicate key in object";
|
||||||
obj[key] = val;
|
obj[key] = val;
|
||||||
|
|
||||||
consumeSpaces(scan);
|
scan->consumeSpaces();
|
||||||
if current(scan) == '}':
|
if scan->current() == '}':
|
||||||
done = true;
|
done = true;
|
||||||
else {
|
else {
|
||||||
if current(scan) != ',':
|
if scan->current() != ',':
|
||||||
return none, "Invalid character where either ',' or '}' were expected";
|
return none, "Invalid character where either ',' or '}' were expected";
|
||||||
consume(scan); # Consume the ","
|
scan->consume(); # Consume the ","
|
||||||
done = false;
|
done = false;
|
||||||
}
|
}
|
||||||
} while not done;
|
} while not done;
|
||||||
assert(current(scan) == '}');
|
assert(scan->current() == '}');
|
||||||
consume(scan);
|
scan->consume();
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseArray(scan: Scanner) {
|
fun parseArray(scan: Scanner) {
|
||||||
|
|
||||||
assert(current(scan) == '[');
|
assert(scan->current() == '[');
|
||||||
consume(scan); # Consume the [
|
scan->consume(); # Consume the [
|
||||||
|
|
||||||
array = [];
|
array = [];
|
||||||
|
|
||||||
consumeSpaces(scan);
|
scan->consumeSpaces();
|
||||||
if current(scan) != ']': do {
|
if scan->current() != ']': do {
|
||||||
|
|
||||||
val, err = parseValue(scan);
|
val, err = parseValue(scan);
|
||||||
if err != none:
|
if err != none:
|
||||||
return none, err;
|
return none, err;
|
||||||
array[count(array)] = val;
|
array[count(array)] = val;
|
||||||
|
|
||||||
consumeSpaces(scan);
|
scan->consumeSpaces();
|
||||||
if current(scan) == ']':
|
if scan->current() == ']':
|
||||||
done = true;
|
done = true;
|
||||||
else {
|
else {
|
||||||
if current(scan) != ',':
|
if scan->current() != ',':
|
||||||
return none, "Invalid character where either ',' or ']' were expected";
|
return none, "Invalid character where either ',' or ']' were expected";
|
||||||
consume(scan); # Consume the ","
|
scan->consume(); # Consume the ","
|
||||||
done = false;
|
done = false;
|
||||||
}
|
}
|
||||||
} while not done;
|
} while not done;
|
||||||
assert(current(scan) == ']');
|
assert(scan->current() == ']');
|
||||||
consume(scan);
|
scan->consume();
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseFalse(scan: Scanner) {
|
fun parseFalse(scan: Scanner) {
|
||||||
|
|
||||||
assert(current(scan) == 'f');
|
assert(scan->current() == 'f');
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
if current(scan) != 'a':
|
if scan->current() != 'a':
|
||||||
return none, "Invalid character after 'f'";
|
return none, "Invalid character after 'f'";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
if current(scan) != 'l':
|
if scan->current() != 'l':
|
||||||
return none, "Invalid character after 'fa'";
|
return none, "Invalid character after 'fa'";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
if current(scan) != 's':
|
if scan->current() != 's':
|
||||||
return none, "Invalid character after 'fal'";
|
return none, "Invalid character after 'fal'";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
if current(scan) != 'e':
|
if scan->current() != 'e':
|
||||||
return none, "Invalid character after 'fals'";
|
return none, "Invalid character after 'fals'";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseTrue(scan: Scanner) {
|
fun parseTrue(scan: Scanner) {
|
||||||
|
|
||||||
assert(current(scan) == 't');
|
assert(scan->current() == 't');
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
if current(scan) != 'r':
|
if scan->current() != 'r':
|
||||||
return none, "Invalid character after 't'";
|
return none, "Invalid character after 't'";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
if current(scan) != 'u':
|
if scan->current() != 'u':
|
||||||
return none, "Invalid character after 'tr'";
|
return none, "Invalid character after 'tr'";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
if current(scan) != 'e':
|
if scan->current() != 'e':
|
||||||
return none, "Invalid character after 'tru'";
|
return none, "Invalid character after 'tru'";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseNull(scan: Scanner) {
|
fun parseNull(scan: Scanner) {
|
||||||
|
|
||||||
assert(current(scan) == 'n');
|
assert(scan->current() == 'n');
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
if current(scan) != 'u':
|
if scan->current() != 'u':
|
||||||
return none, "Invalid character after 'n'";
|
return none, "Invalid character after 'n'";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
if current(scan) != 'l':
|
if scan->current() != 'l':
|
||||||
return none, "Invalid character after 'nu'";
|
return none, "Invalid character after 'nu'";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
if current(scan) != 'l':
|
if scan->current() != 'l':
|
||||||
return none, "Invalid character after 'nul'";
|
return none, "Invalid character after 'nul'";
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
@@ -178,15 +174,15 @@ fun integerFromDigit(char: String) {
|
|||||||
|
|
||||||
fun parseNumber(scan: Scanner) {
|
fun parseNumber(scan: Scanner) {
|
||||||
|
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
|
|
||||||
sign = 1;
|
sign = 1;
|
||||||
if char == '+' or char == '-': {
|
if char == '+' or char == '-': {
|
||||||
|
|
||||||
sign = {'+': 1, '-': -1}[char];
|
sign = {'+': 1, '-': -1}[char];
|
||||||
consume(scan);
|
scan->consume();
|
||||||
|
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
if not isDigit(char):
|
if not isDigit(char):
|
||||||
return none, "Invalid character after +/-";
|
return none, "Invalid character after +/-";
|
||||||
}
|
}
|
||||||
@@ -198,23 +194,23 @@ fun parseNumber(scan: Scanner) {
|
|||||||
n = integerFromDigit(char);
|
n = integerFromDigit(char);
|
||||||
temp = temp * 10 + n;
|
temp = temp * 10 + n;
|
||||||
|
|
||||||
consume(scan);
|
scan->consume();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
|
|
||||||
} while isDigit(char);
|
} while isDigit(char);
|
||||||
|
|
||||||
if char == '.' and isDigit(hint(scan, 1)): {
|
if char == '.' and isDigit(scan->hint(1)): {
|
||||||
|
|
||||||
consume(scan); # Consume the dot
|
scan->consume(); # Consume the dot
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
|
|
||||||
q = 1.0;
|
q = 1.0;
|
||||||
do {
|
do {
|
||||||
q = q / 10;
|
q = q / 10;
|
||||||
n = integerFromDigit(char);
|
n = integerFromDigit(char);
|
||||||
temp = temp + q * n;
|
temp = temp + q * n;
|
||||||
consume(scan);
|
scan->consume();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
} while isDigit(char);
|
} while isDigit(char);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,8 +240,8 @@ fun parseValue(scan: Scanner) {
|
|||||||
'9': parseNumber
|
'9': parseNumber
|
||||||
};
|
};
|
||||||
|
|
||||||
consumeSpaces(scan);
|
scan->consumeSpaces();
|
||||||
char = current(scan);
|
char = scan->current();
|
||||||
if char == none: {
|
if char == none: {
|
||||||
val = none;
|
val = none;
|
||||||
err = "Source ended where a value was expected";
|
err = "Source ended where a value was expected";
|
||||||
|
|||||||
+40
-22
@@ -1,8 +1,46 @@
|
|||||||
|
|
||||||
Scanner = {src: String, i: int};
|
fun dummy() {}
|
||||||
|
Func = type(dummy)
|
||||||
|
| type(print);
|
||||||
|
|
||||||
|
Scanner = {
|
||||||
|
src: String,
|
||||||
|
i: int,
|
||||||
|
hint: Func,
|
||||||
|
current: Func,
|
||||||
|
consume: Func,
|
||||||
|
consumeSpaces: Func
|
||||||
|
};
|
||||||
|
|
||||||
|
fun hint(scan: Scanner, n: int = 1) {
|
||||||
|
k = scan.i + n;
|
||||||
|
if k < count(scan.src):
|
||||||
|
return scan.src[k];
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun current(scan: Scanner)
|
||||||
|
return hint(scan, 0);
|
||||||
|
|
||||||
|
fun consume(scan: Scanner, n: int = 1) {
|
||||||
|
assert(n > 0);
|
||||||
|
limit = count(scan.src);
|
||||||
|
scan.i = min(scan.i + n, limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
fun consumeSpaces(scan: Scanner)
|
||||||
|
while isSpace(current(scan)):
|
||||||
|
consume(scan);
|
||||||
|
|
||||||
fun newScanner(src: String) {
|
fun newScanner(src: String) {
|
||||||
scan = {src: src, i: 0};
|
scan = {
|
||||||
|
src: src,
|
||||||
|
i: 0,
|
||||||
|
hint: hint,
|
||||||
|
consume: consume,
|
||||||
|
current: current,
|
||||||
|
consumeSpaces: consumeSpaces
|
||||||
|
};
|
||||||
assert(istypeof(Scanner, scan));
|
assert(istypeof(Scanner, scan));
|
||||||
return scan;
|
return scan;
|
||||||
}
|
}
|
||||||
@@ -24,23 +62,3 @@ fun min(x, y) {
|
|||||||
return x;
|
return x;
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hint(scan: Scanner, n: int = 1) {
|
|
||||||
k = scan.i + n;
|
|
||||||
if k < count(scan.src):
|
|
||||||
return scan.src[k];
|
|
||||||
return none;
|
|
||||||
}
|
|
||||||
|
|
||||||
fun current(scan: Scanner)
|
|
||||||
return hint(scan, 0);
|
|
||||||
|
|
||||||
fun consume(scan: Scanner, n: int = 1) {
|
|
||||||
assert(n > 0);
|
|
||||||
limit = count(scan.src);
|
|
||||||
scan.i = min(scan.i + n, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
fun consumeSpaces(scan: Scanner)
|
|
||||||
while isSpace(current(scan)):
|
|
||||||
consume(scan);
|
|
||||||
Reference in New Issue
Block a user