Skip to content

Commit f62b920

Browse files
committed
Annotate Parser with grammar rules
1 parent fd3bd81 commit f62b920

1 file changed

Lines changed: 22 additions & 2 deletions

File tree

lib/liquid/parser.rb

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ def jump(point)
1313
@p = point
1414
end
1515

16+
# Consumes a token of specific type.
17+
# Throws SyntaxError if token doesn't match type expectation.
1618
def consume(type = nil)
1719
token = @tokens[@p]
1820
if type && token[0] != type
@@ -41,6 +43,7 @@ def id?(str)
4143
token[1]
4244
end
4345

46+
# Peeks the ahead token, returning true if matching expectation
4447
def look(type, ahead = 0)
4548
tok = @tokens[@p + ahead]
4649
return false unless tok
@@ -51,7 +54,7 @@ def look(type, ahead = 0)
5154
# logical := equality (("and" | "or") equality)*
5255
# equality := comparison (("==" | "!=" | "<>") comparison)*
5356
# comparison := primary ((">=" | ">" | "<" | "<=" | ... ) primary)*
54-
# primary := string | number | variable_lookup | range | boolean
57+
# primary := string | number | variable_lookup | range | boolean | grouping
5558
def expression
5659
logical
5760
end
@@ -61,6 +64,7 @@ def expression
6164
# looks a bit more complicated
6265
#
6366
# `a == b and b or c` is evaluated like (a and (b or c))
67+
# logical := equality (("and" | "or") equality)*
6468
def logical
6569
operator = nil
6670
expr = equality
@@ -69,6 +73,7 @@ def logical
6973
expr
7074
end
7175

76+
# equality := comparison (("==" | "!=" | "<>") comparison)*
7277
def equality
7378
expr = comparison
7479
while look(:equality)
@@ -88,11 +93,12 @@ def comparison
8893
expr
8994
end
9095

96+
# primary := string | number | variable_lookup | range | boolean | grouping
9197
def primary
9298
token = @tokens[@p]
9399
case token[0]
94100
when :id
95-
variable_lookup
101+
variable_lookup_or_literal
96102
when :open_square
97103
unnamed_variable_lookup
98104
when :string
@@ -115,7 +121,18 @@ def string
115121
consume(:string)[1..-2]
116122
end
117123

124+
# variable_lookup := id (lookup)*
125+
# lookup := indexed_lookup | dot_lookup
126+
# indexed_lookup := "[" expression "]"
127+
# dot_lookup := "." id
118128
def variable_lookup
129+
name = consume(:id)
130+
lookups, command_flags = variable_lookups
131+
VariableLookup.new(name, lookups, command_flags)
132+
end
133+
134+
# a variable_lookup without lookups could be a literal
135+
def variable_lookup_or_literal
119136
name = consume(:id)
120137
lookups, command_flags = variable_lookups
121138
if Expression::LITERALS.key?(name) && lookups.empty?
@@ -125,13 +142,15 @@ def variable_lookup
125142
end
126143
end
127144

145+
# unnamed_variable_lookup := indexed_lookup (lookup)*
128146
def unnamed_variable_lookup
129147
name = indexed_lookup
130148
lookups, command_flags = variable_lookups
131149
VariableLookup.new(name, lookups, command_flags)
132150
end
133151

134152
# Parenthesized expressions are recursive
153+
# grouping := "(" expression ")"
135154
def grouping_or_range_lookup
136155
consume(:open_round)
137156
expr = expression
@@ -144,6 +163,7 @@ def grouping_or_range_lookup
144163
consume(:close_round)
145164
end
146165

166+
# range_lookup := "(" expression ".." expression ")"
147167
def range_lookup
148168
consume(:open_round)
149169
first = expression

0 commit comments

Comments
 (0)