diff options
author | Baitinq <manuelpalenzuelamerino@gmail.com> | 2025-01-06 17:14:21 +0100 |
---|---|---|
committer | Baitinq <manuelpalenzuelamerino@gmail.com> | 2025-01-06 17:14:21 +0100 |
commit | c8373bca8a2de3de516f38e8f703794eeaa0bbb6 (patch) | |
tree | 814cba5c6df910d34b2c6ae43c4c92b0a16f2479 | |
parent | Parser: implement parse_number (diff) | |
download | interpreter-c8373bca8a2de3de516f38e8f703794eeaa0bbb6.tar.gz interpreter-c8373bca8a2de3de516f38e8f703794eeaa0bbb6.tar.bz2 interpreter-c8373bca8a2de3de516f38e8f703794eeaa0bbb6.zip |
Parser: Change grammar and implement print and expression parsing
-rw-r--r-- | grammar.ebnf | 2 | ||||
-rw-r--r-- | src/parser.zig | 78 |
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") }, |