diff --git a/lib/liquid/lexer.rb b/lib/liquid/lexer.rb index c0a6463b..f6079f31 100644 --- a/lib/liquid/lexer.rb +++ b/lib/liquid/lexer.rb @@ -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 diff --git a/lib/liquid/parser.rb b/lib/liquid/parser.rb index f715e6ed..15a11bc3 100644 --- a/lib/liquid/parser.rb +++ b/lib/liquid/parser.rb @@ -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 diff --git a/lib/liquid/tags/case.rb b/lib/liquid/tags/case.rb index 9288af3a..4f4731cc 100644 --- a/lib/liquid/tags/case.rb +++ b/lib/liquid/tags/case.rb @@ -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)