summary refs log tree commit diff
diff options
context:
space:
mode:
authorBaitinq <manuelpalenzuelamerino@gmail.com>2025-01-19 16:04:08 +0100
committerBaitinq <manuelpalenzuelamerino@gmail.com>2025-01-19 16:43:59 +0100
commit44ec5d5de6a558fc20b8452a1ee743b64d56e5e5 (patch)
treee6b3f445aa8578b2bcaa5de2d2d91214755230b9
parentFeature: Add support for boolean values (diff)
downloadinterpreter-44ec5d5de6a558fc20b8452a1ee743b64d56e5e5.tar.gz
interpreter-44ec5d5de6a558fc20b8452a1ee743b64d56e5e5.tar.bz2
interpreter-44ec5d5de6a558fc20b8452a1ee743b64d56e5e5.zip
Feature: Add basic support for equality expression
-rw-r--r--examples/7.src2
-rw-r--r--examples/8.src4
-rw-r--r--grammar.ebnf7
-rw-r--r--src/evaluator.zig12
-rw-r--r--src/parser.zig54
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;