@@ -131,7 +131,7 @@ enum MatcherLoc {
131
131
MetaVarDecl {
132
132
span : Span ,
133
133
bind : Ident ,
134
- kind : NonterminalKind ,
134
+ kind : Option < NonterminalKind > ,
135
135
next_metavar : usize ,
136
136
seq_depth : usize ,
137
137
} ,
@@ -337,26 +337,22 @@ impl TtParser {
337
337
/// recursive. This conversion is fairly cheap and the representation is sufficiently better
338
338
/// for matching than `&[TokenTree]` that it's a clear performance win even with the overhead.
339
339
/// But it might be possible to move the conversion outwards so it only occurs once per macro.
340
- fn compute_locs (
341
- & mut self ,
342
- sess : & ParseSess ,
343
- matcher : & [ TokenTree ] ,
344
- ) -> Result < usize , ( Span , String ) > {
340
+ fn compute_locs ( & mut self , sess : & ParseSess , matcher : & [ TokenTree ] ) -> usize {
345
341
fn inner (
346
342
sess : & ParseSess ,
347
343
tts : & [ TokenTree ] ,
348
344
locs : & mut Vec < MatcherLoc > ,
349
345
next_metavar : & mut usize ,
350
346
seq_depth : usize ,
351
- ) -> Result < ( ) , ( Span , String ) > {
347
+ ) {
352
348
for tt in tts {
353
349
match tt {
354
350
TokenTree :: Token ( token) => {
355
351
locs. push ( MatcherLoc :: Token { token : token. clone ( ) } ) ;
356
352
}
357
353
TokenTree :: Delimited ( _, delimited) => {
358
354
locs. push ( MatcherLoc :: Delimited ) ;
359
- inner ( sess, & delimited. all_tts , locs, next_metavar, seq_depth) ? ;
355
+ inner ( sess, & delimited. all_tts , locs, next_metavar, seq_depth) ;
360
356
}
361
357
TokenTree :: Sequence ( _, seq) => {
362
358
// We can't determine `idx_first_after` and construct the final
@@ -370,7 +366,7 @@ impl TtParser {
370
366
let op = seq. kleene . op ;
371
367
let idx_first = locs. len ( ) ;
372
368
let idx_seq = idx_first - 1 ;
373
- inner ( sess, & seq. tts , locs, next_metavar, seq_depth + 1 ) ? ;
369
+ inner ( sess, & seq. tts , locs, next_metavar, seq_depth + 1 ) ;
374
370
375
371
if let Some ( separator) = & seq. separator {
376
372
locs. push ( MatcherLoc :: SequenceSep { separator : separator. clone ( ) } ) ;
@@ -389,40 +385,29 @@ impl TtParser {
389
385
} ;
390
386
}
391
387
& TokenTree :: MetaVarDecl ( span, bind, kind) => {
392
- if let Some ( kind) = kind {
393
- locs. push ( MatcherLoc :: MetaVarDecl {
394
- span,
395
- bind,
396
- kind,
397
- next_metavar : * next_metavar,
398
- seq_depth,
399
- } ) ;
400
- * next_metavar += 1 ;
401
- } else if sess
402
- . missing_fragment_specifiers
403
- . borrow_mut ( )
404
- . remove ( & span)
405
- . is_some ( )
406
- {
407
- // E.g. `$e` instead of `$e:expr`.
408
- return Err ( ( span, "missing fragment specifier" . to_string ( ) ) ) ;
409
- }
388
+ locs. push ( MatcherLoc :: MetaVarDecl {
389
+ span,
390
+ bind,
391
+ kind,
392
+ next_metavar : * next_metavar,
393
+ seq_depth,
394
+ } ) ;
395
+ * next_metavar += 1 ;
410
396
}
411
397
TokenTree :: MetaVar ( ..) | TokenTree :: MetaVarExpr ( ..) => unreachable ! ( ) ,
412
398
}
413
399
}
414
- Ok ( ( ) )
415
400
}
416
401
417
402
self . locs . clear ( ) ;
418
403
let mut next_metavar = 0 ;
419
- inner ( sess, matcher, & mut self . locs , & mut next_metavar, /* seq_depth */ 0 ) ? ;
404
+ inner ( sess, matcher, & mut self . locs , & mut next_metavar, /* seq_depth */ 0 ) ;
420
405
421
406
// A final entry is needed for eof.
422
407
self . locs . push ( MatcherLoc :: Eof ) ;
423
408
424
409
// This is the number of metavar decls.
425
- Ok ( next_metavar)
410
+ next_metavar
426
411
}
427
412
428
413
/// Process the matcher positions of `cur_mps` until it is empty. In the process, this will
@@ -434,6 +419,7 @@ impl TtParser {
434
419
/// track of through the mps generated.
435
420
fn parse_tt_inner (
436
421
& mut self ,
422
+ sess : & ParseSess ,
437
423
num_metavar_decls : usize ,
438
424
token : & Token ,
439
425
) -> Option < NamedParseResult > {
@@ -532,12 +518,20 @@ impl TtParser {
532
518
mp. idx = idx_first;
533
519
self . cur_mps . push ( mp) ;
534
520
}
535
- MatcherLoc :: MetaVarDecl { kind, .. } => {
521
+ & MatcherLoc :: MetaVarDecl { span , kind, .. } => {
536
522
// Built-in nonterminals never start with these tokens, so we can eliminate
537
523
// them from consideration. We use the span of the metavariable declaration
538
524
// to determine any edition-specific matching behavior for non-terminals.
539
- if Parser :: nonterminal_may_begin_with ( * kind, token) {
540
- self . bb_mps . push ( mp) ;
525
+ if let Some ( kind) = kind {
526
+ if Parser :: nonterminal_may_begin_with ( kind, token) {
527
+ self . bb_mps . push ( mp) ;
528
+ }
529
+ } else {
530
+ // Both this check and the one in `nameize` are necessary, surprisingly.
531
+ if sess. missing_fragment_specifiers . borrow_mut ( ) . remove ( & span) . is_some ( ) {
532
+ // E.g. `$e` instead of `$e:expr`.
533
+ return Some ( Error ( span, "missing fragment specifier" . to_string ( ) ) ) ;
534
+ }
541
535
}
542
536
}
543
537
MatcherLoc :: Eof => {
@@ -564,7 +558,7 @@ impl TtParser {
564
558
// Need to take ownership of the matches from within the `Lrc`.
565
559
Lrc :: make_mut ( & mut eof_mp. matches ) ;
566
560
let matches = Lrc :: try_unwrap ( eof_mp. matches ) . unwrap ( ) . into_iter ( ) ;
567
- self . nameize ( matches)
561
+ self . nameize ( sess , matches)
568
562
}
569
563
EofMatcherPositions :: Multiple => {
570
564
Error ( token. span , "ambiguity: multiple successful parses" . to_string ( ) )
@@ -588,10 +582,7 @@ impl TtParser {
588
582
parser : & mut Cow < ' _ , Parser < ' _ > > ,
589
583
matcher : & [ TokenTree ] ,
590
584
) -> NamedParseResult {
591
- let num_metavar_decls = match self . compute_locs ( parser. sess , matcher) {
592
- Ok ( num_metavar_decls) => num_metavar_decls,
593
- Err ( ( span, msg) ) => return Error ( span, msg) ,
594
- } ;
585
+ let num_metavar_decls = self . compute_locs ( parser. sess , matcher) ;
595
586
596
587
// A queue of possible matcher positions. We initialize it with the matcher position in
597
588
// which the "dot" is before the first token of the first token tree in `matcher`.
@@ -607,7 +598,7 @@ impl TtParser {
607
598
608
599
// Process `cur_mps` until either we have finished the input or we need to get some
609
600
// parsing from the black-box parser done.
610
- if let Some ( res) = self . parse_tt_inner ( num_metavar_decls, & parser. token ) {
601
+ if let Some ( res) = self . parse_tt_inner ( & parser . sess , num_metavar_decls, & parser. token ) {
611
602
return res;
612
603
}
613
604
@@ -637,7 +628,11 @@ impl TtParser {
637
628
let mut mp = self . bb_mps . pop ( ) . unwrap ( ) ;
638
629
let loc = & self . locs [ mp. idx ] ;
639
630
if let & MatcherLoc :: MetaVarDecl {
640
- span, kind, next_metavar, seq_depth, ..
631
+ span,
632
+ kind : Some ( kind) ,
633
+ next_metavar,
634
+ seq_depth,
635
+ ..
641
636
} = loc
642
637
{
643
638
// We use the span of the metavariable declaration to determine any
@@ -682,7 +677,9 @@ impl TtParser {
682
677
. bb_mps
683
678
. iter ( )
684
679
. map ( |mp| match & self . locs [ mp. idx ] {
685
- MatcherLoc :: MetaVarDecl { bind, kind, .. } => format ! ( "{} ('{}')" , kind, bind) ,
680
+ MatcherLoc :: MetaVarDecl { bind, kind : Some ( kind) , .. } => {
681
+ format ! ( "{} ('{}')" , kind, bind)
682
+ }
686
683
_ => unreachable ! ( ) ,
687
684
} )
688
685
. collect :: < Vec < String > > ( )
@@ -702,16 +699,30 @@ impl TtParser {
702
699
)
703
700
}
704
701
705
- fn nameize < I : Iterator < Item = NamedMatch > > ( & self , mut res : I ) -> NamedParseResult {
702
+ fn nameize < I : Iterator < Item = NamedMatch > > (
703
+ & self ,
704
+ sess : & ParseSess ,
705
+ mut res : I ,
706
+ ) -> NamedParseResult {
706
707
// Make that each metavar has _exactly one_ binding. If so, insert the binding into the
707
708
// `NamedParseResult`. Otherwise, it's an error.
708
709
let mut ret_val = FxHashMap :: default ( ) ;
709
710
for loc in self . locs . iter ( ) {
710
- if let & MatcherLoc :: MetaVarDecl { span, bind, .. } = loc {
711
- match ret_val. entry ( MacroRulesNormalizedIdent :: new ( bind) ) {
712
- Vacant ( spot) => spot. insert ( res. next ( ) . unwrap ( ) ) ,
713
- Occupied ( ..) => return Error ( span, format ! ( "duplicated bind name: {}" , bind) ) ,
714
- } ;
711
+ if let & MatcherLoc :: MetaVarDecl { span, bind, kind, .. } = loc {
712
+ if kind. is_some ( ) {
713
+ match ret_val. entry ( MacroRulesNormalizedIdent :: new ( bind) ) {
714
+ Vacant ( spot) => spot. insert ( res. next ( ) . unwrap ( ) ) ,
715
+ Occupied ( ..) => {
716
+ return Error ( span, format ! ( "duplicated bind name: {}" , bind) ) ;
717
+ }
718
+ } ;
719
+ } else {
720
+ // Both this check and the one in `parse_tt_inner` are necessary, surprisingly.
721
+ if sess. missing_fragment_specifiers . borrow_mut ( ) . remove ( & span) . is_some ( ) {
722
+ // E.g. `$e` instead of `$e:expr`.
723
+ return Error ( span, "missing fragment specifier" . to_string ( ) ) ;
724
+ }
725
+ }
715
726
}
716
727
}
717
728
Success ( ret_val)
0 commit comments