aboutsummaryrefslogtreecommitdiff
path: root/src/parse.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.zig')
-rw-r--r--src/parse.zig76
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;