zpy

A lisp like language written in hare
Log | Files | Refs

commit 4efce2e290a7d42d0a4eb1c3b50460af1e3cc8e6
parent 50333fa221b728256102c0ff3ef7a93166e53841
Author: thing1 <thing1@seacrossedlovers.xyz>
Date:   Wed, 13 May 2026 10:08:08 +0100

got a working parser/lexer

breaks when linked with libc???

Diffstat:
Mzpy/lex/lexer.ha | 1-
Mzpy/parse/+test.ha | 99++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Mzpy/parse/ast.ha | 2+-
Mzpy/parse/parse.ha | 18+++++++++---------
4 files changed, 81 insertions(+), 39 deletions(-)

diff --git a/zpy/lex/lexer.ha b/zpy/lex/lexer.ha @@ -30,7 +30,6 @@ fn getItem(l: *lexer, ty: types) lexItem = { for (let item .. l.items) { if (item.ty == ty) return item; }; - fmt::println(ty: int)!; abort(); }; diff --git a/zpy/parse/+test.ha b/zpy/parse/+test.ha @@ -1,6 +1,7 @@ use zpy::lex; use memio; use strings; +use fmt; fn equalNodes(n1: node, n2: node) bool = { match (n1) { @@ -11,7 +12,7 @@ fn equalNodes(n1: node, n2: node) bool = { return false; for (let i = 0z; i < len (n1.args); i+=1) { - if (!equalNodes(*n1.args[i], *(n2 as sexpr).args[i])) + if (!equalNodes(n1.args[i], (n2 as sexpr).args[i])) return false; }; @@ -38,56 +39,98 @@ fn BinaryExpr() void = { let lex = lex::new(&memio::fixed(strings::toutf8("(foo 1 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(); + if (!equalNodes(s, sexpr{ + func = "foo", + args = [ + 1: node, + 2: node + ] + })) abort(); }; @test fn NoArgExpr() void = { let lex = lex::new(&memio::fixed(strings::toutf8("(foo)"))); - let sexpr = try(lex, [&parseSexpr])! as sexpr; - assert(sexpr.func == "foo"); - assert(len(sexpr.args) == 0); + let s = try(lex, [&parseSexpr])! as sexpr; + + if (!equalNodes(s, sexpr{ + func = "foo", + args = [] + })) abort(); + }; @test fn ExprWithName() void = { let lex = lex::new(&memio::fixed(strings::toutf8("(foo bar)"))); - let sexpr = try(lex, [&parseSexpr])! as sexpr; - assert(sexpr.func == "foo"); - assert(len(sexpr.args) == 1); + let s = try(lex, [&parseSexpr])! as sexpr; + + if (!equalNodes(s, sexpr{ + func = "foo", + args = [ + "bar": node + ] + })) abort(); }; @test fn ExprWithNameAndNum() void = { let lex = lex::new(&memio::fixed(strings::toutf8("(foo bar 1)"))); - let sexpr = try(lex, [&parseSexpr])! as sexpr; - assert(sexpr.func == "foo"); - assert(len(sexpr.args) == 2); + let s = try(lex, [&parseSexpr])! as sexpr; + + if (!equalNodes(s, sexpr{ + func = "foo", + args = [ + "bar": node, + 1: node + ] + })) abort(); + }; @test fn NestedExpr() void = { let lex = lex::new(&memio::fixed(strings::toutf8("(foo (bar 1))"))); - let sexpr = try(lex, [&parseSexpr])! as sexpr; - assert(sexpr.func == "foo"); - assert(len(sexpr.args) == 1); + let s = try(lex, [&parseSexpr])! as sexpr; + + if (!equalNodes(s, sexpr{ + func = "foo", + args = [ + sexpr{ + func = "bar", + args = [ + 1: node + ] + } + ] + })) abort(); }; @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); + let s = try(lex, [&parseSexpr])! as sexpr; + + if (!equalNodes(s, sexpr{ + func = "foo", + args = [ + sexpr{ + func = "bar", + args = [ + sexpr{ + func = "baz", + args = [ + sexpr{ + func = "boo", + args = [ + 1: node + ] + } + ] + } + ] + }, + 42: node + ] + })) abort(); }; diff --git a/zpy/parse/ast.ha b/zpy/parse/ast.ha @@ -2,7 +2,7 @@ export type node = (sexpr | lit | name); export type sexpr = struct { func: str, - args: []*node + args: []node }; export type lit = u64; diff --git a/zpy/parse/parse.ha b/zpy/parse/parse.ha @@ -3,8 +3,7 @@ use io; use strconv; use fmt; use bufio; - -// TODO put nodes on the heap, as pointers fuck this all up +use strings; export type parserfn = fn(_: *lex::lexer) (node | error); @@ -30,15 +29,18 @@ export fn parseSexpr(l: *lex::lexer) (node | error) = { let name = try(l, [&parseName])?; - let args: []*node = []; + let args: []node = []; for (true) { match (try(l, [&parseSexpr, &parseName, &parseLit])) { case let n: node => - append(args, &n)!; + append(args, n)!; case let e: error => match (want(l, [lex::types::CBRACE])) { - case lex::token => return sexpr{func = name: str, args = args}; + case lex::token => return sexpr{ + func = name: str, + args = args + }: node; case => return e; }; }; @@ -47,16 +49,14 @@ export fn parseSexpr(l: *lex::lexer) (node | error) = { export fn parseName(l: *lex::lexer) (node | error) = { match (want(l, [lex::types::NAME])) { - case let t: lex::token => return t.data; + case let t: lex::token => return t.data: node; case => return ("Want failed to read name", 0): error; }; }; export fn parseLit(l: *lex::lexer) (node | error) = { match (want(l, [lex::types::NUM])) { - case let t: lex::token => return strconv::stou64(t.data)!; + case let t: lex::token => return strconv::stou64(t.data)!: node; case => return ("Want failed to read number", 0): error; }; }; - -