diff options
Diffstat (limited to 'src/parser.zig')
-rw-r--r-- | src/parser.zig | 138 |
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; } |