X-Git-Url: https://git.ayoreis.com/zlox.git/blobdiff_plain/af5a4d8d95bf091ac4139094ed27265fe04a2634..refs/heads/main:/src/Parser.zig?ds=sidebyside diff --git a/src/Parser.zig b/src/Parser.zig index 7b5a311..1eb1b9e 100644 --- a/src/Parser.zig +++ b/src/Parser.zig @@ -1,8 +1,10 @@ const std = @import("std"); const ArenaAllocator = std.heap.ArenaAllocator; const Allocator = std.mem.Allocator; +const ArrayList = std.ArrayList; const Token = @import("Token.zig"); const Parser = @This(); +const Stmt = @import("stmt.zig").Stmt; const Expr = @import("expr.zig").Expr; const TokenType = @import("token_type.zig").TokenType; const lox = @import("main.zig"); @@ -24,20 +26,47 @@ pub fn deinit(self: *Parser) void { self.arena.deinit(); } -pub fn parse(self: *Parser) !?*Expr { +pub fn parse(self: *Parser) ![]const *const Stmt { self.allocator = self.arena.allocator(); - return self.expression() catch |err2| switch (err2) { - error.ParseError => return null, - else => return err2, - }; + var statements: ArrayList(*const Stmt) = .empty; + + while (!self.isAtEnd()) { + try statements.append(self.allocator, try self.statement()); + } + + return statements.toOwnedSlice(self.allocator); } -fn expression(self: *Parser) (Allocator.Error || std.Io.Writer.Error || error{ParseError})!*Expr { +fn expression(self: *Parser) (Allocator.Error || std.Io.Writer.Error || error{ParseError})!*const Expr { return self.equality(); } -fn equality(self: *Parser) !*Expr { +fn statement(self: *Parser) !*const Stmt { + if (self.match(&.{.print})) { + return self.printStatement(); + } + + return self.expressionStatement(); +} + +fn printStatement(self: *Parser) !*const Stmt { + const value = try self.expression(); + _ = try self.consume(.semicolon, "Expect ';' after value."); + const stmt = try self.allocator.create(Stmt); + stmt.* = .{ .print = .init(value) }; + return stmt; +} + +fn expressionStatement(self: *Parser) !*const Stmt { + const expr = try self.expression(); + _ = try self.consume(.semicolon, "Expect ';' after expression."); + const stmt = try self.allocator.create(Stmt); + stmt.* = .{ .expression = .init(expr) }; + return stmt; +} + +fn equality(self: *Parser) !*const Expr { var expr = try self.comparison(); while (self.match(&.{ .bang_equal, .equal_equal })) { @@ -51,7 +80,7 @@ fn equality(self: *Parser) !*Expr { return expr; } -fn comparison(self: *Parser) !*Expr { +fn comparison(self: *Parser) !*const Expr { var expr = try self.term(); while (self.match(&.{ .greater, .greater_equal, .less, .less_equal })) { @@ -65,7 +94,7 @@ fn comparison(self: *Parser) !*Expr { return expr; } -fn term(self: *Parser) !*Expr { +fn term(self: *Parser) !*const Expr { var expr = try self.factor(); while (self.match(&.{ .plus, .minus })) { @@ -79,7 +108,7 @@ fn term(self: *Parser) !*Expr { return expr; } -fn factor(self: *Parser) !*Expr { +fn factor(self: *Parser) !*const Expr { var expr = try self.unary(); while (self.match(&.{ .slash, .star })) { @@ -93,7 +122,7 @@ fn factor(self: *Parser) !*Expr { return expr; } -fn unary(self: *Parser) !*Expr { +fn unary(self: *Parser) !*const Expr { if (self.match(&.{ .bang, .minus })) { const operator = self.previous(); const right = try self.unary(); @@ -105,7 +134,7 @@ fn unary(self: *Parser) !*Expr { return self.primary(); } -fn primary(self: *Parser) !*Expr { +fn primary(self: *Parser) !*const Expr { if (self.match(&.{.false})) { const expr = try self.allocator.create(Expr); expr.* = .{ .literal = .init(.{ .boolean = false }) };