fix precedence

This commit is contained in:
caandt 2025-06-08 11:59:07 -05:00
parent b193b80e40
commit 3ad4054176

View file

@ -45,7 +45,8 @@ fn no_infix(_: *Parser, _: u32, _: *const Expr, _: Token) Error!*const Expr {
return Error.InvalidOp;
}
pub const Operator = struct {
precedence: u32 = 0,
prefix_precedence: u32 = 0,
infix_precedence: u32 = 0,
parse_prefix: *const fn (*Parser, u32, Token) Error!*const Expr = no_prefix,
parse_infix: *const fn (*Parser, u32, *const Expr, Token) Error!*const Expr = no_infix,
};
@ -80,13 +81,13 @@ pub const Parser = struct {
fn parse_expr(self: *Parser, precedence: u32) Error!*const Expr {
const tok = self.tokenizer.next();
const prefix = self.ops.get(tok.kind) orelse return Error.InvalidOp;
var left = try prefix.parse_prefix(self, prefix.precedence, tok);
var left = try prefix.parse_prefix(self, prefix.prefix_precedence, tok);
var infix: Operator = undefined;
while (w: {
infix = self.ops.get(self.tokenizer.peek().kind) orelse break :w false;
break :w infix.precedence > precedence;
break :w infix.infix_precedence > precedence;
}) {
left = try infix.parse_infix(self, infix.precedence, left, self.tokenizer.next());
left = try infix.parse_infix(self, infix.infix_precedence, left, self.tokenizer.next());
}
return left;
}
@ -95,15 +96,17 @@ pub const Parser = struct {
ptr.* = try expr;
return ptr;
}
fn register_unop(self: *Parser, op: []const u8, precedence: u32) !void {
const op_p = try self.ops.getOrPutValue(op_kind(op), .{ .precedence = precedence });
fn register_unop(self: *Parser, op: []const u8, precedence: u32) Error!void {
const op_p = try self.ops.getOrPutValue(op_kind(op), .{});
op_p.value_ptr.parse_prefix = prefix_unop;
op_p.value_ptr.prefix_precedence = precedence;
}
fn register_binop(self: *Parser, op: []const u8, precedence: u32) !void {
const op_p = try self.ops.getOrPutValue(op_kind(op), .{ .precedence = precedence });
fn register_binop(self: *Parser, op: []const u8, precedence: u32) Error!void {
const op_p = try self.ops.getOrPutValue(op_kind(op), .{});
op_p.value_ptr.parse_infix = infix_binop;
op_p.value_ptr.infix_precedence = precedence;
}
pub fn init(allocator: std.mem.Allocator) !Parser {
pub fn init(allocator: std.mem.Allocator) Error!Parser {
const ops = std.AutoHashMap(TokenKind, Operator).init(allocator);
var p = Parser{ .tokenizer = undefined, .allocator = allocator, .ops = ops };