11<?php
22namespace JmesPath ;
33
4+ use JmesPath \Lexer as T ;
5+
46/**
57 * JMESPath Pratt parser
68 * @link http://hall.org.ua/halls/wizzard/pdf/Vaughan.Pratt.TDOP.pdf
@@ -13,42 +15,41 @@ class Parser
1315 private $ token ;
1416 private $ tpos ;
1517 private $ expression ;
16- private static $ nullToken = ['type ' => ' eof ' ];
17- private static $ currentNode = ['type ' => ' current ' ];
18+ private static $ nullToken = ['type ' => T:: T_EOF ];
19+ private static $ currentNode = ['type ' => T:: T_CURRENT ];
1820
1921 private static $ bp = [
20- ' eof ' => 0 ,
21- ' quoted_identifier ' => 0 ,
22- ' identifier ' => 0 ,
23- ' rbracket ' => 0 ,
24- ' rparen ' => 0 ,
25- ' comma ' => 0 ,
26- ' rbrace ' => 0 ,
27- ' number ' => 0 ,
28- ' current ' => 0 ,
29- ' expref ' => 0 ,
30- ' colon ' => 0 ,
31- ' pipe ' => 1 ,
32- ' comparator ' => 2 ,
33- ' or ' => 5 ,
34- ' flatten ' => 6 ,
35- ' star ' => 20 ,
36- ' filter ' => 21 ,
37- ' dot ' => 40 ,
38- ' lbrace ' => 50 ,
39- ' lbracket ' => 55 ,
40- ' lparen ' => 60 ,
22+ T:: T_EOF => 0 ,
23+ T:: T_QUOTED_IDENTIFIER => 0 ,
24+ T:: T_IDENTIFIER => 0 ,
25+ T:: T_RBRACKET => 0 ,
26+ T:: T_RPAREN => 0 ,
27+ T:: T_COMMA => 0 ,
28+ T:: T_RBRACE => 0 ,
29+ T:: T_NUMBER => 0 ,
30+ T:: T_CURRENT => 0 ,
31+ T:: T_EXPREF => 0 ,
32+ T:: T_COLON => 0 ,
33+ T:: T_PIPE => 1 ,
34+ T:: T_COMPARATOR => 2 ,
35+ T:: T_OR => 5 ,
36+ T:: T_FLATTEN => 6 ,
37+ T:: T_STAR => 20 ,
38+ T:: T_FILTER => 21 ,
39+ T:: T_DOT => 40 ,
40+ T:: T_LBRACE => 50 ,
41+ T:: T_LBRACKET => 55 ,
42+ T:: T_LPAREN => 60 ,
4143 ];
4244
4345 /** @var array Acceptable tokens after a dot token */
4446 private static $ afterDot = [
45- 'identifier ' => true , // foo.bar
46- 'quoted_identifier ' => true , // foo."bar"
47- 'star ' => true , // foo.*
48- 'lbrace ' => true , // foo[1]
49- 'lbracket ' => true , // foo{a: 0}
50- 'function ' => true , // foo.*.to_string(@)
51- 'filter ' => true , // foo.[?bar==10]
47+ T::T_IDENTIFIER => true , // foo.bar
48+ T::T_QUOTED_IDENTIFIER => true , // foo."bar"
49+ T::T_STAR => true , // foo.*
50+ T::T_LBRACE => true , // foo[1]
51+ T::T_LBRACKET => true , // foo{a: 0}
52+ T::T_FILTER => true , // foo.[?bar==10]
5253 ];
5354
5455 /**
@@ -75,7 +76,7 @@ public function parse($expression)
7576 $ this ->next ();
7677 $ result = $ this ->expr ();
7778
78- if ($ this ->token ['type ' ] === ' eof ' ) {
79+ if ($ this ->token ['type ' ] === T:: T_EOF ) {
7980 return $ result ;
8081 }
8182
@@ -110,7 +111,7 @@ private function nud_quoted_identifier()
110111 {
111112 $ token = $ this ->token ;
112113 $ this ->next ();
113- $ this ->assertNotToken (' lparen ' );
114+ $ this ->assertNotToken (T:: T_LPAREN );
114115 return ['type ' => 'field ' , 'value ' => $ token ['value ' ]];
115116 }
116117
@@ -130,21 +131,21 @@ private function nud_literal()
130131 private function nud_expref ()
131132 {
132133 $ this ->next ();
133- return ['type ' => ' expref ' , 'children ' => [$ this ->expr (self ::$ bp [' expref ' ])]];
134+ return ['type ' => T:: T_EXPREF , 'children ' => [$ this ->expr (self ::$ bp [T:: T_EXPREF ])]];
134135 }
135136
136137 private function nud_lbrace ()
137138 {
138- static $ validKeys = [' quoted_identifier ' => true , ' identifier ' => true ];
139+ static $ validKeys = [T:: T_QUOTED_IDENTIFIER => true , T:: T_IDENTIFIER => true ];
139140 $ this ->next ($ validKeys );
140141 $ pairs = [];
141142
142143 do {
143144 $ pairs [] = $ this ->parseKeyValuePair ();
144- if ($ this ->token ['type ' ] == ' comma ' ) {
145+ if ($ this ->token ['type ' ] == T:: T_COMMA ) {
145146 $ this ->next ($ validKeys );
146147 }
147- } while ($ this ->token ['type ' ] !== ' rbrace ' );
148+ } while ($ this ->token ['type ' ] !== T:: T_RBRACE );
148149
149150 $ this ->next ();
150151
@@ -170,9 +171,9 @@ private function nud_lbracket()
170171 {
171172 $ this ->next ();
172173 $ type = $ this ->token ['type ' ];
173- if ($ type == ' number ' || $ type == ' colon ' ) {
174+ if ($ type == T:: T_NUMBER || $ type == T:: T_COLON ) {
174175 return $ this ->parseArrayIndexExpression ();
175- } elseif ($ type == ' star ' && $ this ->lookahead () == ' rbracket ' ) {
176+ } elseif ($ type == T:: T_STAR && $ this ->lookahead () == T:: T_RBRACKET ) {
176177 return $ this ->parseWildcardArray ();
177178 } else {
178179 return $ this ->parseMultiSelectList ();
@@ -181,11 +182,11 @@ private function nud_lbracket()
181182
182183 private function led_lbracket (array $ left )
183184 {
184- static $ nextTypes = [' number ' => true , ' colon ' => true , ' star ' => true ];
185+ static $ nextTypes = [T:: T_NUMBER => true , T:: T_COLON => true , T:: T_STAR => true ];
185186 $ this ->next ($ nextTypes );
186187 switch ($ this ->token ['type ' ]) {
187- case ' number ' :
188- case ' colon ' :
188+ case T:: T_NUMBER :
189+ case T:: T_COLON :
189190 return [
190191 'type ' => 'subexpression ' ,
191192 'children ' => [$ left , $ this ->parseArrayIndexExpression ()]
@@ -203,8 +204,8 @@ private function led_flatten(array $left)
203204 'type ' => 'projection ' ,
204205 'from ' => 'array ' ,
205206 'children ' => [
206- ['type ' => ' flatten ' , 'children ' => [$ left ]],
207- $ this ->parseProjection (self ::$ bp [' flatten ' ])
207+ ['type ' => T:: T_FLATTEN , 'children ' => [$ left ]],
208+ $ this ->parseProjection (self ::$ bp [T:: T_FLATTEN ])
208209 ]
209210 ];
210211 }
@@ -213,31 +214,31 @@ private function led_dot(array $left)
213214 {
214215 $ this ->next (self ::$ afterDot );
215216
216- if ($ this ->token ['type ' ] == ' star ' ) {
217+ if ($ this ->token ['type ' ] == T:: T_STAR ) {
217218 return $ this ->parseWildcardObject ($ left );
218219 }
219220
220221 return [
221222 'type ' => 'subexpression ' ,
222- 'children ' => [$ left , $ this ->parseDot (self ::$ bp [' dot ' ])]
223+ 'children ' => [$ left , $ this ->parseDot (self ::$ bp [T:: T_DOT ])]
223224 ];
224225 }
225226
226227 private function led_or (array $ left )
227228 {
228229 $ this ->next ();
229230 return [
230- 'type ' => ' or ' ,
231- 'children ' => [$ left , $ this ->expr (self ::$ bp [' or ' ])]
231+ 'type ' => T:: T_OR ,
232+ 'children ' => [$ left , $ this ->expr (self ::$ bp [T:: T_OR ])]
232233 ];
233234 }
234235
235236 private function led_pipe (array $ left )
236237 {
237238 $ this ->next ();
238239 return [
239- 'type ' => ' pipe ' ,
240- 'children ' => [$ left , $ this ->expr (self ::$ bp [' pipe ' ])]
240+ 'type ' => T:: T_PIPE ,
241+ 'children ' => [$ left , $ this ->expr (self ::$ bp [T:: T_PIPE ])]
241242 ];
242243 }
243244
@@ -246,9 +247,9 @@ private function led_lparen(array $left)
246247 $ args = [];
247248 $ this ->next ();
248249
249- while ($ this ->token ['type ' ] != ' rparen ' ) {
250+ while ($ this ->token ['type ' ] != T:: T_RPAREN ) {
250251 $ args [] = $ this ->expr (0 );
251- if ($ this ->token ['type ' ] == ' comma ' ) {
252+ if ($ this ->token ['type ' ] == T:: T_COMMA ) {
252253 $ this ->next ();
253254 }
254255 }
@@ -266,12 +267,12 @@ private function led_filter(array $left)
266267 {
267268 $ this ->next ();
268269 $ expression = $ this ->expr ();
269- if ($ this ->token ['type ' ] != ' rbracket ' ) {
270+ if ($ this ->token ['type ' ] != T:: T_RBRACKET ) {
270271 throw $ this ->syntax ('Expected a closing rbracket for the filter ' );
271272 }
272273
273274 $ this ->next ();
274- $ rhs = $ this ->parseProjection (self ::$ bp [' filter ' ]);
275+ $ rhs = $ this ->parseProjection (self ::$ bp [T:: T_FILTER ]);
275276
276277 return [
277278 'type ' => 'projection ' ,
@@ -292,7 +293,7 @@ private function led_comparator(array $left)
292293 $ this ->next ();
293294
294295 return [
295- 'type ' => ' comparator ' ,
296+ 'type ' => T:: T_COMPARATOR ,
296297 'value ' => $ token ['value ' ],
297298 'children ' => [$ left , $ this ->expr ()]
298299 ];
@@ -303,10 +304,10 @@ private function parseProjection($bp)
303304 $ type = $ this ->token ['type ' ];
304305 if (self ::$ bp [$ type ] < 10 ) {
305306 return self ::$ currentNode ;
306- } elseif ($ type == ' dot ' ) {
307+ } elseif ($ type == T:: T_DOT ) {
307308 $ this ->next (self ::$ afterDot );
308309 return $ this ->parseDot ($ bp );
309- } elseif ($ type == ' lbracket ' || $ type == ' filter ' ) {
310+ } elseif ($ type == T:: T_LBRACKET || $ type == T:: T_FILTER ) {
310311 return $ this ->expr ($ bp );
311312 }
312313
@@ -315,7 +316,7 @@ private function parseProjection($bp)
315316
316317 private function parseDot ($ bp )
317318 {
318- if ($ this ->token ['type ' ] == ' lbracket ' ) {
319+ if ($ this ->token ['type ' ] == T:: T_LBRACKET ) {
319320 $ this ->next ();
320321 return $ this ->parseMultiSelectList ();
321322 }
@@ -325,7 +326,7 @@ private function parseDot($bp)
325326
326327 private function parseKeyValuePair ()
327328 {
328- static $ validColon = [' colon ' => true ];
329+ static $ validColon = [T:: T_COLON => true ];
329330 $ key = $ this ->token ['value ' ];
330331 $ this ->next ($ validColon );
331332 $ this ->next ();
@@ -346,14 +347,14 @@ private function parseWildcardObject(array $left = null)
346347 'from ' => 'object ' ,
347348 'children ' => [
348349 $ left ?: self ::$ currentNode ,
349- $ this ->parseProjection (self ::$ bp [' star ' ])
350+ $ this ->parseProjection (self ::$ bp [T:: T_STAR ])
350351 ]
351352 ];
352353 }
353354
354355 private function parseWildcardArray (array $ left = null )
355356 {
356- static $ getRbracket = [' rbracket ' => true ];
357+ static $ getRbracket = [T:: T_RBRACKET => true ];
357358 $ this ->next ($ getRbracket );
358359 $ this ->next ();
359360
@@ -362,7 +363,7 @@ private function parseWildcardArray(array $left = null)
362363 'from ' => 'array ' ,
363364 'children ' => [
364365 $ left ?: self ::$ currentNode ,
365- $ this ->parseProjection (self ::$ bp [' star ' ])
366+ $ this ->parseProjection (self ::$ bp [T:: T_STAR ])
366367 ]
367368 ];
368369 }
@@ -373,25 +374,25 @@ private function parseWildcardArray(array $left = null)
373374 private function parseArrayIndexExpression ()
374375 {
375376 static $ matchNext = [
376- ' number ' => true ,
377- ' colon ' => true ,
378- ' rbracket ' => true
377+ T:: T_NUMBER => true ,
378+ T:: T_COLON => true ,
379+ T:: T_RBRACKET => true
379380 ];
380381
381382 $ pos = 0 ;
382383 $ parts = [null , null , null ];
383384 $ expected = $ matchNext ;
384385
385386 do {
386- if ($ this ->token ['type ' ] == ' colon ' ) {
387+ if ($ this ->token ['type ' ] == T:: T_COLON ) {
387388 $ pos ++;
388389 $ expected = $ matchNext ;
389- } elseif ($ this ->token ['type ' ] == ' number ' ) {
390+ } elseif ($ this ->token ['type ' ] == T:: T_NUMBER ) {
390391 $ parts [$ pos ] = $ this ->token ['value ' ];
391- $ expected = [' colon ' => true , ' rbracket ' => true ];
392+ $ expected = [T:: T_COLON => true , T:: T_RBRACKET => true ];
392393 }
393394 $ this ->next ($ expected );
394- } while ($ this ->token ['type ' ] != ' rbracket ' );
395+ } while ($ this ->token ['type ' ] != T:: T_RBRACKET );
395396
396397 // Consume the closing bracket
397398 $ this ->next ();
@@ -411,7 +412,7 @@ private function parseArrayIndexExpression()
411412 'from ' => 'array ' ,
412413 'children ' => [
413414 ['type ' => 'slice ' , 'value ' => $ parts ],
414- $ this ->parseProjection (self ::$ bp [' star ' ])
415+ $ this ->parseProjection (self ::$ bp [T:: T_STAR ])
415416 ]
416417 ];
417418 }
@@ -422,11 +423,11 @@ private function parseMultiSelectList()
422423
423424 do {
424425 $ nodes [] = $ this ->expr ();
425- if ($ this ->token ['type ' ] == ' comma ' ) {
426+ if ($ this ->token ['type ' ] == T:: T_COMMA ) {
426427 $ this ->next ();
427- $ this ->assertNotToken (' rbracket ' );
428+ $ this ->assertNotToken (T:: T_RBRACKET );
428429 }
429- } while ($ this ->token ['type ' ] != ' rbracket ' );
430+ } while ($ this ->token ['type ' ] !== T:: T_RBRACKET );
430431 $ this ->next ();
431432
432433 return ['type ' => 'multi_select_list ' , 'children ' => $ nodes ];
@@ -440,7 +441,7 @@ private function syntax($msg)
440441 private function lookahead ()
441442 {
442443 return (!isset ($ this ->tokens [$ this ->tpos + 1 ]))
443- ? ' eof '
444+ ? T:: T_EOF
444445 : $ this ->tokens [$ this ->tpos + 1 ]['type ' ];
445446 }
446447
0 commit comments