summary refs log tree commit diff
diff options
context:
space:
mode:
authorBaitinq <manuelpalenzuelamerino@gmail.com>2025-01-22 00:25:22 +0100
committerBaitinq <manuelpalenzuelamerino@gmail.com>2025-01-22 00:25:22 +0100
commita04777a20e60857f880775c3c6ed23c6d1e72eca (patch)
treed5302638c8569a4d0905ef1fd4ef1b4e39e6a2de
parentFeature: Add support for while statements (diff)
downloadinterpreter-a04777a20e60857f880775c3c6ed23c6d1e72eca.tar.gz
interpreter-a04777a20e60857f880775c3c6ed23c6d1e72eca.tar.bz2
interpreter-a04777a20e60857f880775c3c6ed23c6d1e72eca.zip
Feature: Add support for division and multiplication
-rw-r--r--examples/7.src2
-rw-r--r--grammar.ebnf4
-rw-r--r--src/evaluator.zig7
-rw-r--r--src/parser.zig36
-rw-r--r--src/tokenizer.zig6
5 files changed, 50 insertions, 5 deletions
diff --git a/examples/7.src b/examples/7.src
index 1245e45..9bb3c73 100644
--- a/examples/7.src
+++ b/examples/7.src
@@ -1,7 +1,7 @@
 let main = () => {
 	let i = 4;
 	
-	if (i - 1) == 5 - (1 + 1) {
+	if (1 - 1 * 2) == 5 - (10 / 2) - 1 {
 		print(i);
 		return i;
 	};
diff --git a/grammar.ebnf b/grammar.ebnf
index 890ba2d..700147e 100644
--- a/grammar.ebnf
+++ b/grammar.ebnf
@@ -18,7 +18,9 @@ Expression   ::= EqualityExpression | AdditiveExpression | FunctionDefinition
 
 EqualityExpression ::= AdditiveExpression "==" AdditiveExpression
 
-AdditiveExpression ::= UnaryExpression (("+" | "-") UnaryExpression)*
+AdditiveExpression ::= MultiplicativeExpression (("+" | "-") MultiplicativeExpression)*
+
+MultiplicativeExpression ::= UnaryExpression (("*" | "/") UnaryExpression)*
 
 UnaryExpression ::= "!" UnaryExpression | PrimaryExpression
 
diff --git a/src/evaluator.zig b/src/evaluator.zig
index 9e89fc4..9f8b61f 100644
--- a/src/evaluator.zig
+++ b/src/evaluator.zig
@@ -165,6 +165,13 @@ 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 });
             },
+            .MULTIPLICATIVE_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);
+                if (x.multiplication) return try self.create_variable(.{ .NUMBER = lhs.NUMBER * rhs.NUMBER });
+                return try self.create_variable(.{ .NUMBER = @divFloor(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);
diff --git a/src/parser.zig b/src/parser.zig
index 13509ea..966cad3 100644
--- a/src/parser.zig
+++ b/src/parser.zig
@@ -15,6 +15,7 @@ const NodeType = enum {
     WHILE_STATEMENT,
     EQUALITY_EXPRESSION,
     ADDITIVE_EXPRESSION,
+    MULTIPLICATIVE_EXPRESSION,
     UNARY_EXPRESSION,
     PRIMARY_EXPRESSION,
     FUNCTION_DEFINITION,
@@ -54,6 +55,11 @@ pub const Node = union(NodeType) {
         lhs: *Node,
         rhs: *Node,
     },
+    MULTIPLICATIVE_EXPRESSION: struct {
+        multiplication: bool,
+        lhs: *Node,
+        rhs: *Node,
+    },
     UNARY_EXPRESSION: struct {
         negation: bool,
         expression: *Node,
@@ -268,11 +274,11 @@ pub const Parser = struct {
         } });
     }
 
-    // AdditiveExpression ::= UnaryExpression (("+" | "-") UnaryExpression)*
+    // AdditiveExpression ::= MultiplicativeExpression (("+" | "-") MultiplicativeExpression)*
     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_unary_expression();
+        var lhs = try self.parse_multiplicative_expression();
 
         while (true) {
             const plus = self.accept_token(tokenizer.TokenType.PLUS);
@@ -280,7 +286,7 @@ pub const Parser = struct {
 
             if (plus == null and minus == null) break;
 
-            const rhs = try self.parse_unary_expression();
+            const rhs = try self.parse_multiplicative_expression();
 
             lhs = try self.create_node(.{ .ADDITIVE_EXPRESSION = .{
                 .addition = plus != null,
@@ -292,6 +298,30 @@ pub const Parser = struct {
         return lhs;
     }
 
+    // MultiplicativeExpression ::= UnaryExpression (("*" | "/") UnaryExpression)*
+    fn parse_multiplicative_expression(self: *Parser) ParserError!*Node {
+        errdefer if (!self.try_context) std.debug.print("Error parsing additive expression\n", .{});
+
+        var lhs = try self.parse_unary_expression();
+
+        while (true) {
+            const mul = self.accept_token(tokenizer.TokenType.MUL);
+            const div = self.accept_token(tokenizer.TokenType.DIV);
+
+            if (mul == null and div == null) break;
+
+            const rhs = try self.parse_unary_expression();
+
+            lhs = try self.create_node(.{ .MULTIPLICATIVE_EXPRESSION = .{
+                .multiplication = mul != null,
+                .lhs = lhs,
+                .rhs = rhs,
+            } });
+        }
+
+        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", .{});
diff --git a/src/tokenizer.zig b/src/tokenizer.zig
index a5c0e9c..e125110 100644
--- a/src/tokenizer.zig
+++ b/src/tokenizer.zig
@@ -23,6 +23,8 @@ pub const TokenType = enum {
     EQUALS,
     PLUS,
     MINUS,
+    MUL,
+    DIV,
     BANG,
 
     // Punctuation
@@ -46,6 +48,8 @@ pub const Token = union(TokenType) {
     EQUALS: void,
     PLUS: void,
     MINUS: void,
+    MUL: void,
+    DIV: void,
     BANG: void,
     SEMICOLON: void,
     COMMA: void,
@@ -90,6 +94,8 @@ 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{ .MUL = void{} };
+        if (c == '/') return Token{ .DIV = void{} };
         if (c == '!') return Token{ .BANG = void{} };
 
         const string = self.consume_string();