diff options
author | Baitinq <manuelpalenzuelamerino@gmail.com> | 2025-01-22 00:25:22 +0100 |
---|---|---|
committer | Baitinq <manuelpalenzuelamerino@gmail.com> | 2025-01-22 00:25:22 +0100 |
commit | a04777a20e60857f880775c3c6ed23c6d1e72eca (patch) | |
tree | d5302638c8569a4d0905ef1fd4ef1b4e39e6a2de | |
parent | Feature: Add support for while statements (diff) | |
download | interpreter-a04777a20e60857f880775c3c6ed23c6d1e72eca.tar.gz interpreter-a04777a20e60857f880775c3c6ed23c6d1e72eca.tar.bz2 interpreter-a04777a20e60857f880775c3c6ed23c6d1e72eca.zip |
Feature: Add support for division and multiplication
-rw-r--r-- | examples/7.src | 2 | ||||
-rw-r--r-- | grammar.ebnf | 4 | ||||
-rw-r--r-- | src/evaluator.zig | 7 | ||||
-rw-r--r-- | src/parser.zig | 36 | ||||
-rw-r--r-- | src/tokenizer.zig | 6 |
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(); |