@@ -241,6 +241,7 @@ def __init__(self, *, env: JSONPathEnvironment) -> None:
241241 TOKEN_FUNCTION : self .parse_function_extension ,
242242 TOKEN_INT : self .parse_integer_literal ,
243243 TOKEN_KEY : self .parse_current_key ,
244+ TOKEN_LBRACKET : self .parse_list_literal ,
244245 TOKEN_LPAREN : self .parse_grouped_expression ,
245246 TOKEN_MISSING : self .parse_undefined ,
246247 TOKEN_NIL : self .parse_nil ,
@@ -293,9 +294,6 @@ def parse(self, stream: TokenStream) -> Iterator[JSONPathSegment]:
293294 if stream .current ().kind in {TOKEN_ROOT , TOKEN_PSEUDO_ROOT }:
294295 stream .next ()
295296
296- # TODO: Support "bare" paths. Those without a leading dot for shorthand
297- # selectors
298-
299297 yield from self .parse_path (stream )
300298
301299 if stream .current ().kind not in (TOKEN_EOF , TOKEN_INTERSECTION , TOKEN_UNION ):
@@ -312,18 +310,18 @@ def parse_path(self, stream: TokenStream) -> Iterable[JSONPathSegment]:
312310 """
313311 while True :
314312 stream .skip_whitespace ()
315- if stream .current (). kind == TOKEN_DOT :
316- # Consume the dot.
317- stream .next ( )
313+ _token = stream .current ()
314+ if _token . kind == TOKEN_DOT :
315+ stream .eat ( TOKEN_DOT )
318316 # Assert that dot is followed by shorthand selector without whitespace.
319317 stream .expect (TOKEN_NAME , TOKEN_WILD , TOKEN_KEYS )
320318 token = stream .current ()
321319 selectors = self .parse_selectors (stream )
322320 yield JSONPathChildSegment (
323321 env = self .env , token = token , selectors = selectors
324322 )
325- elif stream . current () .kind == TOKEN_DDOT :
326- token = stream .next ( )
323+ elif _token .kind == TOKEN_DDOT :
324+ token = stream .eat ( TOKEN_DDOT )
327325 selectors = self .parse_selectors (stream )
328326 if not selectors :
329327 raise JSONPathSyntaxError (
@@ -333,7 +331,14 @@ def parse_path(self, stream: TokenStream) -> Iterable[JSONPathSegment]:
333331 yield JSONPathRecursiveDescentSegment (
334332 env = self .env , token = token , selectors = selectors
335333 )
336- elif stream .current ().kind == TOKEN_LBRACKET :
334+ elif _token .kind == TOKEN_LBRACKET :
335+ selectors = self .parse_selectors (stream )
336+ yield JSONPathChildSegment (
337+ env = self .env , token = _token , selectors = selectors
338+ )
339+ elif _token .kind in {TOKEN_NAME , TOKEN_WILD , TOKEN_KEYS }:
340+ # A non-standard "bare" path. One without a leading identifier (`$`,
341+ # `@`, `^` or `_`).
337342 token = stream .current ()
338343 selectors = self .parse_selectors (stream )
339344 yield JSONPathChildSegment (
@@ -377,6 +382,7 @@ def parse_selectors(self, stream: TokenStream) -> tuple[JSONPathSelector, ...]:
377382 stream .pos -= 1
378383 return tuple (self .parse_bracketed_selection (stream ))
379384
385+ stream .pos -= 1
380386 return ()
381387
382388 def parse_bracketed_selection (self , stream : TokenStream ) -> List [JSONPathSelector ]: # noqa: PLR0912
@@ -446,15 +452,14 @@ def parse_bracketed_selection(self, stream: TokenStream) -> List[JSONPathSelecto
446452 token = token ,
447453 )
448454
449- # XXX:
450- # if stream.peek().kind == TOKEN_EOF:
451- # raise JSONPathSyntaxError(
452- # "unexpected end of segment",
453- # token=stream.current(),
454- # )
455-
456455 stream .skip_whitespace ()
457456
457+ if stream .current ().kind == TOKEN_EOF :
458+ raise JSONPathSyntaxError (
459+ "unexpected end of segment" ,
460+ token = stream .current (),
461+ )
462+
458463 if stream .current ().kind != TOKEN_RBRACKET :
459464 stream .eat (TOKEN_COMMA )
460465 stream .skip_whitespace ()
@@ -665,7 +670,12 @@ def parse_list_literal(self, stream: TokenStream) -> FilterExpression:
665670 stream .eat (TOKEN_LBRACKET )
666671 list_items : List [FilterExpression ] = []
667672
668- while stream .current ().kind != TOKEN_RBRACKET :
673+ while True :
674+ stream .skip_whitespace ()
675+
676+ if stream .current ().kind == TOKEN_RBRACKET :
677+ break
678+
669679 try :
670680 list_items .append (self .list_item_map [stream .current ().kind ](stream ))
671681 except KeyError as err :
@@ -674,11 +684,10 @@ def parse_list_literal(self, stream: TokenStream) -> FilterExpression:
674684 token = stream .current (),
675685 ) from err
676686
677- if stream .peek ().kind != TOKEN_RBRACKET :
678- stream .expect_peek (TOKEN_COMMA )
679- stream .next ()
680-
681- stream .next ()
687+ stream .skip_whitespace ()
688+ if stream .current ().kind != TOKEN_RBRACKET :
689+ stream .eat (TOKEN_COMMA )
690+ stream .skip_whitespace ()
682691
683692 stream .eat (TOKEN_RBRACKET )
684693 return ListLiteral (list_items )
0 commit comments