@@ -42,14 +42,7 @@ fn parse_pattern_atom(tokens: &mut Tokens) -> Result<Pattern> {
4242 Some ( TokenTree :: Group ( group) ) if group. delimiter ( ) == Delimiter :: Parenthesis => {
4343 let group = expect_group ( tokens, Delimiter :: Parenthesis ) ?;
4444 let mut inner = group. stream ( ) . into_iter ( ) . peekable ( ) ;
45- let pattern = parse_parenthesized_pattern ( & mut inner) ?;
46- if let Some ( token) = inner. next ( ) {
47- return Err ( syn:: Error :: new_spanned (
48- token,
49- "unexpected token in query node" ,
50- ) ) ;
51- }
52- Ok ( pattern)
45+ parse_parenthesized_pattern ( & mut inner, group. span ( ) )
5346 }
5447 Some ( TokenTree :: Ident ( identifier) ) if * identifier == "_" => {
5548 tokens. next ( ) ;
@@ -65,25 +58,51 @@ fn parse_pattern_atom(tokens: &mut Tokens) -> Result<Pattern> {
6558 }
6659}
6760
68- fn parse_parenthesized_pattern ( tokens : & mut Tokens ) -> Result < Pattern > {
61+ fn parse_parenthesized_pattern ( tokens : & mut Tokens , span : Span ) -> Result < Pattern > {
6962 match tokens. peek ( ) {
70- None => Err ( syn:: Error :: new (
71- Span :: call_site ( ) ,
72- "empty parenthesized group in query" ,
73- ) ) ,
63+ None => Err ( syn:: Error :: new ( span, "empty query groups are not allowed" ) ) ,
7464 Some ( TokenTree :: Ident ( identifier) ) if * identifier == "_" => {
7565 tokens. next ( ) ;
76- Ok ( Pattern :: Any {
77- match_unnamed : false ,
78- } )
66+ if tokens. peek ( ) . is_none ( ) {
67+ Ok ( Pattern :: Any {
68+ match_unnamed : false ,
69+ } )
70+ } else {
71+ let mut patterns = vec ! [ Pattern :: Any {
72+ match_unnamed: true ,
73+ } ] ;
74+ patterns. extend ( parse_pattern_list ( tokens) ?) ;
75+ finish_sequence ( tokens, patterns, span)
76+ }
77+ }
78+ Some ( TokenTree :: Literal ( _) ) => {
79+ let first = Pattern :: Unnamed ( expect_string_literal ( tokens) ?) ;
80+ if tokens. peek ( ) . is_none ( ) {
81+ Ok ( first)
82+ } else {
83+ let mut patterns = vec ! [ first] ;
84+ patterns. extend ( parse_pattern_list ( tokens) ?) ;
85+ finish_sequence ( tokens, patterns, span)
86+ }
7987 }
80- Some ( TokenTree :: Literal ( _) ) => Ok ( Pattern :: Unnamed ( expect_string_literal ( tokens) ?) ) ,
8188 Some ( TokenTree :: Ident ( _) ) => {
8289 let kind = expect_ident ( tokens, "expected node kind" ) ?. to_string ( ) ;
83- Ok ( Pattern :: Node {
90+ let pattern = Pattern :: Node {
8491 kind,
8592 fields : parse_pattern_fields ( tokens) ?,
86- } )
93+ } ;
94+ if let Some ( token) = tokens. next ( ) {
95+ Err ( syn:: Error :: new_spanned (
96+ token,
97+ "unexpected token in query node" ,
98+ ) )
99+ } else {
100+ Ok ( pattern)
101+ }
102+ }
103+ Some ( TokenTree :: Group ( group) ) if group. delimiter ( ) == Delimiter :: Parenthesis => {
104+ let patterns = parse_pattern_list ( tokens) ?;
105+ finish_sequence ( tokens, patterns, span)
87106 }
88107 Some ( token) => Err ( syn:: Error :: new_spanned (
89108 token. clone ( ) ,
@@ -92,6 +111,23 @@ fn parse_parenthesized_pattern(tokens: &mut Tokens) -> Result<Pattern> {
92111 }
93112}
94113
114+ fn finish_sequence ( tokens : & mut Tokens , patterns : Vec < Pattern > , span : Span ) -> Result < Pattern > {
115+ if let Some ( token) = tokens. next ( ) {
116+ return Err ( syn:: Error :: new_spanned (
117+ token,
118+ "unexpected token in query sequence" ,
119+ ) ) ;
120+ }
121+ match patterns. len ( ) {
122+ 0 => Err ( syn:: Error :: new ( span, "empty query groups are not allowed" ) ) ,
123+ 1 => Err ( syn:: Error :: new (
124+ span,
125+ "single-pattern query groups are not allowed; remove the redundant parentheses" ,
126+ ) ) ,
127+ _ => Ok ( Pattern :: Sequence ( patterns) ) ,
128+ }
129+ }
130+
95131fn parse_pattern_fields ( tokens : & mut Tokens ) -> Result < Vec < ( String , Pattern ) > > {
96132 let mut fields = Vec :: new ( ) ;
97133 let mut bare_children = Vec :: new ( ) ;
@@ -152,33 +188,14 @@ fn parse_pattern_list(tokens: &mut Tokens) -> Result<Vec<Pattern>> {
152188 let mut inner = group. stream ( ) . into_iter ( ) . peekable ( ) ;
153189 if peek_is_repetition ( tokens) {
154190 let cardinality = expect_cardinality ( tokens) ?;
155- let is_single_pattern = matches ! ( inner. peek( ) , Some ( TokenTree :: Ident ( _) ) ) ;
156- let repeated = if is_single_pattern {
157- parse_parenthesized_pattern ( & mut inner) ?
158- } else {
159- let patterns = parse_pattern_list ( & mut inner) ?;
160- if patterns. is_empty ( ) {
161- return Err ( syn:: Error :: new (
162- group. span ( ) ,
163- "empty query groups are not allowed" ,
164- ) ) ;
165- }
166- if patterns. len ( ) == 1 {
167- return Err ( syn:: Error :: new (
168- group. span ( ) ,
169- "single-pattern query groups are not allowed; \
170- remove the redundant parentheses",
171- ) ) ;
172- }
173- Pattern :: Sequence ( patterns)
174- } ;
191+ let repeated = parse_parenthesized_pattern ( & mut inner, group. span ( ) ) ?;
175192 let repeated = Pattern :: Repeated {
176193 pattern : Box :: new ( repeated) ,
177194 cardinality,
178195 } ;
179196 patterns. push ( maybe_capture ( tokens, repeated) ?) ;
180197 } else {
181- let pattern = parse_parenthesized_pattern ( & mut inner) ?;
198+ let pattern = parse_parenthesized_pattern ( & mut inner, group . span ( ) ) ?;
182199 patterns. push ( maybe_capture ( tokens, pattern) ?) ;
183200 }
184201 continue ;
@@ -593,4 +610,71 @@ mod tests {
593610 "cannot capture a query sequence; capture the desired nodes explicitly"
594611 ) ;
595612 }
613+
614+ #[ test]
615+ fn parses_literal_led_repeated_sequence ( ) {
616+ let pattern = parse_pattern ( quote ! ( ( root ( "+" "," ) * ) ) ) . unwrap ( ) ;
617+ let Pattern :: Node { fields, .. } = pattern else {
618+ panic ! ( "expected root node" ) ;
619+ } ;
620+ let Pattern :: Sequence ( children) = & fields[ 0 ] . 1 else {
621+ panic ! ( "expected child sequence" ) ;
622+ } ;
623+ let Pattern :: Repeated {
624+ pattern : repeated, ..
625+ } = & children[ 0 ]
626+ else {
627+ panic ! ( "expected repetition" ) ;
628+ } ;
629+ assert ! ( matches!(
630+ repeated. as_ref( ) ,
631+ Pattern :: Sequence ( patterns)
632+ if matches!(
633+ patterns. as_slice( ) ,
634+ [ Pattern :: Unnamed ( left) , Pattern :: Unnamed ( right) ]
635+ if left == "+" && right == ","
636+ )
637+ ) ) ;
638+ }
639+
640+ #[ test]
641+ fn parses_wildcard_led_repeated_sequence ( ) {
642+ let pattern = parse_pattern ( quote ! ( ( root ( _ "," ) * ) ) ) . unwrap ( ) ;
643+ let Pattern :: Node { fields, .. } = pattern else {
644+ panic ! ( "expected root node" ) ;
645+ } ;
646+ let Pattern :: Sequence ( children) = & fields[ 0 ] . 1 else {
647+ panic ! ( "expected child sequence" ) ;
648+ } ;
649+ let Pattern :: Repeated {
650+ pattern : repeated, ..
651+ } = & children[ 0 ]
652+ else {
653+ panic ! ( "expected repetition" ) ;
654+ } ;
655+ assert ! ( matches!(
656+ repeated. as_ref( ) ,
657+ Pattern :: Sequence ( patterns)
658+ if matches!(
659+ patterns. as_slice( ) ,
660+ [
661+ Pattern :: Any {
662+ match_unnamed: true
663+ } ,
664+ Pattern :: Unnamed ( comma)
665+ ] if comma == ","
666+ )
667+ ) ) ;
668+ }
669+
670+ #[ test]
671+ fn rejects_unconsumed_node_pattern_tokens ( ) {
672+ for query in [ quote ! ( ( root ( foo . ( bar) @x) ) ) , quote ! ( ( root( bar @ x) ) ) ] {
673+ let result = parse_pattern ( query) ;
674+ let Err ( error) = result else {
675+ panic ! ( "expected malformed node pattern to be rejected" ) ;
676+ } ;
677+ assert ! ( error. to_string( ) . starts_with( "unexpected token" ) ) ;
678+ }
679+ }
596680}
0 commit comments