1 const std = @import("std");
2 const ArenaAllocator = std.heap.ArenaAllocator;
3 const Allocator = std.mem.Allocator;
4 const ArrayList = std.ArrayList;
5 const Token = @import("Token.zig");
6 const Parser = @This();
7 const Stmt = @import("stmt.zig").Stmt;
8 const Expr = @import("expr.zig").Expr;
9 const TokenType = @import("token_type.zig").TokenType;
10 const lox = @import("main.zig");
12 arena: ArenaAllocator,
14 tokens: []const Token,
17 pub fn init(child_allocator: Allocator, tokens: []const Token) !Parser {
19 .arena = .init(child_allocator),
20 .allocator = undefined,
25 pub fn deinit(self: *Parser) void {
29 pub fn parse(self: *Parser) ![]const *const Stmt {
30 self.allocator = self.arena.allocator();
32 var statements: ArrayList(*const Stmt) = .empty;
34 while (!self.isAtEnd()) {
35 try statements.append(self.allocator, try self.statement());
38 return statements.toOwnedSlice(self.allocator);
41 fn expression(self: *Parser) (Allocator.Error || std.Io.Writer.Error || error{ParseError})!*const Expr {
42 return self.equality();
45 fn statement(self: *Parser) !*const Stmt {
46 if (self.match(&.{.print})) {
47 return self.printStatement();
50 return self.expressionStatement();
53 fn printStatement(self: *Parser) !*const Stmt {
54 const value = try self.expression();
55 _ = try self.consume(.semicolon, "Expect ';' after value.");
56 const stmt = try self.allocator.create(Stmt);
57 stmt.* = .{ .print = .init(value) };
61 fn expressionStatement(self: *Parser) !*const Stmt {
62 const expr = try self.expression();
63 _ = try self.consume(.semicolon, "Expect ';' after expression.");
64 const stmt = try self.allocator.create(Stmt);
65 stmt.* = .{ .expression = .init(expr) };
69 fn equality(self: *Parser) !*const Expr {
70 var expr = try self.comparison();
72 while (self.match(&.{ .bang_equal, .equal_equal })) {
73 const operator = self.previous();
74 const right = try self.comparison();
75 const binary = try self.allocator.create(Expr);
76 binary.* = .{ .binary = .init(expr, operator, right) };
83 fn comparison(self: *Parser) !*const Expr {
84 var expr = try self.term();
86 while (self.match(&.{ .greater, .greater_equal, .less, .less_equal })) {
87 const operator = self.previous();
88 const right = try self.term();
89 const binary = try self.allocator.create(Expr);
90 binary.* = .{ .binary = .init(expr, operator, right) };
97 fn term(self: *Parser) !*const Expr {
98 var expr = try self.factor();
100 while (self.match(&.{ .plus, .minus })) {
101 const operator = self.previous();
102 const right = try self.factor();
103 const binary = try self.allocator.create(Expr);
104 binary.* = .{ .binary = .init(expr, operator, right) };
111 fn factor(self: *Parser) !*const Expr {
112 var expr = try self.unary();
114 while (self.match(&.{ .slash, .star })) {
115 const operator = self.previous();
116 const right = try self.unary();
117 const binary = try self.allocator.create(Expr);
118 binary.* = .{ .binary = .init(expr, operator, right) };
125 fn unary(self: *Parser) !*const Expr {
126 if (self.match(&.{ .bang, .minus })) {
127 const operator = self.previous();
128 const right = try self.unary();
129 const expr = try self.allocator.create(Expr);
130 expr.* = .{ .unary = .init(operator, right) };
134 return self.primary();
137 fn primary(self: *Parser) !*const Expr {
138 if (self.match(&.{.false})) {
139 const expr = try self.allocator.create(Expr);
140 expr.* = .{ .literal = .init(.{ .boolean = false }) };
144 if (self.match(&.{.true})) {
145 const expr = try self.allocator.create(Expr);
146 expr.* = .{ .literal = .init(.{ .boolean = true }) };
150 if (self.match(&.{.nil})) {
151 const expr = try self.allocator.create(Expr);
152 expr.* = .{ .literal = .init(.{ .nil = {} }) };
156 if (self.match(&.{ .number, .string })) {
157 const expr = try self.allocator.create(Expr);
158 expr.* = .{ .literal = .init(self.previous().literal.?) };
162 if (self.match(&.{.left_paren})) {
163 const expr = try self.expression();
164 _ = try self.consume(.right_paren, "Expect ')' after expression.");
165 const grouping = try self.allocator.create(Expr);
166 grouping.* = .{ .grouping = .init(expr) };
170 try self.err(self.peek(), "Expect expression.");
173 fn match(self: *Parser, types: []const TokenType) bool {
174 for (types) |@"type"| {
175 if (self.check(@"type")) {
184 fn consume(self: *Parser, @"type": TokenType, message: []const u8) !Token {
185 if (self.check(@"type")) return self.advance();
187 try self.err(self.peek(), message);
190 fn check(self: *Parser, @"type": TokenType) bool {
191 if (self.isAtEnd()) return false;
192 return self.peek().type == @"type";
195 fn advance(self: *Parser) Token {
196 if (!self.isAtEnd()) self.current += 1;
197 return self.previous();
200 fn isAtEnd(self: *Parser) bool {
201 return self.peek().type == .eof;
204 fn peek(self: *Parser) Token {
205 return self.tokens[self.current];
208 fn previous(self: *Parser) Token {
209 return self.tokens[self.current - 1];
212 fn err(self: *Parser, token: Token, message: []const u8) !noreturn {
213 try lox.parseError(self.allocator, token, message);
214 return error.ParseError;
217 fn synchronize(self: *Parser) !void {
220 while (!self.isAtEnd()) {
221 if (self.previous().type == .semicolon) return;
223 switch (self.peek().type) {