diff options
Diffstat (limited to 'src/parse.zig')
-rw-r--r-- | src/parse.zig | 50 |
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; |