adjusted examples to use ->

This commit is contained in:
cozis
2022-12-08 03:15:05 +01:00
parent f7d28556a1
commit 57b4f37d3a
4 changed files with 166 additions and 157 deletions
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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";
+41 -23
View File
@@ -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;
} }
@@ -23,24 +61,4 @@ fun min(x, y) {
if x < y: if 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);