]> Repositories - zlox.git/blobdiff - src/Parser.zig
Implement print and expression statements
[zlox.git] / src / Parser.zig
index a584c3ff71f7eebcb5abba1c60a106d43fba5311..1eb1b9e751ac27843d1c0007ca369f73dc301fd2 100644 (file)
@@ -1,8 +1,10 @@
 const std = @import("std");
 const ArenaAllocator = std.heap.ArenaAllocator;
 const Allocator = std.mem.Allocator;
 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 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");
 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();
 }
 
     self.arena.deinit();
 }
 
-pub fn parse(self: *Parser) !?*Expr {
+pub fn parse(self: *Parser) ![]const *const Stmt {
     self.allocator = self.arena.allocator();
 
     self.allocator = self.arena.allocator();
 
-    return self.expression() catch |err| switch (err) {
-        error.ParseError => return null,
-        else => return err,
-    };
+    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();
 }
 
     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 })) {
     var expr = try self.comparison();
 
     while (self.match(&.{ .bang_equal, .equal_equal })) {
@@ -51,7 +80,7 @@ fn equality(self: *Parser) !*Expr {
     return 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 })) {
     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;
 }
 
     return expr;
 }
 
-fn term(self: *Parser) !*Expr {
+fn term(self: *Parser) !*const Expr {
     var expr = try self.factor();
 
     while (self.match(&.{ .plus, .minus })) {
     var expr = try self.factor();
 
     while (self.match(&.{ .plus, .minus })) {
@@ -79,7 +108,7 @@ fn term(self: *Parser) !*Expr {
     return expr;
 }
 
     return expr;
 }
 
-fn factor(self: *Parser) !*Expr {
+fn factor(self: *Parser) !*const Expr {
     var expr = try self.unary();
 
     while (self.match(&.{ .slash, .star })) {
     var expr = try self.unary();
 
     while (self.match(&.{ .slash, .star })) {
@@ -93,7 +122,7 @@ fn factor(self: *Parser) !*Expr {
     return 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();
     if (self.match(&.{ .bang, .minus })) {
         const operator = self.previous();
         const right = try self.unary();
@@ -102,10 +131,10 @@ fn unary(self: *Parser) !*Expr {
         return expr;
     }
 
         return expr;
     }
 
-    return try self.primary();
+    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 }) };
     if (self.match(&.{.false})) {
         const expr = try self.allocator.create(Expr);
         expr.* = .{ .literal = .init(.{ .boolean = false }) };
@@ -138,7 +167,7 @@ fn primary(self: *Parser) !*Expr {
         return grouping;
     }
 
         return grouping;
     }
 
-    try self.@"error"(self.peek(), "Expect expression.");
+    try self.err(self.peek(), "Expect expression.");
 }
 
 fn match(self: *Parser, types: []const TokenType) bool {
 }
 
 fn match(self: *Parser, types: []const TokenType) bool {
@@ -155,7 +184,7 @@ fn match(self: *Parser, types: []const TokenType) bool {
 fn consume(self: *Parser, @"type": TokenType, message: []const u8) !Token {
     if (self.check(@"type")) return self.advance();
 
 fn consume(self: *Parser, @"type": TokenType, message: []const u8) !Token {
     if (self.check(@"type")) return self.advance();
 
-    try self.@"error"(self.peek(), message);
+    try self.err(self.peek(), message);
 }
 
 fn check(self: *Parser, @"type": TokenType) bool {
 }
 
 fn check(self: *Parser, @"type": TokenType) bool {
@@ -180,8 +209,8 @@ fn previous(self: *Parser) Token {
     return self.tokens[self.current - 1];
 }
 
     return self.tokens[self.current - 1];
 }
 
-fn @"error"(self: *Parser, token: Token, message: []const u8) !noreturn {
-    try lox.parse_error(self.allocator, token, message);
+fn err(self: *Parser, token: Token, message: []const u8) !noreturn {
+    try lox.parseError(self.allocator, token, message);
     return error.ParseError;
 }
 
     return error.ParseError;
 }