diff options
| author | Ibrahim Muftee <ibrahim@muftee.net> | 2026-07-24 16:11:27 -0500 |
|---|---|---|
| committer | Ibrahim Muftee <ibrahim@muftee.net> | 2026-07-24 16:11:49 -0500 |
| commit | 9d18f62407bec90f95919356bfd6711c7ba7923c (patch) | |
| tree | 8e635c276b64c687fe6816dc838852d0409e2a30 | |
| parent | e5ab0622364911a8a7364689d3b59e856a6c09e9 (diff) | |
| -rw-r--r-- | ast/ast.odin | 49 | ||||
| -rw-r--r-- | parser/parser.odin | 51 |
2 files changed, 75 insertions, 25 deletions
diff --git a/ast/ast.odin b/ast/ast.odin index 67039a3..8007e54 100644 --- a/ast/ast.odin +++ b/ast/ast.odin @@ -1,6 +1,9 @@ package ast import "../token" +import "core:bytes" + +THIRTY_TWO_KILOBYTES := 262144 Node :: union { Program, @@ -28,6 +31,11 @@ Return_Statement :: struct { return_value: Expression, } +Expression_Statement :: struct { + token: token.Token, + expression: Expression, +} + Expression :: union { Identifier, } @@ -51,6 +59,8 @@ token_literal :: proc(node: Node) -> (literal: string) { literal = token.literal(s.token) case Return_Statement: literal = token.literal(s.token) + case Expression_Statement: + literal = token.literal(s.token) } case Expression: switch e in n { @@ -60,3 +70,42 @@ token_literal :: proc(node: Node) -> (literal: string) { } return literal } + +node_to_string :: proc(node: Node) -> string { + out: bytes.Buffer + bytes.buffer_init_allocator(&out, 4, THIRTY_TWO_KILOBYTES, context.temp_allocator) + + switch n in node { + case Program: + for stmt in n { + bytes.buffer_write_string(&out, node_to_string(n)) + } + case Statement: + switch s in n { + case Let_Statement: + bytes.buffer_write_string(&out, token.literal(s.token) + " ") + bytes.buffer_write_string(&out, node_to_string(s.name)) + bytes.buffer_write_string(&out, " = ") + if s.value != nil { + bytes.buffer_write_string(&out, node_to_string(s.value)) + } + bytes.buffer_write_string(&out, ";") + case Return_Statement: + bytes.buffer_write_string(&out, token.literal(s.token) + " ") + if s.return_value != nil { + bytes.buffer_write_string(&out, node_to_string(s.return_value)) + } + case Expression_Statement: + if s.expression != nil { + bytes.buffer_write_string(&out, node_to_string(s.expression)) + } + } + case Expression: + switch e in n { + case Identifier: + literal = token.literal(e.token) + } + } + + return bytes.buffer_to_string(&out) +} diff --git a/parser/parser.odin b/parser/parser.odin index 289ba1f..f3efbd5 100644 --- a/parser/parser.odin +++ b/parser/parser.odin @@ -14,6 +14,7 @@ Parser :: struct { errors: [dynamic]string, } + new :: proc(l: ^lexer.Lexer) -> Parser { p := Parser{l, token.Illegal{}, token.Illegal{}, make([dynamic]string, context.temp_allocator)} next_token(&p) @@ -21,8 +22,29 @@ new :: proc(l: ^lexer.Lexer) -> Parser { return p } -errors :: proc(p: ^Parser) -> []string { - return p.errors[:] +next_token :: proc(p: ^Parser) { + p.cur_token = p.peek_token + p.peek_token = lexer.next_token(p.l) +} + +cur_token_is :: proc(p: ^Parser, $T: typeid) -> bool { + _, ok := p.cur_token.(T) + return ok +} + +peek_token_is :: proc(p: ^Parser, $T: typeid) -> bool { + _, ok := p.peek_token.(T) + return ok +} + +expect_peek :: proc(p: ^Parser, $T: typeid) -> bool { + if peek_token_is(p, T) { + next_token(p) + return true + } else { + peek_error(p, T) + return false + } } peek_error :: proc(p: ^Parser, $T: typeid) { @@ -30,9 +52,8 @@ peek_error :: proc(p: ^Parser, $T: typeid) { append(&p.errors, msg) } -next_token :: proc(p: ^Parser) { - p.cur_token = p.peek_token - p.peek_token = lexer.next_token(p.l) +errors :: proc(p: ^Parser) -> []string { + return p.errors[:] } parse_program :: proc(p: ^Parser) -> ast.Program { @@ -91,25 +112,6 @@ parse_return_statement :: proc(p: ^Parser) -> (stmt: ast.Return_Statement, ok: b return } -cur_token_is :: proc(p: ^Parser, $T: typeid) -> bool { - _, ok := p.cur_token.(T) - return ok -} - -peek_token_is :: proc(p: ^Parser, $T: typeid) -> bool { - _, ok := p.peek_token.(T) - return ok -} - -expect_peek :: proc(p: ^Parser, $T: typeid) -> bool { - if peek_token_is(p, T) { - next_token(p) - return true - } else { - peek_error(p, T) - return false - } -} @(test) test_let_statements :: proc(t: ^testing.T) { @@ -179,4 +181,3 @@ check_parse_errors :: proc(t: ^testing.T, p: ^Parser) { testing.fail_now(t) } - |
