fix(parser): implement RTL associativity for boolean expressions

- Use right-recursive descent for proper RTL precedence
- Add bin/liquid-spec-all-adapters for CI workflow
- Update CI to use dedicated script

Fixes 128 precedence test failures from original implementation.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
Charles-P. Clermont
2026-01-28 09:09:19 -05:00
co-authored by Claude Opus 4.5
parent 3b13ee0ff3
commit 26cb29487b
3 changed files with 16 additions and 15 deletions
+10 -10
View File
@@ -59,18 +59,18 @@ module Liquid
logical
end
# Logical relations in Liquid, unlike other languages, are right-to-left
# associative. This creates a right-leaning tree and is why the method
# looks a bit more complicated
#
# Logical relations use right-to-left associativity.
# `a and b or c` is evaluated like (a and (b or c))
# logical := equality (("and" | "or") equality)*
# This enables short-circuit: if `a` is false, entire expression short-circuits.
# logical := equality (("and" | "or") logical)?
def logical
operator = nil
expr = equality
expr = BinaryExpression.new(expr, operator, equality) if (operator = consume?(:logical))
expr.right_node = BinaryExpression.new(expr.right_node, operator, equality) while (operator = consume?(:logical))
expr
left = equality
if (operator = consume?(:logical))
right = logical # recursive call builds proper RTL tree
BinaryExpression.new(left, operator, right)
else
left
end
end
# equality := comparison (("==" | "!=" | "<>") comparison)*