diff options
| author | Baitinq <[email protected]> | 2025-01-18 23:29:31 +0100 |
|---|---|---|
| committer | Baitinq <[email protected]> | 2025-01-18 23:29:31 +0100 |
| commit | 79c0f45847dee608747eca6b8e36e68cb9c881e3 (patch) | |
| tree | 3c651c35d9de5e2897b9a1225d7965b8d3071feb /src/parser.zig | |
| parent | Examples: add future examples :^) (diff) | |
| download | interpreter-79c0f45847dee608747eca6b8e36e68cb9c881e3.tar.gz interpreter-79c0f45847dee608747eca6b8e36e68cb9c881e3.tar.bz2 interpreter-79c0f45847dee608747eca6b8e36e68cb9c881e3.zip | |
Feature: Add basic support for if statements
Diffstat (limited to 'src/parser.zig')
| -rw-r--r-- | src/parser.zig | 64 |
1 files changed, 46 insertions, 18 deletions
diff --git a/src/parser.zig b/src/parser.zig index cf7f7d3..81006f8 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -11,6 +11,7 @@ const NodeType = enum { STATEMENT, ASSIGNMENT_STATEMENT, FUNCTION_CALL_STATEMENT, + IF_STATEMENT, EXPRESSION, ADDITIVE_EXPRESSION, PRIMARY_EXPRESSION, @@ -34,6 +35,10 @@ pub const Node = union(NodeType) { name: []const u8, arguments: []*Node, }, + IF_STATEMENT: struct { + condition: *Node, + statements: []*Node, + }, EXPRESSION: union(enum) { ADDITIVE_EXPRESSION: struct { expression: *Node, @@ -101,14 +106,16 @@ pub const Parser = struct { } }); } - // Statement ::= (AssignmentStatement | FunctionCallStatement) SEMICOLON + // Statement ::= (AssignmentStatement | FunctionCallStatement | IfStatement | ReturnStatement) SEMICOLON fn parse_statement(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing statement\n", .{}); const statement = self.accept_parse(parse_function_call_statement) orelse + self.accept_parse(parse_if_statement) orelse + self.accept_parse(parse_return_statement) orelse try self.parse_assignment_statement(); - _ = try self.require_token(tokenizer.TokenType.SEMICOLON); + _ = try self.parse_token(tokenizer.TokenType.SEMICOLON); return self.create_node(.{ .STATEMENT = .{ @@ -126,9 +133,9 @@ pub const Parser = struct { is_declaration = true; } - const identifier = try self.require_token(tokenizer.TokenType.IDENTIFIER); + const identifier = try self.parse_token(tokenizer.TokenType.IDENTIFIER); - _ = try self.require_token(tokenizer.TokenType.EQUALS); + _ = try self.parse_token(tokenizer.TokenType.EQUALS); const expression = try self.parse_expression(); @@ -145,13 +152,13 @@ pub const Parser = struct { fn parse_function_call_statement(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing function call statement\n", .{}); - const identifier = try self.require_token(tokenizer.TokenType.IDENTIFIER); + const identifier = try self.parse_token(tokenizer.TokenType.IDENTIFIER); - _ = try self.require_token(tokenizer.TokenType.LPAREN); + _ = try self.parse_token(tokenizer.TokenType.LPAREN); const arguments = try self.parse_function_arguments(); - _ = try self.require_token(tokenizer.TokenType.RPAREN); + _ = try self.parse_token(tokenizer.TokenType.RPAREN); return self.create_node(.{ .FUNCTION_CALL_STATEMENT = .{ .name = try self.allocator.dupe(u8, identifier.IDENTIFIER), @@ -177,6 +184,29 @@ pub const Parser = struct { return node_list.items; } + // 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", .{}); + + _ = try self.parse_token(tokenizer.TokenType.IF); + + const expression = try self.parse_expression(); + + _ = try self.parse_token(tokenizer.TokenType.LBRACE); + + var statements = std.ArrayList(*Node).init(self.allocator); + while (self.accept_parse(parse_statement)) |expr| { + try statements.append(expr); + } + + _ = try self.parse_token(tokenizer.TokenType.RBRACE); + + return try self.create_node(.{ .IF_STATEMENT = .{ + .condition = expression, + .statements = statements.items, + } }); + } + // Expression ::= AdditiveExpression | FunctionDefinition fn parse_expression(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing expression\n", .{}); @@ -234,23 +264,23 @@ pub const Parser = struct { fn parse_function_definition(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing function definition\n", .{}); - _ = try self.require_token(tokenizer.TokenType.LPAREN); + _ = try self.parse_token(tokenizer.TokenType.LPAREN); const parameters = try self.parse_function_parameters(); - _ = try self.require_token(tokenizer.TokenType.RPAREN); + _ = try self.parse_token(tokenizer.TokenType.RPAREN); - _ = try self.require_token(tokenizer.TokenType.ARROW); - _ = try self.require_token(tokenizer.TokenType.LBRACE); + _ = try self.parse_token(tokenizer.TokenType.ARROW); + _ = try self.parse_token(tokenizer.TokenType.LBRACE); var nodes = std.ArrayList(*Node).init(self.allocator); while (self.accept_parse(parse_statement)) |expression| { try nodes.append(expression); } - try nodes.append(try self.parse_return_statement()); + std.debug.assert(nodes.getLast().STATEMENT.statement.* == .RETURN_STATEMENT); - _ = try self.require_token(tokenizer.TokenType.RBRACE); + _ = try self.parse_token(tokenizer.TokenType.RBRACE); return self.create_node(.{ .FUNCTION_DEFINITION = .{ .statements = nodes.items, @@ -283,15 +313,13 @@ pub const Parser = struct { return node_list.items; } - // ReturnStatement :== RETURN Expression + // ReturnStatement ::= RETURN Expression fn parse_return_statement(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing return statement\n", .{}); - _ = try self.require_token(tokenizer.TokenType.RETURN); + _ = try self.parse_token(tokenizer.TokenType.RETURN); const expression = try self.parse_expression(); - _ = try self.require_token(tokenizer.TokenType.SEMICOLON); //TODO: I dont like this - return self.create_node(.{ .RETURN_STATEMENT = .{ .expression = @constCast(expression), @@ -318,7 +346,7 @@ pub const Parser = struct { return null; } - fn require_token(self: *Parser, expected_token: tokenizer.TokenType) ParserError!tokenizer.Token { + fn parse_token(self: *Parser, expected_token: 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; |