diff options
author | Baitinq <manuelpalenzuelamerino@gmail.com> | 2025-01-21 00:32:14 +0100 |
---|---|---|
committer | Baitinq <manuelpalenzuelamerino@gmail.com> | 2025-01-21 00:32:14 +0100 |
commit | 967dc36c30abbab9e2983568feab9bb514ab58df (patch) | |
tree | dd038d87758bfe17edba4c1ba5457b1ebbde9184 | |
parent | Parser: Add support for parenthesis grouping (diff) | |
download | interpreter-967dc36c30abbab9e2983568feab9bb514ab58df.tar.gz interpreter-967dc36c30abbab9e2983568feab9bb514ab58df.tar.bz2 interpreter-967dc36c30abbab9e2983568feab9bb514ab58df.zip |
Feature: Add support for NOT unary expression
-rw-r--r-- | examples/9.src | 3 | ||||
-rw-r--r-- | grammar.ebnf | 4 | ||||
-rw-r--r-- | src/evaluator.zig | 5 | ||||
-rw-r--r-- | src/parser.zig | 27 | ||||
-rw-r--r-- | src/tokenizer.zig | 3 |
5 files changed, 37 insertions, 5 deletions
diff --git a/examples/9.src b/examples/9.src index d21ae71..f3ab389 100644 --- a/examples/9.src +++ b/examples/9.src @@ -1,7 +1,8 @@ let main = () => { let i = true; + i = !i; - if i { + if !i { print(i); return 1; }; diff --git a/grammar.ebnf b/grammar.ebnf index a251f26..33a6574 100644 --- a/grammar.ebnf +++ b/grammar.ebnf @@ -16,7 +16,9 @@ Expression ::= EqualityExpression | AdditiveExpression | FunctionDefinition EqualityExpression ::= AdditiveExpression "==" AdditiveExpression -AdditiveExpression ::= PrimaryExpression (("+" | "-") PrimaryExpression)* +AdditiveExpression ::= UnaryExpression (("+" | "-") UnaryExpression)* + +UnaryExpression ::= "!" UnaryExpression | PrimaryExpression PrimaryExpression ::= NUMBER | BOOLEAN | IDENTIFIER | FunctionCallStatement | LPAREN Expression RPAREN diff --git a/src/evaluator.zig b/src/evaluator.zig index f35956a..c1997f3 100644 --- a/src/evaluator.zig +++ b/src/evaluator.zig @@ -144,6 +144,11 @@ pub const Evaluator = struct { if (x.addition) return try self.create_variable(.{ .NUMBER = lhs.NUMBER + rhs.NUMBER }); return try self.create_variable(.{ .NUMBER = lhs.NUMBER - rhs.NUMBER }); }, + .UNARY_EXPRESSION => |x| { + const val = try self.get_expression_value(x.expression) orelse return EvaluatorError.EvaluationError; + std.debug.assert(val.* == .BOOLEAN); + return try self.create_variable(.{ .BOOLEAN = !val.BOOLEAN }); + }, .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; diff --git a/src/parser.zig b/src/parser.zig index ce5522d..f574161 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -15,6 +15,7 @@ const NodeType = enum { EXPRESSION, EQUALITY_EXPRESSION, ADDITIVE_EXPRESSION, + UNARY_EXPRESSION, PRIMARY_EXPRESSION, FUNCTION_DEFINITION, RETURN_STATEMENT, @@ -58,6 +59,10 @@ pub const Node = union(NodeType) { lhs: *Node, rhs: *Node, }, + UNARY_EXPRESSION: struct { + negation: bool, + expression: *Node, + }, PRIMARY_EXPRESSION: union(enum) { NUMBER: struct { value: i64, @@ -244,11 +249,11 @@ pub const Parser = struct { } }); } - // AdditiveExpression ::= PrimaryExpression (("+" | "-") PrimaryExpression)* + // AdditiveExpression ::= UnaryExpression (("+" | "-") UnaryExpression)* fn parse_additive_expression(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing additive expression\n", .{}); - var lhs = try self.parse_primary_expression(); + var lhs = try self.parse_unary_expression(); while (true) { const plus = self.accept_token(tokenizer.TokenType.PLUS); @@ -256,7 +261,7 @@ pub const Parser = struct { if (plus == null and minus == null) break; - const rhs = try self.parse_primary_expression(); + const rhs = try self.parse_unary_expression(); lhs = try self.create_node(.{ .ADDITIVE_EXPRESSION = .{ .addition = plus != null, @@ -268,6 +273,22 @@ pub const Parser = struct { return lhs; } + // UnaryExpression ::= "!" UnaryExpression | PrimaryExpression + fn parse_unary_expression(self: *Parser) ParserError!*Node { + errdefer if (!self.try_context) std.debug.print("Error parsing unary expression\n", .{}); + + const negation = self.accept_token(tokenizer.TokenType.NOT) != null; + + if (!negation) { + return try self.parse_primary_expression(); + } + + return self.create_node(.{ .UNARY_EXPRESSION = .{ + .negation = negation, + .expression = try self.parse_unary_expression(), + } }); + } + // PrimaryExpression ::= NUMBER | BOOLEAN | IDENTIFIER | FunctionCallStatement | LPAREN Expression RPAREN fn parse_primary_expression(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing primary expression\n", .{}); diff --git a/src/tokenizer.zig b/src/tokenizer.zig index 6765ea9..d137763 100644 --- a/src/tokenizer.zig +++ b/src/tokenizer.zig @@ -22,6 +22,7 @@ pub const TokenType = enum { EQUALS, PLUS, MINUS, + NOT, // Punctuation SEMICOLON, @@ -43,6 +44,7 @@ pub const Token = union(TokenType) { EQUALS: void, PLUS: void, MINUS: void, + NOT: void, SEMICOLON: void, COMMA: void, LPAREN: void, @@ -79,6 +81,7 @@ pub const Tokenizer = struct { if (c == '=') return Token{ .EQUALS = void{} }; if (c == '+') return Token{ .PLUS = void{} }; if (c == '-') return Token{ .MINUS = void{} }; + if (c == '!') return Token{ .NOT = void{} }; const string = self.consume_string(); if (string.len == 0) return TokenizerError.TokenizingError; |