mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-20 03:10:39 -07:00
Annotate Parser with grammar rules
This commit is contained in:
+23
-3
@@ -13,6 +13,8 @@ module Liquid
|
|||||||
@p = point
|
@p = point
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Consumes a token of specific type.
|
||||||
|
# Throws SyntaxError if token doesn't match type expectation.
|
||||||
def consume(type = nil)
|
def consume(type = nil)
|
||||||
token = @tokens[@p]
|
token = @tokens[@p]
|
||||||
if type && token[0] != type
|
if type && token[0] != type
|
||||||
@@ -41,6 +43,7 @@ module Liquid
|
|||||||
token[1]
|
token[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Peeks the ahead token, returning true if matching expectation
|
||||||
def look(type, ahead = 0)
|
def look(type, ahead = 0)
|
||||||
tok = @tokens[@p + ahead]
|
tok = @tokens[@p + ahead]
|
||||||
return false unless tok
|
return false unless tok
|
||||||
@@ -51,7 +54,7 @@ module Liquid
|
|||||||
# logical := equality (("and" | "or") equality)*
|
# logical := equality (("and" | "or") equality)*
|
||||||
# equality := comparison (("==" | "!=" | "<>") comparison)*
|
# equality := comparison (("==" | "!=" | "<>") comparison)*
|
||||||
# comparison := primary ((">=" | ">" | "<" | "<=" | ... ) primary)*
|
# comparison := primary ((">=" | ">" | "<" | "<=" | ... ) primary)*
|
||||||
# primary := string | number | variable_lookup | range | boolean
|
# primary := string | number | variable_lookup | range | boolean | grouping
|
||||||
def expression
|
def expression
|
||||||
logical
|
logical
|
||||||
end
|
end
|
||||||
@@ -60,7 +63,8 @@ module Liquid
|
|||||||
# associative. This creates a right-leaning tree and is why the method
|
# associative. This creates a right-leaning tree and is why the method
|
||||||
# looks a bit more complicated
|
# looks a bit more complicated
|
||||||
#
|
#
|
||||||
# `a == b and b or c` is evaluated like (a and (b or c))
|
# `a and b or c` is evaluated like (a and (b or c))
|
||||||
|
# logical := equality (("and" | "or") equality)*
|
||||||
def logical
|
def logical
|
||||||
operator = nil
|
operator = nil
|
||||||
expr = equality
|
expr = equality
|
||||||
@@ -69,6 +73,7 @@ module Liquid
|
|||||||
expr
|
expr
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# equality := comparison (("==" | "!=" | "<>") comparison)*
|
||||||
def equality
|
def equality
|
||||||
expr = comparison
|
expr = comparison
|
||||||
while look(:equality)
|
while look(:equality)
|
||||||
@@ -88,11 +93,12 @@ module Liquid
|
|||||||
expr
|
expr
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# primary := string | number | variable_lookup | range | boolean | grouping
|
||||||
def primary
|
def primary
|
||||||
token = @tokens[@p]
|
token = @tokens[@p]
|
||||||
case token[0]
|
case token[0]
|
||||||
when :id
|
when :id
|
||||||
variable_lookup
|
variable_lookup_or_literal
|
||||||
when :open_square
|
when :open_square
|
||||||
unnamed_variable_lookup
|
unnamed_variable_lookup
|
||||||
when :string
|
when :string
|
||||||
@@ -115,7 +121,18 @@ module Liquid
|
|||||||
consume(:string)[1..-2]
|
consume(:string)[1..-2]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# variable_lookup := id (lookup)*
|
||||||
|
# lookup := indexed_lookup | dot_lookup
|
||||||
|
# indexed_lookup := "[" expression "]"
|
||||||
|
# dot_lookup := "." id
|
||||||
def variable_lookup
|
def variable_lookup
|
||||||
|
name = consume(:id)
|
||||||
|
lookups, command_flags = variable_lookups
|
||||||
|
VariableLookup.new(name, lookups, command_flags)
|
||||||
|
end
|
||||||
|
|
||||||
|
# a variable_lookup without lookups could be a literal
|
||||||
|
def variable_lookup_or_literal
|
||||||
name = consume(:id)
|
name = consume(:id)
|
||||||
lookups, command_flags = variable_lookups
|
lookups, command_flags = variable_lookups
|
||||||
if Expression::LITERALS.key?(name) && lookups.empty?
|
if Expression::LITERALS.key?(name) && lookups.empty?
|
||||||
@@ -125,6 +142,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# unnamed_variable_lookup := indexed_lookup (lookup)*
|
||||||
def unnamed_variable_lookup
|
def unnamed_variable_lookup
|
||||||
name = indexed_lookup
|
name = indexed_lookup
|
||||||
lookups, command_flags = variable_lookups
|
lookups, command_flags = variable_lookups
|
||||||
@@ -132,6 +150,7 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Parenthesized expressions are recursive
|
# Parenthesized expressions are recursive
|
||||||
|
# grouping := "(" expression ")"
|
||||||
def grouping_or_range_lookup
|
def grouping_or_range_lookup
|
||||||
consume(:open_round)
|
consume(:open_round)
|
||||||
expr = expression
|
expr = expression
|
||||||
@@ -144,6 +163,7 @@ module Liquid
|
|||||||
consume(:close_round)
|
consume(:close_round)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# range_lookup := "(" expression ".." expression ")"
|
||||||
def range_lookup
|
def range_lookup
|
||||||
consume(:open_round)
|
consume(:open_round)
|
||||||
first = expression
|
first = expression
|
||||||
|
|||||||
Reference in New Issue
Block a user