Make Parser.expression parse equality expressions

This commit is contained in:
Charles-P. Clermont
2026-01-26 16:52:31 -05:00
parent b161dae495
commit 0b890904f0
5 changed files with 51 additions and 9 deletions
+3 -3
View File
@@ -6,14 +6,14 @@ module Liquid
CLOSE_SQUARE = [:close_square, "]"].freeze
COLON = [:colon, ":"].freeze
COMMA = [:comma, ","].freeze
COMPARISION_NOT_EQUAL = [:comparison, "!="].freeze
COMPARISION_NOT_EQUAL = [:equality, "!="].freeze
COMPARISON_CONTAINS = [:comparison, "contains"].freeze
COMPARISON_EQUAL = [:comparison, "=="].freeze
COMPARISON_EQUAL = [:equality, "=="].freeze
COMPARISON_GREATER_THAN = [:comparison, ">"].freeze
COMPARISON_GREATER_THAN_OR_EQUAL = [:comparison, ">="].freeze
COMPARISON_LESS_THAN = [:comparison, "<"].freeze
COMPARISON_LESS_THAN_OR_EQUAL = [:comparison, "<="].freeze
COMPARISON_NOT_EQUAL_ALT = [:comparison, "<>"].freeze
COMPARISON_NOT_EQUAL_ALT = [:equality, "<>"].freeze
DASH = [:dash, "-"].freeze
DOT = [:dot, "."].freeze
DOTDOT = [:dotdot, ".."].freeze
+12 -2
View File
@@ -47,11 +47,21 @@ module Liquid
tok[0] == type
end
# expression := comparison
# expression := equality
# equality := comparison (("==" | "!=" | "<>") comparison)*
# comparison := primary ((">=" | ">" | "<" | "<=" | ... ) primary)*
# primary := string | number | variable_lookup | range | boolean
def expression
comparison
equality
end
def equality
expr = comparison
while look(:equality)
operator = consume
expr = BinaryExpression.new(expr, operator, comparison)
end
expr
end
# comparison := primary ((">=" | ">" | "<" | "<=" | ... ) primary)*
+1 -1
View File
@@ -97,7 +97,7 @@ module Liquid
def parse_comparison(p)
a = parse_expression(p)
if (op = p.consume?(:comparison))
if (op = p.consume?(:comparison) || p.consume?(:equality))
b = parse_expression(p)
Condition.new(a, op, b)
else
+10 -3
View File
@@ -26,10 +26,17 @@ class LexerUnitTest < Minitest::Test
)
end
def test_equality
assert_equal(
[[:equality, '=='], [:equality, '<>'], [:equality, '!='], [:end_of_string]],
tokenize('== <> != '),
)
end
def test_comparison
assert_equal(
[[:comparison, '=='], [:comparison, '<>'], [:comparison, 'contains'], [:end_of_string]],
tokenize('== <> contains '),
[[:comparison, '>'], [:comparison, '>='], [:comparison, '<'], [:comparison, '<='], [:comparison, 'contains'], [:end_of_string]],
tokenize('> >= < <= contains'),
)
end
@@ -81,7 +88,7 @@ class LexerUnitTest < Minitest::Test
def test_whitespace
assert_equal(
[[:id, 'five'], [:pipe, '|'], [:comparison, '=='], [:end_of_string]],
[[:id, 'five'], [:pipe, '|'], [:equality, '=='], [:end_of_string]],
tokenize("five|\n\t =="),
)
end
+25
View File
@@ -77,6 +77,31 @@ class ParserUnitTest < Minitest::Test
assert_equal(0..5, p.expression)
end
def test_equality
p = new_parser("a == b")
expr = p.expression
assert(expr.is_a?(BinaryExpression))
assert_equal('==', expr.operator)
assert_equal('a', expr.left.name)
assert_equal('b', expr.right.name)
# BinaryExpression(==)
# left: BinaryExpression(<)
# left: 0
# right: 5
# right: BinaryExpression(>)
# left: 6
# right: 1
p = new_parser("0 < 5 == 6 > 1")
expr = p.expression
assert(expr.is_a?(BinaryExpression))
assert_equal('==', expr.operator)
assert_equal(0, expr.left.left)
assert_equal(5, expr.left.right)
assert_equal(6, expr.right.left)
assert_equal(1, expr.right.right)
end
def test_comparison
p = new_parser("a > b")
expr = p.expression