diff options
| author | Baitinq <[email protected]> | 2025-01-23 22:55:57 +0100 |
|---|---|---|
| committer | Baitinq <[email protected]> | 2025-01-23 22:55:57 +0100 |
| commit | 84d70492d13a23d9ad5e409cdff2a6860b9c0adb (patch) | |
| tree | c72b8cb9a0906d037343a05ce6a1a944c670d33e | |
| parent | Sync grammar (diff) | |
| download | pry-lang-84d70492d13a23d9ad5e409cdff2a6860b9c0adb.tar.gz pry-lang-84d70492d13a23d9ad5e409cdff2a6860b9c0adb.tar.bz2 pry-lang-84d70492d13a23d9ad5e409cdff2a6860b9c0adb.zip | |
Feature: Support calling funtion definitions
| -rw-r--r-- | grammar.ebnf | 2 | ||||
| -rw-r--r-- | src/evaluator.zig | 27 | ||||
| -rw-r--r-- | src/parser.zig | 26 |
3 files changed, 40 insertions, 15 deletions
diff --git a/grammar.ebnf b/grammar.ebnf index 5aa9b54..7175f6a 100644 --- a/grammar.ebnf +++ b/grammar.ebnf @@ -4,7 +4,7 @@ Statement ::= (AssignmentStatement | FunctionCallStatement | IfStatement | Wh AssignmentStatement ::= "let" IDENTIFIER EQUALS Expression -FunctionCallStatement ::= IDENTIFIER LPAREN FunctionArguments? RPAREN +FunctionCallStatement ::= (IDENTIFIER | FunctionDefinition) LPAREN FunctionArguments? RPAREN IfStatement ::= "if" Expression LBRACE Statement* RBRACE -- TODO: Should function definitions be allowed? diff --git a/src/evaluator.zig b/src/evaluator.zig index ec6a698..3a145f8 100644 --- a/src/evaluator.zig +++ b/src/evaluator.zig @@ -97,16 +97,25 @@ pub const Evaluator = struct { const function_call_statement = node.FUNCTION_CALL_STATEMENT; - // Print function implementation - if (std.mem.eql(u8, function_call_statement.name, "print")) { - std.debug.assert(function_call_statement.arguments.len == 1); - std.debug.print("PRINT: {any}\n", .{try self.get_expression_value(function_call_statement.arguments[0])}); - return null; - } - - const function_definition = self.environment.get_variable(function_call_statement.name) orelse return EvaluatorError.EvaluationError; + switch (function_call_statement.expression.*) { + .FUNCTION_DEFINITION => |*function_definition| { + return try self.evaluate_function_definition(@ptrCast(function_definition), function_call_statement.arguments); + }, + .PRIMARY_EXPRESSION => |*primary_expression| { + std.debug.assert(primary_expression.* == .IDENTIFIER); + + // Print function implementation + if (std.mem.eql(u8, function_call_statement.expression.PRIMARY_EXPRESSION.IDENTIFIER.name, "print")) { + std.debug.assert(function_call_statement.arguments.len == 1); + std.debug.print("PRINT: {any}\n", .{try self.get_expression_value(function_call_statement.arguments[0])}); + return null; + } - return self.evaluate_function_definition(function_definition.FUNCTION_DEFINITION, function_call_statement.arguments); + const function_definition = self.environment.get_variable(primary_expression.IDENTIFIER.name) orelse return EvaluatorError.EvaluationError; + return self.evaluate_function_definition(function_definition.FUNCTION_DEFINITION, function_call_statement.arguments); + }, + else => unreachable, + } } fn evaluate_if_statement(self: *Evaluator, node: *parser.Node) !?*Variable { diff --git a/src/parser.zig b/src/parser.zig index 94f5cb7..3f77b19 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -19,7 +19,7 @@ pub const Node = union(enum) { expression: *Node, }, FUNCTION_CALL_STATEMENT: struct { - name: []const u8, + expression: *Node, arguments: []*Node, }, IF_STATEMENT: struct { @@ -149,11 +149,14 @@ pub const Parser = struct { }); } - // FunctionCallStatement ::= IDENTIFIER LPAREN FunctionArguments? RPAREN + // FunctionCallStatement ::= (IDENTIFIER | FunctionDefinition) LPAREN FunctionArguments? RPAREN fn parse_function_call_statement(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing function call statement {any}\n", .{self.peek_token()}); - const identifier = try self.parse_token(tokenizer.TokenType.IDENTIFIER); + const identifier = self.accept_token(tokenizer.TokenType.IDENTIFIER); + const fn_def = self.accept_parse(parse_function_definition); + + if (identifier == null and fn_def == null) return ParserError.ParsingError; _ = try self.parse_token(tokenizer.TokenType.LPAREN); @@ -161,8 +164,21 @@ pub const Parser = struct { _ = try self.parse_token(tokenizer.TokenType.RPAREN); + if (fn_def != null) { + return self.create_node(.{ .FUNCTION_CALL_STATEMENT = .{ + .expression = fn_def.?, + .arguments = arguments, + } }); + } + return self.create_node(.{ .FUNCTION_CALL_STATEMENT = .{ - .name = try self.arena.dupe(u8, identifier.type.IDENTIFIER), + .expression = try self.create_node(.{ + .PRIMARY_EXPRESSION = .{ + .IDENTIFIER = .{ + .name = try self.arena.dupe(u8, identifier.?.type.IDENTIFIER), + }, + }, + }), .arguments = arguments, } }); } @@ -327,8 +343,8 @@ pub const Parser = struct { fn parse_primary_expression(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing primary expression {any}\n", .{self.peek_token()}); - if (self.accept_parse(parse_function_definition)) |stmt| return stmt; if (self.accept_parse(parse_function_call_statement)) |stmt| return stmt; + if (self.accept_parse(parse_function_definition)) |stmt| return stmt; // LPAREN (Expression) RPAREN if (self.accept_token(tokenizer.TokenType.LPAREN)) |_| { |