diff options
Diffstat (limited to 'src/parse.zig')
-rw-r--r-- | src/parse.zig | 76 |
1 files changed, 52 insertions, 24 deletions
diff --git a/src/parse.zig b/src/parse.zig index 8ceabeb..2149cd7 100644 --- a/src/parse.zig +++ b/src/parse.zig @@ -1,7 +1,31 @@ -pub const Expr = union(enum) { - IntegerLiteral: Token, - BinOp: struct { lhs: *const Expr, op: Token, rhs: *const Expr }, - Invalid: Token, +const std = @import("std"); +const Allocator = std.mem.Allocator; + +const root = @import("root"); +const Lexer = root.Lexer; +const Token = root.Lexer.Token; +const Peekable = root.Peekable; +const peekable = root.peekable; + +pub const Expr = struct { + loc: Lexer.Location, + type: Type, + + pub const Type = union(enum) { + integer_literal, + bin_op: BinOp, + invalid: Token, + + pub const BinOp = struct { + lhs: *const Expr, + rhs: *const Expr, + op: Op, + + const Op = enum { + plus, + }; + }; + }; }; pub fn expression(allocator: Allocator, lexer: *Peekable(Lexer)) error{OutOfMemory}!*Expr { @@ -9,28 +33,41 @@ pub fn expression(allocator: Allocator, lexer: *Peekable(Lexer)) error{OutOfMemo } 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(); + var lhs = try primaryExpr(allocator, lexer); + while (true) { + const token: Lexer.Token = if (lexer.peek()) |t| t else break; + const op: Expr.Type.BinOp.Op = switch (token.type) { + .plus => .plus, + else => break, + }; + + _ = lexer.next(); - const rhs = try primaryExpr(allocator, lexer); - return allocate(allocator, .{ .BinOp = .{ .lhs = lhs, .op = op, .rhs = rhs } }); + const rhs = try primaryExpr(allocator, lexer); + lhs = try allocate(allocator, .{ + .loc = lhs.loc.combine(rhs.loc), + .type = .{ .bin_op = .{ .lhs = lhs, .op = op, .rhs = rhs } }, + }); + } + return lhs; } 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 => { + .left_paren => { const res = expression(allocator, lexer); const right_paren = lexer.next().?; - if (right_paren.type != .RightParen) - return allocate(allocator, .{ .Invalid = right_paren }); + if (right_paren.type != .right_paren) + return allocate(allocator, .{ + .loc = right_paren.loc, + .type = .{ .invalid = right_paren }, + }); return res; }, - .IntegerLiteral => .{ .IntegerLiteral = token }, - else => .{ .Invalid = token }, + .integer_literal => .{ .loc = token.loc, .type = .integer_literal }, + else => .{ .loc = token.loc, .type = .{ .invalid = token } }, }); } @@ -39,12 +76,3 @@ fn allocate(allocator: Allocator, expr: Expr) !*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; |