summary refs log tree commit diff
diff options
context:
space:
mode:
authorBaitinq <manuelpalenzuelamerino@gmail.com>2025-01-06 17:14:21 +0100
committerBaitinq <manuelpalenzuelamerino@gmail.com>2025-01-06 17:14:21 +0100
commitc8373bca8a2de3de516f38e8f703794eeaa0bbb6 (patch)
tree814cba5c6df910d34b2c6ae43c4c92b0a16f2479
parentParser: implement parse_number (diff)
downloadinterpreter-c8373bca8a2de3de516f38e8f703794eeaa0bbb6.tar.gz
interpreter-c8373bca8a2de3de516f38e8f703794eeaa0bbb6.tar.bz2
interpreter-c8373bca8a2de3de516f38e8f703794eeaa0bbb6.zip
Parser: Change grammar and implement print and expression parsing
-rw-r--r--grammar.ebnf2
-rw-r--r--src/parser.zig78
2 files changed, 71 insertions, 9 deletions
diff --git a/grammar.ebnf b/grammar.ebnf
index cc087fe..1423e74 100644
--- a/grammar.ebnf
+++ b/grammar.ebnf
@@ -6,4 +6,4 @@ VariableStatement ::= ("let" IDENTIFIER | IDENTIFIER) EQUALS Expression
 
 PrintStatement :== PRINT LPAREN Expression RPAREN
 
-Expression :== NUMBER | IDENTIFIER | LPAREN Expression RPAREN
+Expression :== NUMBER | IDENTIFIER
diff --git a/src/parser.zig b/src/parser.zig
index c5aa045..5621f6b 100644
--- a/src/parser.zig
+++ b/src/parser.zig
@@ -1,6 +1,10 @@
 const std = @import("std");
 const tokenizer = @import("tokenizer.zig");
 
+const ParserError = error{
+    Error,
+};
+
 const NodeType = enum {
     PROGRAM,
     VARIABLE_STATEMENT,
@@ -40,20 +44,20 @@ pub const Parser = struct {
         });
     }
 
-    pub fn parse(parser: *Parser) !Node {
+    pub fn parse(parser: *Parser) ParserError!Node {
         return parser.parse_program();
     }
 
-    fn parse_program(_: *Parser) !Node {
+    fn parse_program(_: *Parser) ParserError!Node {
         return Node{
             .NUMBER = .{ .value = 9 },
         };
     }
 
-    fn parse_identifier(self: *Parser) !Node {
-        const token = self.peek_token() orelse return error.InvalidArgument;
+    fn parse_identifier(self: *Parser) ParserError!Node {
+        const token = self.peek_token() orelse return ParserError.Error;
 
-        if (token != .IDENTIFIER) return error.InvalidArgument;
+        if (token != .IDENTIFIER) return ParserError.Error;
 
         _ = self.consume_token();
 
@@ -62,10 +66,10 @@ pub const Parser = struct {
         } };
     }
 
-    fn parse_number(self: *Parser) !Node {
-        const token = self.peek_token() orelse return error.InvalidArgument;
+    fn parse_number(self: *Parser) ParserError!Node {
+        const token = self.peek_token() orelse return ParserError.Error;
 
-        if (token != .NUMBER) return error.InvalidArgument;
+        if (token != .NUMBER) return ParserError.Error;
 
         _ = self.consume_token();
 
@@ -74,6 +78,48 @@ pub const Parser = struct {
         } };
     }
 
+    fn parse_print_statement(self: *Parser) ParserError!Node {
+        // print + ( + statement + ) + ;
+
+        var token = self.consume_token() orelse return ParserError.Error;
+
+        if (token != .PRINT) return ParserError.Error;
+
+        token = self.consume_token() orelse return ParserError.Error;
+
+        if (token != .LPAREN) return ParserError.Error;
+
+        const expression = try self.parse_expression();
+
+        token = self.consume_token() orelse return ParserError.Error;
+
+        if (token != .RPAREN) return ParserError.Error;
+
+        token = self.consume_token() orelse return ParserError.Error;
+
+        if (token != .SEMICOLON) return ParserError.Error;
+
+        return Node{
+            .PRINT_STATEMENT = .{
+                .expression = @constCast(&expression), //TODO: Warning ptr
+            },
+        };
+    }
+
+    fn parse_expression(self: *Parser) ParserError!Node {
+        const token = self.peek_token() orelse return ParserError.Error;
+
+        if (token == .NUMBER) {
+            return self.parse_number();
+        } else if (token == .IDENTIFIER) {
+            return self.parse_identifier();
+        } else if (token == .PRINT) {
+            return self.parse_print_statement();
+        } else {
+            return ParserError.Error;
+        }
+    }
+
     fn consume_token(self: *Parser) ?tokenizer.Token {
         if (self.offset >= self.tokens.len) return null;
 
@@ -89,6 +135,22 @@ pub const Parser = struct {
     }
 };
 
+test "parse print" {
+    const tokens: []tokenizer.Token = @constCast(&[_]tokenizer.Token{
+        tokenizer.Token{ .PRINT = void{} },
+        tokenizer.Token{ .LPAREN = void{} },
+        tokenizer.Token{ .NUMBER = 7 },
+        tokenizer.Token{ .RPAREN = void{} },
+        tokenizer.Token{ .SEMICOLON = void{} },
+    });
+    var parser = Parser.init(tokens);
+    const print = try parser.parse_print_statement();
+    //TODO: Warning ptr
+    try std.testing.expectEqualDeep(Node{ .PRINT_STATEMENT = .{ .expression = @constCast(&Node{ .NUMBER = .{
+        .value = 7,
+    } }) } }, print);
+}
+
 test "parse identifier" {
     const tokens: []tokenizer.Token = @constCast(&[_]tokenizer.Token{
         tokenizer.Token{ .IDENTIFIER = @constCast("i") },