aboutsummaryrefslogtreecommitdiff
path: root/src/parse.zig
diff options
context:
space:
mode:
authorMathias Magnusson <mathias@magnusson.space>2025-05-28 23:00:32 +0200
committerMathias Magnusson <mathias@magnusson.space>2025-05-28 23:00:32 +0200
commit7b85276fc98643b1138df6f322b8bd657339ea96 (patch)
tree3d36e1d4961f92caa0fe0e00bb8e27a0fd1242b5 /src/parse.zig
downloadhuginn-7b85276fc98643b1138df6f322b8bd657339ea96.tar.gz
initial commit
Diffstat (limited to 'src/parse.zig')
-rw-r--r--src/parse.zig50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/parse.zig b/src/parse.zig
new file mode 100644
index 0000000..8ceabeb
--- /dev/null
+++ b/src/parse.zig
@@ -0,0 +1,50 @@
+pub const Expr = union(enum) {
+ IntegerLiteral: Token,
+ BinOp: struct { lhs: *const Expr, op: Token, rhs: *const Expr },
+ Invalid: Token,
+};
+
+pub fn expression(allocator: Allocator, lexer: *Peekable(Lexer)) error{OutOfMemory}!*Expr {
+ return addExpr(allocator, lexer);
+}
+
+pub fn addExpr(allocator: Allocator, lexer: *Peekable(Lexer)) !*Expr {
+ const lhs = try primaryExpr(allocator, lexer);
+ const token: ?Lexer.Token = lexer.peek();
+ const op = (if (token) |t| if (t.type == .Plus) t else null else null) orelse return lhs;
+ _ = lexer.next();
+
+ const rhs = try primaryExpr(allocator, lexer);
+ return allocate(allocator, .{ .BinOp = .{ .lhs = lhs, .op = op, .rhs = rhs } });
+}
+
+pub fn primaryExpr(allocator: Allocator, lexer: *Peekable(Lexer)) !*Expr {
+ const token = lexer.next().?;
+ // std.debug.print("term {}\n", .{token});
+ return allocate(allocator, switch (token.type) {
+ .LeftParen => {
+ const res = expression(allocator, lexer);
+ const right_paren = lexer.next().?;
+ if (right_paren.type != .RightParen)
+ return allocate(allocator, .{ .Invalid = right_paren });
+ return res;
+ },
+ .IntegerLiteral => .{ .IntegerLiteral = token },
+ else => .{ .Invalid = token },
+ });
+}
+
+fn allocate(allocator: Allocator, expr: Expr) !*Expr {
+ const res = try allocator.create(Expr);
+ res.* = expr;
+ return res;
+}
+
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+
+const Lexer = @import("./lexer.zig");
+const Token = Lexer.Token;
+const root = @import("root");
+const Peekable = root.Peekable;
+const peekable = root.peekable;