Prepare logical for grouping

This commit is contained in:
Charles-P. Clermont
2026-01-27 10:07:35 -05:00
parent 7f414e5fa6
commit f9b5313020
3 changed files with 18 additions and 16 deletions
+14 -8
View File
@@ -6,22 +6,24 @@ module Liquid
CLOSE_SQUARE = [:close_square, "]"].freeze
COLON = [:colon, ":"].freeze
COMMA = [:comma, ","].freeze
COMPARISION_NOT_EQUAL = [:equality, "!="].freeze
COMPARISON_CONTAINS = [:comparison, "contains"].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 = [:equality, "<>"].freeze
EQUALITY_EQUAL_EQUAL = [:equality, "=="].freeze
EQUALITY_NOT_EQUAL = [:equality, "!="].freeze
EQUALITY_NOT_EQUAL_ALT = [:equality, "<>"].freeze
DASH = [:dash, "-"].freeze
DOT = [:dot, "."].freeze
DOTDOT = [:dotdot, ".."].freeze
DOT_ORD = ".".ord
DOUBLE_STRING_LITERAL = /"[^\"]*"/
EOS = [:end_of_string].freeze
IDENTIFIER = /[a-zA-Z_][\w-]*\??/
NUMBER_LITERAL = /-?\d+(\.\d+)?/
IDENTIFIER = /[a-zA-Z_][\w-]*\??/
LOGICAL_AND = [:logical, 'and'].freeze
LOGICAL_OR = [:logical, 'or'].freeze
NUMBER_LITERAL = /-?\d+(\.\d+)?/
OPEN_ROUND = [:open_round, "("].freeze
OPEN_SQUARE = [:open_square, "["].freeze
PIPE = [:pipe, "|"].freeze
@@ -38,11 +40,11 @@ module Liquid
TWO_CHARS_COMPARISON_JUMP_TABLE = [].tap do |table|
table["=".ord] = [].tap do |sub_table|
sub_table["=".ord] = COMPARISON_EQUAL
sub_table["=".ord] = EQUALITY_EQUAL_EQUAL
sub_table.freeze
end
table["!".ord] = [].tap do |sub_table|
sub_table["=".ord] = COMPARISION_NOT_EQUAL
sub_table["=".ord] = EQUALITY_NOT_EQUAL
sub_table.freeze
end
table.freeze
@@ -51,7 +53,7 @@ module Liquid
COMPARISON_JUMP_TABLE = [].tap do |table|
table["<".ord] = [].tap do |sub_table|
sub_table["=".ord] = COMPARISON_LESS_THAN_OR_EQUAL
sub_table[">".ord] = COMPARISON_NOT_EQUAL_ALT
sub_table[">".ord] = EQUALITY_NOT_EQUAL_ALT
sub_table.freeze
end
table[">".ord] = [].tap do |sub_table|
@@ -151,6 +153,10 @@ module Liquid
# Special case for "contains"
output << if type == :id && t == "contains" && output.last&.first != :dot
COMPARISON_CONTAINS
elsif type == :id && t == "and" && output.last&.first != :dot
LOGICAL_AND
elsif type == :id && t == "or" && output.last&.first != :dot
LOGICAL_OR
else
[type, t]
end
+3 -7
View File
@@ -62,14 +62,10 @@ module Liquid
#
# `a == b and b or c` is evaluated like (a and (b or c))
def logical
operator = nil
expr = equality
while (operator = id?('and') || id?('or'))
if expr.is_a?(BinaryExpression) && (expr.operator == 'and' || expr.operator == 'or')
expr.right_node = BinaryExpression.new(expr.right_node, operator, equality)
else
expr = BinaryExpression.new(expr, operator, equality)
end
end
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
end
+1 -1
View File
@@ -104,7 +104,7 @@ module Liquid
block.attach(body)
@blocks << block
break unless parser.id?('or') || parser.consume?(:comma)
break unless parser.consume?(:logical) == 'or' || parser.consume?(:comma)
end
parser.consume(:end_of_string)