tt_call/rust/
path.rs

1#[doc(hidden)]
2#[macro_export]
3macro_rules! private_parse_path {
4    // Entry point. Dup tokens.
5    {
6        $caller:tt
7        input = [{ $($input:tt)* }]
8    } => {
9        $crate::private_parse_path! {
10            $caller
11            tokens = [{ $($input)* }]
12            _tokens = [{ $($input)* }]
13        }
14    };
15
16    // Parse absolute path.
17    {
18        $caller:tt
19        tokens = [{ :: $_segment:ident $($rest:tt)* }]
20        _tokens = [{ $colons:tt $segment:tt $($dup:tt)* }]
21    } => {
22        $crate::tt_call! {
23            macro = [{ $crate::private_parse_possibly_empty_path_after_ident }]
24            input = [{ $($rest)* }]
25            ~~> $crate::private_parse_path! {
26                $caller
27                prefix = [{ $colons $segment }]
28            }
29        }
30    };
31
32    // Parse relative path.
33    {
34        $caller:tt
35        tokens = [{ $_segment:ident $($rest:tt)* }]
36        _tokens = [{ $segment:tt $($dup:tt)* }]
37    } => {
38        $crate::tt_call! {
39            macro = [{ $crate::private_parse_possibly_empty_path_after_ident }]
40            input = [{ $($rest)* }]
41            ~~> $crate::private_parse_path! {
42                $caller
43                prefix = [{ $segment }]
44            }
45        }
46    };
47
48    // Return path.
49    {
50        $caller:tt
51        prefix = [{ $($prefix:tt)* }]
52        path = [{ $($path:tt)* }]
53        rest = [{ $($rest:tt)* }]
54    } => {
55        $crate::tt_return! {
56            $caller
57            path = [{ $($prefix)* $($path)* }]
58            rest = [{ $($rest)* }]
59        }
60    };
61
62}
63
64#[doc(hidden)]
65#[macro_export]
66macro_rules! private_parse_possibly_empty_path_after_ident {
67    // Entry point. Dup tokens.
68    {
69        $caller:tt
70        input = [{ $($input:tt)* }]
71    } => {
72        $crate::private_parse_possibly_empty_path_after_ident! {
73            $caller
74            path = [{ }]
75            tokens = [{ $($input)* }]
76            _tokens = [{ $($input)* }]
77        }
78    };
79
80    // Parse empty angle brackets.
81    {
82        $caller:tt
83        path = [{ $($path:tt)* }]
84        tokens = [{ < > $($rest:tt)* }]
85        _tokens = [{ $lt:tt $gt:tt $($dup:tt)* }]
86    } => {
87        $crate::private_parse_possibly_empty_path_after_close_angle! {
88            $caller
89            path = [{ $($path)* $lt $gt }]
90            tokens = [{ $($rest)* }]
91        }
92    };
93
94    // Unexpected: input ends after open angle bracket.
95    {
96        $caller:tt
97        path = [{ $($path:tt)* }]
98        tokens = [{ < }]
99        _tokens = [{ $unexpected:tt }]
100    } => {
101        $crate::error_unexpected! {
102            $unexpected
103        }
104    };
105
106    // Parse generic param inside of angle brackets.
107    {
108        $caller:tt
109        path = [{ $($path:tt)* }]
110        tokens = [{ < $($rest:tt)+ }]
111        _tokens = [{ $lt:tt $($dup:tt)* }]
112    } => {
113        $crate::tt_call! {
114            macro = [{ $crate::private_parse_generic_param }]
115            input = [{ $($rest)* }]
116            ~~> $crate::private_parse_in_angle_brackets! {
117                $caller
118                prefix = [{ $($path)* $lt }]
119            }
120        }
121    };
122
123    // Parse empty turbofish.
124    {
125        $caller:tt
126        path = [{ $($path:tt)* }]
127        tokens = [{ :: < > $($rest:tt)* }]
128        _tokens = [{ $colons:tt $lt:tt $gt:tt $($dup:tt)* }]
129    } => {
130        $crate::private_parse_possibly_empty_path_after_close_angle! {
131            $caller
132            path = [{ $($path)* $colons $lt $gt }]
133            tokens = [{ $($rest)* }]
134        }
135    };
136
137    // Parse generic param inside of turbofish.
138    {
139        $caller:tt
140        path = [{ $($path:tt)* }]
141        tokens = [{ :: < $($rest:tt)+ }]
142        _tokens = [{ $colons:tt $lt:tt $($dup:tt)* }]
143    } => {
144        $crate::tt_call! {
145            macro = [{ $crate::private_parse_generic_param }]
146            input = [{ $($rest)* }]
147            ~~> $crate::private_parse_in_angle_brackets! {
148                $caller
149                prefix = [{ $($path)* $colons $lt }]
150            }
151        }
152    };
153
154    // Parse parenthesized parameter data.
155    {
156        $caller:tt
157        path = [{ $($path:tt)* }]
158        tokens = [{ ($($args:tt)*) $($rest:tt)* }]
159        _tokens = [{ $original:tt $($dup:tt)* }]
160    } => {
161        $crate::tt_call! {
162            macro = [{ $crate::private_validate_fn_path_args }]
163            tokens = [{ $($args)* }]
164            ~~> $crate::private_parse_path_after_fn_args! {
165                $caller
166                path = [{ $($path)* $original }]
167                tokens = [{ $($rest)* }]
168            }
169        }
170    };
171
172    // Anything after close angle is allowed after ident.
173    {
174        $caller:tt
175        path = [{ $($path:tt)* }]
176        tokens = [{ $($tokens:tt)* }]
177        _tokens = [{ $($dup:tt)* }]
178    } => {
179        $crate::private_parse_possibly_empty_path_after_close_angle! {
180            $caller
181            path = [{ $($path)* }]
182            tokens = [{ $($tokens)* }]
183        }
184    };
185}
186
187#[doc(hidden)]
188#[macro_export]
189macro_rules! private_parse_possibly_empty_path_after_close_angle {
190    // Entry point. Dup tokens.
191    {
192        $caller:tt
193        path = [{ $($path:tt)* }]
194        tokens = [{ $($tokens:tt)* }]
195    } => {
196        $crate::private_parse_possibly_empty_path_after_close_angle! {
197            $caller
198            path = [{ $($path)* }]
199            tokens = [{ $($tokens)* }]
200            _tokens = [{ $($tokens)* }]
201        }
202    };
203
204    // Parse path segment.
205    {
206        $caller:tt
207        path = [{ $($path:tt)* }]
208        tokens = [{ :: $_segment:ident $($rest:tt)* }]
209        _tokens = [{ $colons:tt $segment:tt $($dup:tt)* }]
210    } => {
211        $crate::private_parse_possibly_empty_path_after_ident! {
212            $caller
213            path = [{ $($path)* $colons $segment }]
214            tokens = [{ $($rest)* }]
215            _tokens = [{ $($rest)* }]
216        }
217    };
218
219    // Unexpected: double colon is followed by something other than ident.
220    {
221        $caller:tt
222        path = [{ $($path:tt)* }]
223        tokens = [{ :: $($unexpected:tt)+ }]
224        _tokens = [{ $($dup:tt)* }]
225    } => {
226        $crate::error_unexpected! {
227            $($unexpected)*
228        }
229    };
230
231    // Not a double colon. End of path.
232    {
233        $caller:tt
234        path = [{ $($path:tt)* }]
235        tokens = [{ $($rest:tt)* }]
236        _tokens = [{ $($dup:tt)* }]
237    } => {
238        $crate::tt_return! {
239            $caller
240            path = [{ $($path)* }]
241            rest = [{ $($rest)* }]
242        }
243    };
244}
245
246#[doc(hidden)]
247#[macro_export]
248macro_rules! private_parse_in_angle_brackets {
249    // Entry point. Dup rest tokens.
250    {
251        $caller:tt
252        prefix = [{ $($path:tt)* }]
253        param = [{ $($param:tt)* }]
254        rest = [{ $($rest:tt)* }]
255    } => {
256        $crate::private_parse_in_angle_brackets! {
257            $caller
258            prefix = [{ $($path)* }]
259            param = [{ $($param)* }]
260            rest = [{ $($rest)* }]
261            _rest = [{ $($rest)* }]
262        }
263    };
264
265    // End of angle bracketed path parameters. Parse rest of path.
266    {
267        $caller:tt
268        prefix = [{ $($path:tt)* }]
269        param = [{ $($param:tt)* }]
270        rest = [{ > $($rest:tt)* }]
271        _rest = [{ $gt:tt $($dup:tt)* }]
272    } => {
273        $crate::private_parse_possibly_empty_path_after_close_angle! {
274            $caller
275            path = [{ $($path)* $($param)* $gt }]
276            tokens = [{ $($rest)* }]
277        }
278    };
279
280    // Split a `>>` token into `> >`.
281    {
282        $caller:tt
283        prefix = [{ $($path:tt)* }]
284        param = [{ $($param:tt)* }]
285        rest = [{ >> $($rest:tt)* }]
286        _rest = [{ $($dup:tt)* }]
287    } => {
288        $crate::tt_return! {
289            $caller
290            path = [{ $($path)* $($param)* > }]
291            rest = [{ > $($rest)* }]
292        }
293    };
294
295    // End of angle bracketed path paremeters with trailing comma.
296    {
297        $caller:tt
298        prefix = [{ $($path:tt)* }]
299        param = [{ $($param:tt)* }]
300        rest = [{ , > $($rest:tt)* }]
301        _rest = [{ $comma:tt $gt:tt $($dup:tt)* }]
302    } => {
303        $crate::private_parse_possibly_empty_path_after_close_angle! {
304            $caller
305            path = [{ $($path)* $($param)* $comma $gt }]
306            tokens = [{ $($rest)* }]
307        }
308    };
309
310    // Split a `>>` token into `> >`.
311    {
312        $caller:tt
313        prefix = [{ $($path:tt)* }]
314        param = [{ $($param:tt)* }]
315        rest = [{ , >> $($rest:tt)* }]
316        _rest = [{ $comma:tt $($dup:tt)* }]
317    } => {
318        $crate::tt_return! {
319            $caller
320            path = [{ $($path)* $($param)* $comma > }]
321            rest = [{ > $($rest)* }]
322        }
323    };
324
325    // Parse generic parameter after comma.
326    {
327        $caller:tt
328        prefix = [{ $($path:tt)* }]
329        param = [{ $($param:tt)* }]
330        rest = [{ , $($rest:tt)+ }]
331        _rest = [{ $comma:tt $($dup:tt)* }]
332    } => {
333        $crate::tt_call! {
334            macro = [{ $crate::private_parse_generic_param }]
335            input = [{ $($rest)* }]
336            ~~> $crate::private_parse_in_angle_brackets! {
337                $caller
338                prefix = [{ $($path)* $($param)* $comma }]
339            }
340        }
341    };
342
343    // Unexpected: generic parameter is not followed by `>` or comma.
344    {
345        $caller:tt
346        prefix = [{ $($path:tt)* }]
347        param = [{ $($param:tt)* }]
348        rest = [{ $($unexpected:tt)+ }]
349        _rest = [{ $($dup:tt)* }]
350    } => {
351        $crate::error_unexpected! {
352            $($unexpected)*
353        }
354    };
355
356    // Unexpected: input ends inside of angle brackets.
357    {
358        $caller:tt
359        prefix = [{ $($path:tt)* }]
360        param = [{ $($param:tt)+ }]
361        rest = [{ }]
362        _rest = [{ }]
363    } => {
364        $crate::error_unexpected_last! {
365            $($param)*
366        }
367    };
368
369}
370
371#[doc(hidden)]
372#[macro_export]
373macro_rules! private_parse_generic_param {
374    // Parse lifetime parameters.
375    {
376        $caller:tt
377        input = [{ $lifetime:lifetime $($rest:tt)* }]
378    } => {
379        $crate::tt_return! {
380            $caller
381            param = [{ $lifetime }]
382            rest = [{ $($rest)* }]
383        }
384    };
385
386    // Parse associated type parameter.
387    {
388        $caller:tt
389        input = [{ $assoc:ident = $($rest:tt)+ }]
390    } => {
391        $crate::tt_call! {
392            macro = [{ $crate::parse_type }]
393            input = [{ $($rest)* }]
394            ~~> $crate::private_parse_generic_param! {
395                $caller
396                assoc = [{ $assoc = }]
397            }
398        }
399    };
400
401    // Return from parsing associated type parameter.
402    {
403        $caller:tt
404        assoc = [{ $assoc:ident $eq:tt }]
405        type = [{ $($ty:tt)* }]
406        rest = [{ $($rest:tt)* }]
407    } => {
408        $crate::tt_return! {
409            $caller
410            param = [{ $assoc $eq $($ty)* }]
411            rest = [{ $($rest)* }]
412        }
413    };
414
415    // Parse type parameter.
416    {
417        $caller:tt
418        input = [{ $($input:tt)+ }]
419    } => {
420        $crate::tt_call! {
421            macro = [{ $crate::private_parse_type_with_plus }]
422            input = [{ $($input)* }]
423            ~~> $crate::private_parse_generic_param! {
424                $caller
425            }
426        }
427    };
428
429    // Return from parsing type parameter.
430    {
431        $caller:tt
432        type = [{ $($ty:tt)* }]
433        rest = [{ $($rest:tt)* }]
434    } => {
435        $crate::tt_return! {
436            $caller
437            param = [{ $($ty)* }]
438            rest = [{ $($rest)* }]
439        }
440    };
441}
442
443#[doc(hidden)]
444#[macro_export]
445macro_rules! private_validate_fn_path_args {
446    // Function arguments are empty.
447    {
448        $caller:tt
449        tokens = [{ }]
450    } => {
451        $crate::tt_return! {
452            $caller
453        }
454    };
455
456    // Validate first function argument type.
457    {
458        $caller:tt
459        tokens = [{ $($rest:tt)+ }]
460    } => {
461        $crate::tt_call! {
462            macro = [{ $crate::parse_type }]
463            input = [{ $($rest)* }]
464            ~~> $crate::private_validate_fn_path_args! {
465                $caller
466            }
467        }
468    };
469
470    // All function argument types are valid.
471    {
472        $caller:tt
473        type = [{ $($ty:tt)* }]
474        rest = [{ }]
475    } => {
476        $crate::tt_return! {
477            $caller
478        }
479    };
480
481    // Validate next function argument type after comma.
482    {
483        $caller:tt
484        type = [{ $($ty:tt)* }]
485        rest = [{ , $($rest:tt)* }]
486    } => {
487        $crate::private_validate_fn_path_args! {
488            $caller
489            tokens = [{ $($rest)* }]
490        }
491    };
492
493    // Unexpected: function argument type is not followed by comma.
494    {
495        $caller:tt
496        type = [{ $($ty:tt)* }]
497        rest = [{ $($unexpected:tt)+ }]
498    } => {
499        $crate::error_unexpected! {
500            $($unexpected)*
501        }
502    };
503}
504
505#[doc(hidden)]
506#[macro_export]
507macro_rules! private_parse_path_after_fn_args {
508    // Entry point. Dup tokens.
509    {
510        $caller:tt
511        path = [{ $($path:tt)* }]
512        tokens = [{ $($tokens:tt)* }]
513    } => {
514        $crate::private_parse_path_after_fn_args! {
515            $caller
516            path = [{ $($path)* }]
517            tokens = [{ $($tokens)* }]
518            _tokens = [{ $($tokens)* }]
519        }
520    };
521
522    // Parse function return type.
523    {
524        $caller:tt
525        path = [{ $($path:tt)* }]
526        tokens = [{ -> $($rest:tt)* }]
527        _tokens = [{ $arrow:tt $($dup:tt)* }]
528    } => {
529        $crate::tt_call! {
530            macro = [{ $crate::parse_type }]
531            input = [{ $($rest)* }]
532            ~~> $crate::private_parse_path_after_fn_args! {
533                $caller
534                path = [{ $($path)* $arrow }]
535            }
536        }
537    };
538
539    // Function has default return type.
540    {
541        $caller:tt
542        path = [{ $($path:tt)* }]
543        tokens = [{ $($rest:tt)* }]
544        _tokens = [{ $($dup:tt)* }]
545    } => {
546        $crate::tt_return! {
547            $caller
548            path = [{ $($path)* }]
549            rest = [{ $($rest)* }]
550        }
551    };
552
553    // Return from parsing function return type.
554    {
555        $caller:tt
556        path = [{ $($path:tt)* }]
557        type = [{ $($ret:tt)* }]
558        rest = [{ $($rest:tt)* }]
559    } => {
560        $crate::tt_return! {
561            $caller
562            path = [{ $($path)* $($ret)* }]
563            rest = [{ $($rest)* }]
564        }
565    };
566}