@@ -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