This commit is contained in:
agra
2026-02-20 12:12:51 +02:00
parent e0e655cd36
commit 1ecac79642
10 changed files with 265 additions and 29 deletions

View File

@@ -1025,7 +1025,7 @@ pub const Parser = struct {
// ---- Expression parsing (Pratt / precedence climbing) ----
pub fn parseExpr(self: *Parser) anyerror!*Node {
return self.parseBinary(0);
return self.parseBinary(Prec.none);
}
fn parseBinary(self: *Parser, min_prec: u8) anyerror!*Node {
@@ -1088,6 +1088,12 @@ pub const Parser = struct {
const operand = try self.parseUnary();
return try self.createNode(start, .{ .unary_op = .{ .op = .not, .operand = operand } });
}
if (self.current.tag == .tilde) {
const start = self.current.loc.start;
self.advance();
const operand = try self.parseUnary();
return try self.createNode(start, .{ .unary_op = .{ .op = .bit_not, .operand = operand } });
}
if (self.current.tag == .kw_xx) {
const start = self.current.loc.start;
self.advance();
@@ -1435,9 +1441,9 @@ pub const Parser = struct {
const start = self.current.loc.start;
self.advance(); // skip 'if'
// Parse condition at prec 5 (arithmetic+), leaving all comparisons
// Parse condition above comparison level, leaving comparisons
// unconsumed for manual handling with match disambiguation.
var condition = try self.parseBinary(5);
var condition = try self.parseBinary(Prec.shift);
// Handle comparisons with chain detection and match disambiguation.
// All comparisons (< <= > >= == !=) are at the same precedence.
@@ -1459,13 +1465,13 @@ pub const Parser = struct {
// Chain followed by == { is an error — fall through to
// regular comparison (will likely fail at parse time)
}
const rhs = try self.parseBinary(5);
const rhs = try self.parseBinary(Prec.shift);
try operands.append(self.allocator, rhs);
try ops.append(self.allocator, .eq);
} else {
const cmp_op = self.binaryOp() orelse break;
self.advance();
const rhs = try self.parseBinary(5);
const rhs = try self.parseBinary(Prec.shift);
try operands.append(self.allocator, rhs);
try ops.append(self.allocator, cmp_op);
}
@@ -1488,7 +1494,7 @@ pub const Parser = struct {
}
// Handle and/or with proper Pratt precedence
condition = try self.parseBinaryRhs(condition, 1);
condition = try self.parseBinaryRhs(condition, Prec.logical_or);
// Inline form: if cond then expr [else expr]
if (self.current.tag == .kw_then) {
@@ -1771,7 +1777,9 @@ pub const Parser = struct {
fn isAssignOp(self: *const Parser) bool {
return switch (self.current.tag) {
.equal, .plus_equal, .minus_equal, .star_equal, .slash_equal, .percent_equal => true,
.equal, .plus_equal, .minus_equal, .star_equal, .slash_equal, .percent_equal,
.ampersand_equal, .pipe_equal, .caret_equal, .less_less_equal, .greater_greater_equal,
=> true,
else => false,
};
}
@@ -1784,6 +1792,11 @@ pub const Parser = struct {
.star_equal => .mul_assign,
.slash_equal => .div_assign,
.percent_equal => .mod_assign,
.ampersand_equal => .and_assign,
.pipe_equal => .or_assign,
.caret_equal => .xor_assign,
.less_less_equal => .shl_assign,
.greater_greater_equal => .shr_assign,
else => unreachable,
};
}
@@ -1827,16 +1840,31 @@ pub const Parser = struct {
} });
}
const Prec = struct {
const none: u8 = 0;
const logical_or: u8 = 1; // or
const logical_and: u8 = 2; // and
const bit_or: u8 = 3; // |
const bit_xor: u8 = 4; // ^
const bit_and: u8 = 5; // &
const comparison: u8 = 6; // == != < <= > >= in
const shift: u8 = 7; // << >>
const additive: u8 = 8; // + -
const multiplicative: u8 = 9; // * / %
};
fn binaryPrec(self: *const Parser) u8 {
return switch (self.current.tag) {
.kw_or => 1,
.kw_and => 2,
.pipe => 3,
.ampersand => 3,
.equal_equal, .bang_equal, .less, .less_equal, .greater, .greater_equal, .kw_in => 4,
.plus, .minus => 5,
.star, .slash, .percent => 6,
else => 0,
.kw_or => Prec.logical_or,
.kw_and => Prec.logical_and,
.pipe => Prec.bit_or,
.caret => Prec.bit_xor,
.ampersand => Prec.bit_and,
.equal_equal, .bang_equal, .less, .less_equal, .greater, .greater_equal, .kw_in => Prec.comparison,
.less_less, .greater_greater => Prec.shift,
.plus, .minus => Prec.additive,
.star, .slash, .percent => Prec.multiplicative,
else => Prec.none,
};
}
@@ -1845,6 +1873,7 @@ pub const Parser = struct {
.kw_and => .and_op,
.kw_or => .or_op,
.pipe => .bit_or,
.caret => .bit_xor,
.ampersand => .bit_and,
.plus => .add,
.minus => .sub,
@@ -1857,6 +1886,8 @@ pub const Parser = struct {
.less_equal => .lte,
.greater => .gt,
.greater_equal => .gte,
.less_less => .shl,
.greater_greater => .shr,
.kw_in => .in_op,
else => null,
};