diff options
author | Mathias Magnusson <mathias@magnusson.space> | 2025-06-02 15:17:22 +0200 |
---|---|---|
committer | Mathias Magnusson <mathias@magnusson.space> | 2025-06-02 15:17:22 +0200 |
commit | a39f75cae1d74d89efc0a871bba953c1f1af3b1b (patch) | |
tree | d7ff616ba70aea4424d93be17c885e202904ce8e /src/parse.zig | |
parent | 939ee7606fbfe3afa6b6a008fb617120a6dd8114 (diff) | |
download | huginn-a39f75cae1d74d89efc0a871bba953c1f1af3b1b.tar.gz |
add statements ending in ; and allow parsing multiple of them
Diffstat (limited to 'src/parse.zig')
-rw-r--r-- | src/parse.zig | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/src/parse.zig b/src/parse.zig index 901ce0d..1dda517 100644 --- a/src/parse.zig +++ b/src/parse.zig @@ -5,6 +5,15 @@ const root = @import("root"); const Lexer = root.Lexer; const Token = root.Lexer.Token; +pub const Stmt = struct { + loc: Lexer.Location, + type: Type, + + pub const Type = union(enum) { + expr: *const Expr, + }; +}; + pub const Expr = struct { loc: Lexer.Location, type: Type, @@ -12,7 +21,6 @@ pub const Expr = struct { pub const Type = union(enum) { integer_literal, bin_op: BinOp, - invalid: Token, call: Call, identifier, @@ -48,14 +56,30 @@ pub const Expr = struct { switch (self.type) { .integer_literal => try writer.print("<int>", .{}), .bin_op => |bin_op| try writer.print("({} {} {})", .{ bin_op.lhs, bin_op.op, bin_op.rhs }), - .invalid => try writer.print("<invalid>", .{}), .call => |call| try writer.print("({} {})", .{ call.proc, call.arg }), .identifier => try writer.print("<identifier>", .{}), } } }; -pub fn expression(allocator: Allocator, lexer: *Lexer) error{OutOfMemory}!*Expr { +pub fn statements(allocator: Allocator, lexer: *Lexer) ![]Stmt { + var stmts: std.ArrayList(Stmt) = .init(allocator); + while (lexer.peek().type != .eof) { + try stmts.append(try statement(allocator, lexer)); + } + return try stmts.toOwnedSlice(); +} + +pub fn statement(allocator: Allocator, lexer: *Lexer) !Stmt { + var expr = try expression(allocator, lexer); + const semicolon: Lexer.Token = if (lexer.peek().type == .semicolon) lexer.next() else return error.ExpectedSemicolon; + return .{ + .loc = expr.loc.combine(semicolon.loc), + .type = .{ .expr = expr }, + }; +} + +pub fn expression(allocator: Allocator, lexer: *Lexer) error{ OutOfMemory, ExpectedRightParen, UnexpectedToken }!*Expr { return addExpr(allocator, lexer); } @@ -70,7 +94,7 @@ pub fn addExpr(allocator: Allocator, lexer: *Lexer) !*Expr { _ = lexer.next(); const rhs = try callExpr(allocator, lexer); - lhs = try allocate(allocator, .{ + lhs = try allocate(Expr, allocator, .{ .loc = lhs.loc.combine(rhs.loc), .type = .{ .bin_op = .{ .lhs = lhs, .op = op, .rhs = rhs } }, }); @@ -82,11 +106,11 @@ pub fn callExpr(allocator: Allocator, lexer: *Lexer) !*Expr { var proc = try primaryExpr(allocator, lexer); while (true) { switch (lexer.peek().type) { - .left_paren, .integer_literal => {}, + .left_paren, .integer_literal, .identifier => {}, else => break, } const arg = try primaryExpr(allocator, lexer); - proc = try allocate(allocator, .{ + proc = try allocate(Expr, allocator, .{ .loc = proc.loc.combine(arg.loc), .type = .{ .call = .{ .proc = proc, .arg = arg } }, }); @@ -97,25 +121,25 @@ pub fn callExpr(allocator: Allocator, lexer: *Lexer) !*Expr { pub fn primaryExpr(allocator: Allocator, lexer: *Lexer) !*Expr { const token = lexer.next(); // std.debug.print("term {}\n", .{token}); - return allocate(allocator, switch (token.type) { + return allocate(Expr, allocator, switch (token.type) { .left_paren => { const res = expression(allocator, lexer); const right_paren = lexer.next(); if (right_paren.type != .right_paren) - return allocate(allocator, .{ - .loc = right_paren.loc, - .type = .{ .invalid = right_paren }, - }); + return error.ExpectedRightParen; return res; }, .integer_literal => .{ .loc = token.loc, .type = .integer_literal }, .identifier => .{ .loc = token.loc, .type = .identifier }, - else => .{ .loc = token.loc, .type = .{ .invalid = token } }, + else => |t| { + std.debug.print("Expected '(', integer literal, or identifier. Got {}\n", .{t}); + return error.UnexpectedToken; + }, }); } -fn allocate(allocator: Allocator, expr: Expr) !*Expr { - const res = try allocator.create(Expr); - res.* = expr; +fn allocate(T: type, allocator: Allocator, t: T) !*T { + const res = try allocator.create(T); + res.* = t; return res; } |