summary refs log tree commit diff
path: root/src/parser.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.zig')
-rw-r--r--src/parser.zig138
1 files changed, 70 insertions, 68 deletions
diff --git a/src/parser.zig b/src/parser.zig
index 966cad3..c5eb623 100644
--- a/src/parser.zig
+++ b/src/parser.zig
@@ -6,23 +6,7 @@ const ParserError = error{
     OutOfMemory,
 };
 
-const NodeType = enum {
-    PROGRAM,
-    STATEMENT,
-    ASSIGNMENT_STATEMENT,
-    FUNCTION_CALL_STATEMENT,
-    IF_STATEMENT,
-    WHILE_STATEMENT,
-    EQUALITY_EXPRESSION,
-    ADDITIVE_EXPRESSION,
-    MULTIPLICATIVE_EXPRESSION,
-    UNARY_EXPRESSION,
-    PRIMARY_EXPRESSION,
-    FUNCTION_DEFINITION,
-    RETURN_STATEMENT,
-};
-
-pub const Node = union(NodeType) {
+pub const Node = union(enum) {
     PROGRAM: struct {
         statements: []*Node,
     },
@@ -35,7 +19,7 @@ pub const Node = union(NodeType) {
         expression: *Node,
     },
     FUNCTION_CALL_STATEMENT: struct {
-        name: []const u8,
+        expression: *Node,
         arguments: []*Node,
     },
     IF_STATEMENT: struct {
@@ -74,9 +58,6 @@ pub const Node = union(NodeType) {
         IDENTIFIER: struct {
             name: []const u8,
         },
-        FUNCTION_CALL: struct {
-            name: []const u8,
-        },
     },
     FUNCTION_DEFINITION: struct {
         statements: []*Node,
@@ -91,16 +72,16 @@ pub const Parser = struct {
     tokens: []tokenizer.Token,
     offset: u32,
 
-    allocator: std.mem.Allocator,
+    arena: std.mem.Allocator,
 
     try_context: bool, //TODO: I dont like this
 
-    pub fn init(tokens: []tokenizer.Token, arena_allocator: *std.heap.ArenaAllocator) ParserError!*Parser {
-        const parser = try arena_allocator.allocator().create(Parser);
+    pub fn init(tokens: []tokenizer.Token, arena_allocator: std.mem.Allocator) ParserError!*Parser {
+        const parser = try arena_allocator.create(Parser);
         parser.* = .{
             .tokens = tokens,
             .offset = 0,
-            .allocator = arena_allocator.allocator(),
+            .arena = arena_allocator,
             .try_context = false,
         };
         return parser;
@@ -112,7 +93,7 @@ pub const Parser = struct {
 
     // Program ::= Statement+
     fn parse_program(self: *Parser) !*Node {
-        var nodes = std.ArrayList(*Node).init(self.allocator);
+        var nodes = std.ArrayList(*Node).init(self.arena);
         while (self.offset < self.tokens.len) {
             try nodes.append(@constCast(try self.parse_statement()));
         }
@@ -124,7 +105,7 @@ pub const Parser = struct {
 
     // Statement    ::= (AssignmentStatement | FunctionCallStatement | IfStatement | WhileStatement | ReturnStatement) SEMICOLON
     fn parse_statement(self: *Parser) ParserError!*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing statement\n", .{});
+        errdefer if (!self.try_context) std.debug.print("Error parsing statement {any}\n", .{self.peek_token()});
 
         const statement = self.accept_parse(parse_function_call_statement) orelse
             self.accept_parse(parse_if_statement) orelse
@@ -143,7 +124,7 @@ pub const Parser = struct {
 
     // AssignmentStatement ::= "let" IDENTIFIER EQUALS Expression
     fn parse_assignment_statement(self: *Parser) ParserError!*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing assignment statement\n", .{});
+        errdefer if (!self.try_context) std.debug.print("Error parsing assignment statement {any}\n", .{self.peek_token()});
 
         var is_declaration: bool = false;
         if (self.accept_token(.LET) != null) {
@@ -159,17 +140,20 @@ pub const Parser = struct {
         return self.create_node(.{
             .ASSIGNMENT_STATEMENT = .{
                 .is_declaration = is_declaration,
-                .name = try self.allocator.dupe(u8, identifier.IDENTIFIER),
+                .name = try self.arena.dupe(u8, identifier.type.IDENTIFIER),
                 .expression = @constCast(expression),
             },
         });
     }
 
-    // FunctionCallStatement ::= IDENTIFIER LPAREN FunctionArguments? RPAREN
+    // FunctionCallStatement ::= (IDENTIFIER | FunctionDefinition) LPAREN FunctionArguments? RPAREN
     fn parse_function_call_statement(self: *Parser) ParserError!*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing function call statement\n", .{});
+        errdefer if (!self.try_context) std.debug.print("Error parsing function call statement {any}\n", .{self.peek_token()});
 
-        const identifier = try self.parse_token(tokenizer.TokenType.IDENTIFIER);
+        const identifier = self.accept_token(tokenizer.TokenType.IDENTIFIER);
+        const fn_def = self.accept_parse(parse_function_definition);
+
+        if (identifier == null and fn_def == null) return ParserError.ParsingError;
 
         _ = try self.parse_token(tokenizer.TokenType.LPAREN);
 
@@ -177,16 +161,30 @@ pub const Parser = struct {
 
         _ = try self.parse_token(tokenizer.TokenType.RPAREN);
 
+        if (fn_def != null) {
+            return self.create_node(.{ .FUNCTION_CALL_STATEMENT = .{
+                .expression = fn_def.?,
+                .arguments = arguments,
+            } });
+        }
+
         return self.create_node(.{ .FUNCTION_CALL_STATEMENT = .{
-            .name = try self.allocator.dupe(u8, identifier.IDENTIFIER),
+            .expression = try self.create_node(.{
+                .PRIMARY_EXPRESSION = .{
+                    .IDENTIFIER = .{
+                        .name = try self.arena.dupe(u8, identifier.?.type.IDENTIFIER),
+                    },
+                },
+            }),
             .arguments = arguments,
         } });
     }
 
     // FunctionArguments ::= Expression ("," Expression)*
     fn parse_function_arguments(self: *Parser) ParserError![]*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing function arguments\n", .{});
-        var node_list = std.ArrayList(*Node).init(self.allocator);
+        errdefer if (!self.try_context) std.debug.print("Error parsing function arguments {any}\n", .{self.peek_token()});
+
+        var node_list = std.ArrayList(*Node).init(self.arena);
 
         var first = true;
         while (true) {
@@ -203,7 +201,7 @@ pub const Parser = struct {
 
     // IfStatement ::= "if" Expression LBRACE Statement* RBRACE
     fn parse_if_statement(self: *Parser) ParserError!*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing if statement\n", .{});
+        errdefer if (!self.try_context) std.debug.print("Error parsing if statement {any}\n", .{self.peek_token()});
 
         _ = try self.parse_token(tokenizer.TokenType.IF);
 
@@ -211,7 +209,7 @@ pub const Parser = struct {
 
         _ = try self.parse_token(tokenizer.TokenType.LBRACE);
 
-        var statements = std.ArrayList(*Node).init(self.allocator);
+        var statements = std.ArrayList(*Node).init(self.arena);
         while (self.accept_parse(parse_statement)) |expr| {
             try statements.append(expr);
         }
@@ -226,7 +224,7 @@ pub const Parser = struct {
 
     // WhileStatement ::= "while" Expression LBRACE Statement* RBRACE
     fn parse_while_statement(self: *Parser) ParserError!*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing while statement\n", .{});
+        errdefer if (!self.try_context) std.debug.print("Error parsing while statement {any}\n", .{self.peek_token()});
 
         _ = try self.parse_token(tokenizer.TokenType.WHILE);
 
@@ -234,7 +232,7 @@ pub const Parser = struct {
 
         _ = try self.parse_token(tokenizer.TokenType.LBRACE);
 
-        var statements = std.ArrayList(*Node).init(self.allocator);
+        var statements = std.ArrayList(*Node).init(self.arena);
         while (self.accept_parse(parse_statement)) |expr| {
             try statements.append(expr);
         }
@@ -247,19 +245,18 @@ pub const Parser = struct {
         } });
     }
 
-    // Expression   ::= EqualityExpression | AdditiveExpression | FunctionDefinition
+    // Expression ::= EqualityExpression | AdditiveExpression
     fn parse_expression(self: *Parser) ParserError!*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing expression\n", .{});
+        errdefer if (!self.try_context) std.debug.print("Error parsing expression {any}\n", .{self.peek_token()});
 
         return self.accept_parse(parse_equality_expression) orelse
-            self.accept_parse(parse_function_definition) orelse
             self.accept_parse(parse_additive_expression) orelse
             return ParserError.ParsingError;
     }
 
     // EqualityExpression ::= AdditiveExpression "==" AdditiveExpression
     fn parse_equality_expression(self: *Parser) ParserError!*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing equality expression\n", .{});
+        errdefer if (!self.try_context) std.debug.print("Error parsing equality expression {any}\n", .{self.peek_token()});
 
         const lhs = try self.parse_additive_expression();
 
@@ -276,7 +273,7 @@ pub const Parser = struct {
 
     // AdditiveExpression ::= MultiplicativeExpression (("+" | "-") MultiplicativeExpression)*
     fn parse_additive_expression(self: *Parser) ParserError!*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing additive expression\n", .{});
+        errdefer if (!self.try_context) std.debug.print("Error parsing additive expression {any}\n", .{self.peek_token()});
 
         var lhs = try self.parse_multiplicative_expression();
 
@@ -300,7 +297,7 @@ pub const Parser = struct {
 
     // MultiplicativeExpression ::= UnaryExpression (("*" | "/") UnaryExpression)*
     fn parse_multiplicative_expression(self: *Parser) ParserError!*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing additive expression\n", .{});
+        errdefer if (!self.try_context) std.debug.print("Error parsing additive expression {any}\n", .{self.peek_token()});
 
         var lhs = try self.parse_unary_expression();
 
@@ -322,37 +319,40 @@ pub const Parser = struct {
         return lhs;
     }
 
-    // UnaryExpression ::= "!" UnaryExpression | PrimaryExpression
+    // UnaryExpression ::= ("!" | "-") UnaryExpression | PrimaryExpression
     fn parse_unary_expression(self: *Parser) ParserError!*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing unary expression\n", .{});
+        errdefer if (!self.try_context) std.debug.print("Error parsing unary expression {any}\n", .{self.peek_token()});
 
-        const negation = self.accept_token(tokenizer.TokenType.BANG) != null;
+        const not = self.accept_token(tokenizer.TokenType.BANG) != null;
+        const minus = self.accept_token(tokenizer.TokenType.MINUS) != null;
 
-        if (!negation) {
+        if (!not and !minus) {
             return try self.parse_primary_expression();
         }
 
         return self.create_node(.{ .UNARY_EXPRESSION = .{
-            .negation = negation,
+            .negation = not,
             .expression = try self.parse_unary_expression(),
         } });
     }
 
-    // PrimaryExpression ::= NUMBER | BOOLEAN | IDENTIFIER | FunctionCallStatement | LPAREN Expression RPAREN
+    // PrimaryExpression ::= NUMBER | BOOLEAN | IDENTIFIER | FunctionCallStatement | FunctionDefinition | LPAREN Expression RPAREN
     fn parse_primary_expression(self: *Parser) ParserError!*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing primary expression\n", .{});
+        errdefer if (!self.try_context) std.debug.print("Error parsing primary expression {any}\n", .{self.peek_token()});
 
+        if (self.accept_parse(parse_function_call_statement)) |stmt| return stmt;
+        if (self.accept_parse(parse_function_definition)) |stmt| return stmt;
+
+        // LPAREN (Expression) RPAREN
         if (self.accept_token(tokenizer.TokenType.LPAREN)) |_| {
             const expr = try self.parse_expression();
             _ = try self.parse_token(tokenizer.TokenType.RPAREN);
             return expr;
         }
 
-        if (self.accept_parse(parse_function_call_statement)) |stmt| return stmt;
-
         const token = self.consume_token() orelse return ParserError.ParsingError;
 
-        return switch (token) {
+        return switch (token.type) {
             .NUMBER => |number_token| try self.create_node(.{
                 .PRIMARY_EXPRESSION = .{
                     .NUMBER = .{
@@ -368,7 +368,7 @@ pub const Parser = struct {
             .IDENTIFIER => |identifier_token| try self.create_node(.{
                 .PRIMARY_EXPRESSION = .{
                     .IDENTIFIER = .{
-                        .name = try self.allocator.dupe(u8, identifier_token),
+                        .name = try self.arena.dupe(u8, identifier_token),
                     },
                 },
             }),
@@ -378,7 +378,7 @@ pub const Parser = struct {
 
     // FunctionDefinition ::= LPAREN FunctionParamters? RPAREN ARROW LBRACE Statement* ReturnStatement RBRACE
     fn parse_function_definition(self: *Parser) ParserError!*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing function definition\n", .{});
+        errdefer if (!self.try_context) std.debug.print("Error parsing function definition {any}\n", .{self.peek_token()});
 
         _ = try self.parse_token(tokenizer.TokenType.LPAREN);
 
@@ -389,12 +389,12 @@ pub const Parser = struct {
         _ = try self.parse_token(tokenizer.TokenType.ARROW);
         _ = try self.parse_token(tokenizer.TokenType.LBRACE);
 
-        var nodes = std.ArrayList(*Node).init(self.allocator);
+        var nodes = std.ArrayList(*Node).init(self.arena);
         while (self.accept_parse(parse_statement)) |expression| {
             try nodes.append(expression);
         }
 
-        std.debug.assert(nodes.getLast().STATEMENT.statement.* == .RETURN_STATEMENT);
+        if (nodes.items.len == 0 or nodes.getLast().STATEMENT.statement.* != .RETURN_STATEMENT) return ParserError.ParsingError;
 
         _ = try self.parse_token(tokenizer.TokenType.RBRACE);
 
@@ -406,8 +406,9 @@ pub const Parser = struct {
 
     // FunctionParameters ::= IDENTIFIER ("," IDENTIFIER)*
     fn parse_function_parameters(self: *Parser) ParserError![]*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing function parameters\n", .{});
-        var node_list = std.ArrayList(*Node).init(self.allocator);
+        errdefer if (!self.try_context) std.debug.print("Error parsing function parameters {any}\n", .{self.peek_token()});
+
+        var node_list = std.ArrayList(*Node).init(self.arena);
 
         var first = true;
         while (true) {
@@ -420,7 +421,7 @@ pub const Parser = struct {
             try node_list.append(try self.create_node(.{
                 .PRIMARY_EXPRESSION = .{
                     .IDENTIFIER = .{
-                        .name = try self.allocator.dupe(u8, ident.IDENTIFIER),
+                        .name = try self.arena.dupe(u8, ident.type.IDENTIFIER),
                     },
                 },
             }));
@@ -431,7 +432,8 @@ pub const Parser = struct {
 
     // ReturnStatement ::= RETURN Expression
     fn parse_return_statement(self: *Parser) ParserError!*Node {
-        errdefer if (!self.try_context) std.debug.print("Error parsing return statement\n", .{});
+        errdefer if (!self.try_context) std.debug.print("Error parsing return statement {any}\n", .{self.peek_token()});
+
         _ = try self.parse_token(tokenizer.TokenType.RETURN);
 
         const expression = try self.parse_expression();
@@ -443,11 +445,11 @@ pub const Parser = struct {
         });
     }
 
-    fn parse_token(self: *Parser, expected_token: tokenizer.TokenType) ParserError!tokenizer.Token {
+    fn parse_token(self: *Parser, expected_token: std.meta.Tag(tokenizer.TokenType)) ParserError!tokenizer.Token {
         errdefer if (!self.try_context) std.debug.print("Error accepting token: {any}\n", .{expected_token});
         const token = self.peek_token() orelse return ParserError.ParsingError;
 
-        if (token != expected_token) {
+        if (expected_token != std.meta.activeTag(token.type)) {
             if (!self.try_context) std.debug.print("Expected {any} - found {any}\n", .{ expected_token, token });
             return ParserError.ParsingError;
         }
@@ -468,9 +470,9 @@ pub const Parser = struct {
         return node;
     }
 
-    fn accept_token(self: *Parser, token: tokenizer.TokenType) ?tokenizer.Token {
+    fn accept_token(self: *Parser, token_type: std.meta.Tag(tokenizer.TokenType)) ?tokenizer.Token {
         const curr_token = self.peek_token() orelse return null;
-        if (curr_token == token) {
+        if (std.meta.activeTag(curr_token.type) == token_type) {
             return self.consume_token();
         }
         return null;
@@ -491,7 +493,7 @@ pub const Parser = struct {
     }
 
     fn create_node(self: *Parser, node_value: Node) !*Node {
-        const node = try self.allocator.create(Node);
+        const node = try self.arena.create(Node);
         node.* = node_value;
         return node;
     }