mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-26 13:45:13 -07:00
Make Parser.expression parse comparisons
This commit is contained in:
@@ -62,6 +62,7 @@ require 'liquid/interrupts'
|
|||||||
require 'liquid/tags'
|
require 'liquid/tags'
|
||||||
require "liquid/environment"
|
require "liquid/environment"
|
||||||
require 'liquid/lexer'
|
require 'liquid/lexer'
|
||||||
|
require 'liquid/binary_expression'
|
||||||
require 'liquid/parser'
|
require 'liquid/parser'
|
||||||
require 'liquid/i18n'
|
require 'liquid/i18n'
|
||||||
require 'liquid/drop'
|
require 'liquid/drop'
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Liquid
|
||||||
|
class BinaryExpression
|
||||||
|
attr_reader :left, :operator, :right
|
||||||
|
|
||||||
|
def initialize(left, operator, right)
|
||||||
|
@left = left
|
||||||
|
@operator = operator
|
||||||
|
@right = right
|
||||||
|
end
|
||||||
|
|
||||||
|
def evaluate(context)
|
||||||
|
left_value = value(left, context)
|
||||||
|
right_value = value(@right, context)
|
||||||
|
|
||||||
|
case operator
|
||||||
|
when '>'
|
||||||
|
left_value > right_value
|
||||||
|
when '>='
|
||||||
|
left_value >= right_value
|
||||||
|
when '<'
|
||||||
|
left_value < right_value
|
||||||
|
when '<='
|
||||||
|
left_value <= right_value
|
||||||
|
when '=='
|
||||||
|
left_value == right_value
|
||||||
|
when '!=', '<>'
|
||||||
|
left_value != right_value
|
||||||
|
when 'contains'
|
||||||
|
if left_value && right_value && left_value.respond_to?(:include?)
|
||||||
|
right_value = right_value.to_s if left_value.is_a?(String)
|
||||||
|
left_value.include?(right_value)
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def value(expr, context)
|
||||||
|
Utils.to_liquid_value(context.evaluate(expr))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -47,7 +47,24 @@ module Liquid
|
|||||||
tok[0] == type
|
tok[0] == type
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# expression := comparison
|
||||||
|
# comparison := primary ((">=" | ">" | "<" | "<=" | ... ) primary)*
|
||||||
|
# primary := string | number | variable_lookup | range | boolean
|
||||||
def expression
|
def expression
|
||||||
|
comparison
|
||||||
|
end
|
||||||
|
|
||||||
|
# comparison := primary ((">=" | ">" | "<" | "<=" | ... ) primary)*
|
||||||
|
def comparison
|
||||||
|
expr = primary
|
||||||
|
while look(:comparison)
|
||||||
|
operator = consume
|
||||||
|
expr = BinaryExpression.new(expr, operator, primary)
|
||||||
|
end
|
||||||
|
expr
|
||||||
|
end
|
||||||
|
|
||||||
|
def primary
|
||||||
token = @tokens[@p]
|
token = @tokens[@p]
|
||||||
case token[0]
|
case token[0]
|
||||||
when :id
|
when :id
|
||||||
|
|||||||
@@ -77,6 +77,30 @@ class ParserUnitTest < Minitest::Test
|
|||||||
assert_equal(0..5, p.expression)
|
assert_equal(0..5, p.expression)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_comparison
|
||||||
|
p = new_parser("a > b")
|
||||||
|
expr = p.expression
|
||||||
|
assert(expr.is_a?(BinaryExpression))
|
||||||
|
assert_equal('>', expr.operator)
|
||||||
|
assert(expr.left.is_a?(VariableLookup))
|
||||||
|
assert_equal('a', expr.left.name)
|
||||||
|
assert(expr.right.is_a?(VariableLookup))
|
||||||
|
assert_equal('b', expr.right.name)
|
||||||
|
|
||||||
|
# BinaryExpression(>=)
|
||||||
|
# left: BinaryExpression(>)
|
||||||
|
# left: 10
|
||||||
|
# right: 5
|
||||||
|
# right: 4
|
||||||
|
p = new_parser("10 > 5 >= 4")
|
||||||
|
expr = p.expression
|
||||||
|
assert(expr.is_a?(BinaryExpression))
|
||||||
|
assert_equal('>=', expr.operator)
|
||||||
|
assert_equal(10, expr.left.left)
|
||||||
|
assert_equal(5, expr.left.right)
|
||||||
|
assert_equal(4, expr.right)
|
||||||
|
end
|
||||||
|
|
||||||
def test_number
|
def test_number
|
||||||
p = new_parser('-1 0 1 2.0')
|
p = new_parser('-1 0 1 2.0')
|
||||||
assert_equal(-1, p.number)
|
assert_equal(-1, p.number)
|
||||||
|
|||||||
Reference in New Issue
Block a user