summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ast/ast.odin49
-rw-r--r--parser/parser.odin51
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)
}
-