commit 102aa58ebfdc93faff8397c578fbef465877d6ec
parent 2aa6b92667ea64a185d8db290ebc9470adb99374
Author: thing1 <thing1@seacrossedlovers.xyz>
Date: Tue, 12 May 2026 17:42:33 +0100
updates
Diffstat:
3 files changed, 60 insertions(+), 26 deletions(-)
diff --git a/zpy/lex/+test.ha b/zpy/lex/+test.ha
@@ -8,10 +8,8 @@ fn check(lex: *lexer, expect: [](types | invalid)) void = {
let n = next(lex);
match (exp) {
- case let ty: types =>
- assert((n as token).ty == ty);
- case invalid =>
- assert(n is error);
+ case let ty: types => assert((n as token).ty == ty);
+ case invalid => assert(n is error);
};
};
};
diff --git a/zpy/parse/+test.ha b/zpy/parse/+test.ha
@@ -2,12 +2,54 @@ use zpy::lex;
use memio;
use strings;
+fn equalNodes(n1: node, n2: node) bool = {
+ match (n1) {
+ case let n1: sexpr =>
+ if (n2 is sexpr) {
+ if ((n2 as sexpr).func == n1.func) {
+ if (len(n1.args) != len((n2 as sexpr).args))
+ return false;
+
+ for (let i = 0z; i < len (n1.args); i+=1) {
+ if (!equalNodes(*n1.args[i], *(n2 as sexpr).args[i]))
+ return false;
+ };
+
+ return true;
+ };
+ };
+
+ case let n1: name =>
+ if (n2 is name)
+ if ((n2 as name) == n1)
+ return true;
+
+ case let n1: lit =>
+ if (n2 is lit)
+ if ((n2 as lit) == n1)
+ return true;
+ };
+
+ return false;
+};
+
@test
fn BinaryExpr() void = {
let lex = lex::new(&memio::fixed(strings::toutf8("(foo 1 2)")));
- let sexpr = try(lex, [&parseSexpr])! as sexpr;
- assert(sexpr.func == "foo");
- assert(len(sexpr.args) == 2);
+ let s = try(lex, [&parseSexpr])! as sexpr;
+
+ assert(s.func == "foo");
+ assert(len(s.args) == 2);
+ assert(*s.args[0] == 1);
+ assert(*s.args[1] == 2);
+
+ //if (!equalNodes(s, sexpr{
+ // func = "foo",
+ // args = [
+ // &1: *node,
+ // &2: *node
+ // ]
+ //})) abort();
};
@test
@@ -41,3 +83,11 @@ fn NestedExpr() void = {
assert(sexpr.func == "foo");
assert(len(sexpr.args) == 1);
};
+
+@test
+fn DeeplyNestedExpr() void = {
+ let lex = lex::new(&memio::fixed(strings::toutf8("(foo (bar (baz (boo 1))) 42)")));
+ let sexpr = try(lex, [&parseSexpr])! as sexpr;
+ assert(sexpr.func == "foo");
+ assert(len(sexpr.args) == 2);
+};
diff --git a/zpy/parse/parse.ha b/zpy/parse/parse.ha
@@ -4,38 +4,24 @@ use strconv;
use fmt;
use bufio;
+// TODO put nodes on the heap, as pointers fuck this all up
+
export type parserfn = fn(_: *lex::lexer) (node | error);
export fn try(l: *lex::lexer, fs: []*parserfn) (node | error) = {
let save = io::tell(l.in)!;
- for (let i = 0z; i < len(fs); i+=1) {
- let f = fs[i];
-
+ for (let f .. fs) {
match (f(l)) {
case let n: node => return n;
- case let e: error =>
- io::seek(l.in, save, io::whence::SET)!;
- printrest(l);
+ case let e: error => io::seek(l.in, save, io::whence::SET)!;
};
};
return ("reached end of try block", 0);
};
-fn printrest(l: *lex::lexer) void = {
- let save = io::tell(l.in)!;
- for (true) {
- match (bufio::read_rune(l.in)!) {
- case let r: rune => fmt::print(r)!;
- case => break;
- };
- };
- fmt::println()!;
- io::seek(l.in, save, io::whence::SET)!;
-};
-
export fn parseSexpr(l: *lex::lexer) (node | error) = {
match (want(l, [lex::types::OBRACE])) {
case lex::token => yield;
@@ -47,7 +33,7 @@ export fn parseSexpr(l: *lex::lexer) (node | error) = {
let args: []*node = [];
for (true) {
- match (try(l, [ &parseName, &parseSexpr, &parseLit])) {
+ match (try(l, [&parseSexpr, &parseName, &parseLit])) {
case let n: node =>
append(args, &n)!;
case let e: error =>