diff options
author | Baitinq <manuelpalenzuelamerino@gmail.com> | 2025-01-19 16:04:08 +0100 |
---|---|---|
committer | Baitinq <manuelpalenzuelamerino@gmail.com> | 2025-01-19 16:43:59 +0100 |
commit | 44ec5d5de6a558fc20b8452a1ee743b64d56e5e5 (patch) | |
tree | e6b3f445aa8578b2bcaa5de2d2d91214755230b9 | |
parent | Feature: Add support for boolean values (diff) | |
download | interpreter-44ec5d5de6a558fc20b8452a1ee743b64d56e5e5.tar.gz interpreter-44ec5d5de6a558fc20b8452a1ee743b64d56e5e5.tar.bz2 interpreter-44ec5d5de6a558fc20b8452a1ee743b64d56e5e5.zip |
Feature: Add basic support for equality expression
-rw-r--r-- | examples/7.src | 2 | ||||
-rw-r--r-- | examples/8.src | 4 | ||||
-rw-r--r-- | grammar.ebnf | 7 | ||||
-rw-r--r-- | src/evaluator.zig | 12 | ||||
-rw-r--r-- | src/parser.zig | 54 |
5 files changed, 54 insertions, 25 deletions
diff --git a/examples/7.src b/examples/7.src index 0cb0721..b96cba8 100644 --- a/examples/7.src +++ b/examples/7.src @@ -1,7 +1,7 @@ let main = () => { let i = 4; - if i - 4 { + if i + 1 == 5 { print(i); return i; }; diff --git a/examples/8.src b/examples/8.src index 1ec46e4..33323f7 100644 --- a/examples/8.src +++ b/examples/8.src @@ -1,8 +1,8 @@ let fib = (n) => { - if n { + if n == 0 { return 0; }; - if n - 1 { + if n == 1 { return 1; }; return fib(n-2) + fib(n-1); diff --git a/grammar.ebnf b/grammar.ebnf index eee1103..aaa0e78 100644 --- a/grammar.ebnf +++ b/grammar.ebnf @@ -12,13 +12,14 @@ ReturnStatement ::= RETURN Expression FunctionArguments ::= Expression ("," Expression)* -Expression ::= AdditiveExpression | FunctionDefinition +Expression ::= EqualityExpression | AdditiveExpression | FunctionDefinition -AdditiveExpression ::= PrimaryExpression (("+" | "-") AdditiveExpression) +EqualityExpression ::= AdditiveExpression "==" AdditiveExpression + +AdditiveExpression ::= PrimaryExpression (("+" | "-") AdditiveExpression)? PrimaryExpression ::= NUMBER | BOOLEAN | IDENTIFIER | FunctionCallStatement FunctionDefinition ::= LPAREN FunctionParamters? RPAREN ARROW LBRACE Statement* ReturnStatement SEMICOLON RBRACE FunctionParameters ::= IDENTIFIER ("," IDENTIFIER)* - diff --git a/src/evaluator.zig b/src/evaluator.zig index 39c7235..f35956a 100644 --- a/src/evaluator.zig +++ b/src/evaluator.zig @@ -141,10 +141,14 @@ pub const Evaluator = struct { const lhs = try self.get_expression_value(x.lhs) orelse return EvaluatorError.EvaluationError; const rhs = try self.get_expression_value(x.rhs) orelse return EvaluatorError.EvaluationError; std.debug.assert(lhs.* == .NUMBER and rhs.* == .NUMBER); - var res: i64 = undefined; - if (x.addition) res = lhs.NUMBER + rhs.NUMBER; - res = lhs.NUMBER - rhs.NUMBER; - return try self.create_variable(.{ .NUMBER = res }); + if (x.addition) return try self.create_variable(.{ .NUMBER = lhs.NUMBER + rhs.NUMBER }); + return try self.create_variable(.{ .NUMBER = lhs.NUMBER - rhs.NUMBER }); + }, + .EQUALITY_EXPRESSION => |x| { + const lhs = try self.get_expression_value(x.lhs) orelse return EvaluatorError.EvaluationError; + const rhs = try self.get_expression_value(x.rhs) orelse return EvaluatorError.EvaluationError; + std.debug.assert(lhs.* == .NUMBER and rhs.* == .NUMBER); //TODO: Generic + return try self.create_variable(.{ .BOOLEAN = (lhs.NUMBER == rhs.NUMBER) }); }, .PRIMARY_EXPRESSION => |x| { switch (x) { diff --git a/src/parser.zig b/src/parser.zig index ac66e5d..1014ba4 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -13,6 +13,7 @@ const NodeType = enum { FUNCTION_CALL_STATEMENT, IF_STATEMENT, EXPRESSION, + EQUALITY_EXPRESSION, ADDITIVE_EXPRESSION, PRIMARY_EXPRESSION, FUNCTION_DEFINITION, @@ -40,6 +41,7 @@ pub const Node = union(NodeType) { statements: []*Node, }, EXPRESSION: union(enum) { + //TODO: Why do we need this ADDITIVE_EXPRESSION: struct { expression: *Node, }, @@ -47,6 +49,10 @@ pub const Node = union(NodeType) { expression: *Node, }, }, + EQUALITY_EXPRESSION: struct { + lhs: *Node, + rhs: *Node, + }, ADDITIVE_EXPRESSION: struct { addition: bool, lhs: *Node, @@ -211,16 +217,34 @@ pub const Parser = struct { } }); } - // Expression ::= AdditiveExpression | FunctionDefinition + // Expression ::= EqualityExpression | AdditiveExpression | FunctionDefinition fn parse_expression(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing expression\n", .{}); - return self.accept_parse(parse_additive_expression) orelse + return self.accept_parse(parse_equality_expression) orelse + self.accept_parse(parse_additive_expression) orelse self.accept_parse(parse_function_definition) orelse return ParserError.ParsingError; } - // AdditiveExpression ::= PrimaryExpression (("+" | "-") AdditiveExpression) + // EqualityExpression ::= AdditiveExpression "==" AdditiveExpression + fn parse_equality_expression(self: *Parser) ParserError!*Node { + errdefer if (!self.try_context) std.debug.print("Error parsing equality expression\n", .{}); + + const lhs = try self.parse_additive_expression(); + + _ = try self.parse_token(tokenizer.TokenType.EQUALS); + _ = try self.parse_token(tokenizer.TokenType.EQUALS); + + const rhs = try self.parse_additive_expression(); + + return self.create_node(.{ .EQUALITY_EXPRESSION = .{ + .lhs = lhs, + .rhs = rhs, + } }); + } + + // AdditiveExpression ::= PrimaryExpression (("+" | "-") AdditiveExpression)? fn parse_additive_expression(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing additive expression\n", .{}); @@ -339,6 +363,18 @@ pub const Parser = struct { }); } + 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; + + if (token != expected_token) { + if (!self.try_context) std.debug.print("Expected {any} - found {any}\n", .{ expected_token, token }); + return ParserError.ParsingError; + } + + return self.consume_token() orelse unreachable; + } + fn accept_parse(self: *Parser, parsing_func: *const fn (_: *Parser) ParserError!*Node) ?*Node { const prev_offset = self.offset; self.try_context = true; @@ -358,18 +394,6 @@ pub const Parser = struct { return null; } - 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; - - if (token != expected_token) { - if (!self.try_context) std.debug.print("Expected {any} - found {any}\n", .{ expected_token, token }); - return ParserError.ParsingError; - } - - return self.consume_token() orelse unreachable; - } - fn consume_token(self: *Parser) ?tokenizer.Token { if (self.offset >= self.tokens.len) return null; |