@@ -154,7 +154,7 @@ type NamedMatchVec = SmallVec<[NamedMatch; 4]>;
154
154
/// lifetime. By separating `'tt` from `'root`, we can show that.
155
155
#[ derive( Clone ) ]
156
156
struct MatcherPos < ' root , ' tt > {
157
- /// The token or sequence of tokens that make up the matcher
157
+ /// The token or sequence of tokens that make up the matcher. `elts` is short for "elements".
158
158
top_elts : TokenTreeOrTokenTreeSlice < ' tt > ,
159
159
160
160
/// The position of the "dot" in this matcher
@@ -184,17 +184,8 @@ struct MatcherPos<'root, 'tt> {
184
184
/// in this matcher.
185
185
match_hi : usize ,
186
186
187
- // The following fields are used if we are matching a repetition. If we aren't, they should be
188
- // `None`.
189
- /// The KleeneOp of this sequence if we are in a repetition.
190
- seq_op : Option < mbe:: KleeneOp > ,
191
-
192
- /// The separator if we are in a repetition.
193
- sep : Option < Token > ,
194
-
195
- /// The "parent" matcher position if we are in a repetition. That is, the matcher position just
196
- /// before we enter the sequence.
197
- up : Option < MatcherPosHandle < ' root , ' tt > > ,
187
+ /// This field is only used if we are matching a repetition.
188
+ repetition : Option < MatcherPosRepetition < ' root , ' tt > > ,
198
189
199
190
/// Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from
200
191
/// a delimited token tree (e.g., something wrapped in `(` `)`) or to get the contents of a doc
@@ -207,14 +198,58 @@ struct MatcherPos<'root, 'tt> {
207
198
stack : SmallVec < [ MatcherTtFrame < ' tt > ; 1 ] > ,
208
199
}
209
200
201
+ // This type is used a lot. Make sure it doesn't unintentionally get bigger.
202
+ #[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
203
+ rustc_data_structures:: static_assert_size!( MatcherPos <' _, ' _>, 192 ) ;
204
+
210
205
impl < ' root , ' tt > MatcherPos < ' root , ' tt > {
206
+ /// Generates the top-level matcher position in which the "dot" is before the first token of
207
+ /// the matcher `ms`.
208
+ fn new ( ms : & ' tt [ TokenTree ] ) -> Self {
209
+ let match_idx_hi = count_names ( ms) ;
210
+ MatcherPos {
211
+ // Start with the top level matcher given to us.
212
+ top_elts : TtSeq ( ms) ,
213
+
214
+ // The "dot" is before the first token of the matcher.
215
+ idx : 0 ,
216
+
217
+ // Initialize `matches` to a bunch of empty `Vec`s -- one for each metavar in
218
+ // `top_elts`. `match_lo` for `top_elts` is 0 and `match_hi` is `match_idx_hi`.
219
+ // `match_cur` is 0 since we haven't actually matched anything yet.
220
+ matches : create_matches ( match_idx_hi) ,
221
+ match_lo : 0 ,
222
+ match_cur : 0 ,
223
+ match_hi : match_idx_hi,
224
+
225
+ // Haven't descended into any delimiters, so this is empty.
226
+ stack : smallvec ! [ ] ,
227
+
228
+ // Haven't descended into any sequences, so this is `None`.
229
+ repetition : None ,
230
+ }
231
+ }
232
+
211
233
/// Adds `m` as a named match for the `idx`-th metavar.
212
234
fn push_match ( & mut self , idx : usize , m : NamedMatch ) {
213
235
let matches = Lrc :: make_mut ( & mut self . matches [ idx] ) ;
214
236
matches. push ( m) ;
215
237
}
216
238
}
217
239
240
+ #[ derive( Clone ) ]
241
+ struct MatcherPosRepetition < ' root , ' tt > {
242
+ /// The KleeneOp of this sequence.
243
+ seq_op : mbe:: KleeneOp ,
244
+
245
+ /// The separator.
246
+ sep : Option < Token > ,
247
+
248
+ /// The "parent" matcher position. That is, the matcher position just before we enter the
249
+ /// sequence.
250
+ up : MatcherPosHandle < ' root , ' tt > ,
251
+ }
252
+
218
253
// Lots of MatcherPos instances are created at runtime. Allocating them on the
219
254
// heap is slow. Furthermore, using SmallVec<MatcherPos> to allocate them all
220
255
// on the stack is also slow, because MatcherPos is quite a large type and
@@ -258,6 +293,12 @@ impl<'root, 'tt> DerefMut for MatcherPosHandle<'root, 'tt> {
258
293
}
259
294
}
260
295
296
+ enum EofItems < ' root , ' tt > {
297
+ None ,
298
+ One ( MatcherPosHandle < ' root , ' tt > ) ,
299
+ Multiple ,
300
+ }
301
+
261
302
/// Represents the possible results of an attempted parse.
262
303
crate enum ParseResult < T > {
263
304
/// Parsed successfully.
@@ -300,35 +341,6 @@ fn create_matches(len: usize) -> Box<[Lrc<NamedMatchVec>]> {
300
341
. into_boxed_slice ( )
301
342
}
302
343
303
- /// Generates the top-level matcher position in which the "dot" is before the first token of the
304
- /// matcher `ms`.
305
- fn initial_matcher_pos < ' root , ' tt > ( ms : & ' tt [ TokenTree ] ) -> MatcherPos < ' root , ' tt > {
306
- let match_idx_hi = count_names ( ms) ;
307
- let matches = create_matches ( match_idx_hi) ;
308
- MatcherPos {
309
- // Start with the top level matcher given to us
310
- top_elts : TtSeq ( ms) , // "elts" is an abbr. for "elements"
311
- // The "dot" is before the first token of the matcher
312
- idx : 0 ,
313
-
314
- // Initialize `matches` to a bunch of empty `Vec`s -- one for each metavar in `top_elts`.
315
- // `match_lo` for `top_elts` is 0 and `match_hi` is `matches.len()`. `match_cur` is 0 since
316
- // we haven't actually matched anything yet.
317
- matches,
318
- match_lo : 0 ,
319
- match_cur : 0 ,
320
- match_hi : match_idx_hi,
321
-
322
- // Haven't descended into any delimiters, so empty stack
323
- stack : smallvec ! [ ] ,
324
-
325
- // Haven't descended into any sequences, so both of these are `None`.
326
- seq_op : None ,
327
- sep : None ,
328
- up : None ,
329
- }
330
- }
331
-
332
344
/// `NamedMatch` is a pattern-match result for a single `token::MATCH_NONTERMINAL`:
333
345
/// so it is associated with a single ident in a parse, and all
334
346
/// `MatchedNonterminal`s in the `NamedMatch` have the same non-terminal type
@@ -475,10 +487,10 @@ fn inner_parse_loop<'root, 'tt>(
475
487
sess : & ParseSess ,
476
488
cur_items : & mut SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
477
489
next_items : & mut Vec < MatcherPosHandle < ' root , ' tt > > ,
478
- eof_items : & mut SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
479
490
bb_items : & mut SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
491
+ eof_items : & mut EofItems < ' root , ' tt > ,
480
492
token : & Token ,
481
- ) -> ParseResult < ( ) > {
493
+ ) -> Result < ( ) , ( rustc_span :: Span , String ) > {
482
494
// Pop items from `cur_items` until it is empty.
483
495
while let Some ( mut item) = cur_items. pop ( ) {
484
496
// When unzipped trees end, remove them. This corresponds to backtracking out of a
@@ -504,7 +516,7 @@ fn inner_parse_loop<'root, 'tt>(
504
516
// We are repeating iff there is a parent. If the matcher is inside of a repetition,
505
517
// then we could be at the end of a sequence or at the beginning of the next
506
518
// repetition.
507
- if item . up . is_some ( ) {
519
+ if let Some ( repetition ) = & item . repetition {
508
520
// At this point, regardless of whether there is a separator, we should add all
509
521
// matches from the complete repetition of the sequence to the shared, top-level
510
522
// `matches` list (actually, `up.matches`, which could itself not be the top-level,
@@ -515,7 +527,7 @@ fn inner_parse_loop<'root, 'tt>(
515
527
// NOTE: removing the condition `idx == len` allows trailing separators.
516
528
if idx == len {
517
529
// Get the `up` matcher
518
- let mut new_pos = item . up . clone ( ) . unwrap ( ) ;
530
+ let mut new_pos = repetition . up . clone ( ) ;
519
531
520
532
// Add matches from this repetition to the `matches` of `up`
521
533
for idx in item. match_lo ..item. match_hi {
@@ -530,32 +542,33 @@ fn inner_parse_loop<'root, 'tt>(
530
542
}
531
543
532
544
// Check if we need a separator.
533
- if idx == len && item . sep . is_some ( ) {
545
+ if idx == len && repetition . sep . is_some ( ) {
534
546
// We have a separator, and it is the current token. We can advance past the
535
547
// separator token.
536
- if item . sep . as_ref ( ) . map_or ( false , |sep| token_name_eq ( token, sep) ) {
548
+ if repetition . sep . as_ref ( ) . map_or ( false , |sep| token_name_eq ( token, sep) ) {
537
549
item. idx += 1 ;
538
550
next_items. push ( item) ;
539
551
}
540
- }
541
- // We don't need a separator. Move the "dot" back to the beginning of the matcher
542
- // and try to match again UNLESS we are only allowed to have _one_ repetition.
543
- else if item . seq_op != Some ( mbe :: KleeneOp :: ZeroOrOne ) {
552
+ } else if repetition . seq_op != mbe :: KleeneOp :: ZeroOrOne {
553
+ // We don't need a separator. Move the "dot" back to the beginning of the
554
+ // matcher and try to match again UNLESS we are only allowed to have _one_
555
+ // repetition.
544
556
item. match_cur = item. match_lo ;
545
557
item. idx = 0 ;
546
558
cur_items. push ( item) ;
547
559
}
560
+ } else {
561
+ // If we are not in a repetition, then being at the end of a matcher means that we
562
+ // have reached the potential end of the input.
563
+ * eof_items = match eof_items {
564
+ EofItems :: None => EofItems :: One ( item) ,
565
+ EofItems :: One ( _) | EofItems :: Multiple => EofItems :: Multiple ,
566
+ }
548
567
}
549
- // If we are not in a repetition, then being at the end of a matcher means that we have
550
- // reached the potential end of the input.
551
- else {
552
- eof_items. push ( item) ;
553
- }
554
- }
555
- // We are in the middle of a matcher.
556
- else {
557
- // Look at what token in the matcher we are trying to match the current token (`token`)
558
- // against. Depending on that, we may generate new items.
568
+ } else {
569
+ // We are in the middle of a matcher. Look at what token in the matcher we are trying
570
+ // to match the current token (`token`) against. Depending on that, we may generate new
571
+ // items.
559
572
match item. top_elts . get_tt ( idx) {
560
573
// Need to descend into a sequence
561
574
TokenTree :: Sequence ( sp, seq) => {
@@ -578,22 +591,24 @@ fn inner_parse_loop<'root, 'tt>(
578
591
let matches = create_matches ( item. matches . len ( ) ) ;
579
592
cur_items. push ( MatcherPosHandle :: Box ( Box :: new ( MatcherPos {
580
593
stack : smallvec ! [ ] ,
581
- sep : seq. separator . clone ( ) ,
582
- seq_op : Some ( seq. kleene . op ) ,
583
594
idx : 0 ,
584
595
matches,
585
596
match_lo : item. match_cur ,
586
597
match_cur : item. match_cur ,
587
598
match_hi : item. match_cur + seq. num_captures ,
588
- up : Some ( item) ,
599
+ repetition : Some ( MatcherPosRepetition {
600
+ up : item,
601
+ sep : seq. separator . clone ( ) ,
602
+ seq_op : seq. kleene . op ,
603
+ } ) ,
589
604
top_elts : Tt ( TokenTree :: Sequence ( sp, seq) ) ,
590
605
} ) ) ) ;
591
606
}
592
607
593
608
// We need to match a metavar (but the identifier is invalid)... this is an error
594
609
TokenTree :: MetaVarDecl ( span, _, None ) => {
595
610
if sess. missing_fragment_specifiers . borrow_mut ( ) . remove ( & span) . is_some ( ) {
596
- return Error ( span, "missing fragment specifier" . to_string ( ) ) ;
611
+ return Err ( ( span, "missing fragment specifier" . to_string ( ) ) ) ;
597
612
}
598
613
}
599
614
@@ -641,7 +656,7 @@ fn inner_parse_loop<'root, 'tt>(
641
656
}
642
657
643
658
// Yay a successful parse (so far)!
644
- Success ( ( ) )
659
+ Ok ( ( ) )
645
660
}
646
661
647
662
/// Use the given sequence of token trees (`ms`) as a matcher. Match the token
@@ -659,17 +674,18 @@ pub(super) fn parse_tt(
659
674
//
660
675
// This MatcherPos instance is allocated on the stack. All others -- and
661
676
// there are frequently *no* others! -- are allocated on the heap.
662
- let mut initial = initial_matcher_pos ( ms) ;
677
+ let mut initial = MatcherPos :: new ( ms) ;
663
678
let mut cur_items = smallvec ! [ MatcherPosHandle :: Ref ( & mut initial) ] ;
664
679
let mut next_items = Vec :: new ( ) ;
665
680
666
681
loop {
682
+ assert ! ( next_items. is_empty( ) ) ;
683
+
667
684
// Matcher positions black-box parsed by parser.rs (`parser`)
668
685
let mut bb_items = SmallVec :: new ( ) ;
669
686
670
687
// Matcher positions that would be valid if the macro invocation was over now
671
- let mut eof_items = SmallVec :: new ( ) ;
672
- assert ! ( next_items. is_empty( ) ) ;
688
+ let mut eof_items = EofItems :: None ;
673
689
674
690
// Process `cur_items` until either we have finished the input or we need to get some
675
691
// parsing from the black-box parser done. The result is that `next_items` will contain a
@@ -678,37 +694,34 @@ pub(super) fn parse_tt(
678
694
parser. sess ,
679
695
& mut cur_items,
680
696
& mut next_items,
681
- & mut eof_items,
682
697
& mut bb_items,
698
+ & mut eof_items,
683
699
& parser. token ,
684
700
) {
685
- Success ( _) => { }
686
- Failure ( token, msg) => return Failure ( token, msg) ,
687
- Error ( sp, msg) => return Error ( sp, msg) ,
688
- ErrorReported => return ErrorReported ,
701
+ Ok ( ( ) ) => { }
702
+ Err ( ( sp, msg) ) => return Error ( sp, msg) ,
689
703
}
690
704
691
705
// inner parse loop handled all cur_items, so it's empty
692
706
assert ! ( cur_items. is_empty( ) ) ;
693
707
694
- // We need to do some post processing after the `inner_parser_loop `.
708
+ // We need to do some post processing after the `inner_parse_loop `.
695
709
//
696
710
// Error messages here could be improved with links to original rules.
697
711
698
712
// If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise,
699
713
// either the parse is ambiguous (which should never happen) or there is a syntax error.
700
714
if parser. token == token:: Eof {
701
- if eof_items. len ( ) == 1 {
702
- let matches =
703
- eof_items[ 0 ] . matches . iter_mut ( ) . map ( |dv| Lrc :: make_mut ( dv) . pop ( ) . unwrap ( ) ) ;
704
- return nameize ( parser. sess , ms, matches) ;
705
- } else if eof_items. len ( ) > 1 {
706
- return Error (
707
- parser. token . span ,
708
- "ambiguity: multiple successful parses" . to_string ( ) ,
709
- ) ;
710
- } else {
711
- return Failure (
715
+ return match eof_items {
716
+ EofItems :: One ( mut eof_item) => {
717
+ let matches =
718
+ eof_item. matches . iter_mut ( ) . map ( |dv| Lrc :: make_mut ( dv) . pop ( ) . unwrap ( ) ) ;
719
+ nameize ( parser. sess , ms, matches)
720
+ }
721
+ EofItems :: Multiple => {
722
+ Error ( parser. token . span , "ambiguity: multiple successful parses" . to_string ( ) )
723
+ }
724
+ EofItems :: None => Failure (
712
725
Token :: new (
713
726
token:: Eof ,
714
727
if parser. token . span . is_dummy ( ) {
@@ -718,22 +731,23 @@ pub(super) fn parse_tt(
718
731
} ,
719
732
) ,
720
733
"missing tokens in macro arguments" ,
721
- ) ;
722
- }
734
+ ) ,
735
+ } ;
723
736
}
724
- // Performance hack: eof_items may share matchers via Rc with other things that we want
725
- // to modify. Dropping eof_items now may drop these refcounts to 1, preventing an
726
- // unnecessary implicit clone later in Rc::make_mut.
737
+ // Performance hack: ` eof_items` may share matchers via `Rc` with other things that we want
738
+ // to modify. Dropping ` eof_items` now may drop these refcounts to 1, preventing an
739
+ // unnecessary implicit clone later in ` Rc::make_mut` .
727
740
drop ( eof_items) ;
728
741
729
742
// If there are no possible next positions AND we aren't waiting for the black-box parser,
730
743
// then there is a syntax error.
731
744
if bb_items. is_empty ( ) && next_items. is_empty ( ) {
732
745
return Failure ( parser. token . clone ( ) , "no rules expected this token in macro call" ) ;
733
746
}
734
- // Another possibility is that we need to call out to parse some rust nonterminal
735
- // (black-box) parser. However, if there is not EXACTLY ONE of these, something is wrong.
736
- else if ( !bb_items. is_empty ( ) && !next_items. is_empty ( ) ) || bb_items. len ( ) > 1 {
747
+
748
+ if ( !bb_items. is_empty ( ) && !next_items. is_empty ( ) ) || bb_items. len ( ) > 1 {
749
+ // We need to call out to parse some rust nonterminal (black-box) parser. But something
750
+ // is wrong, because there is not EXACTLY ONE of these.
737
751
let nts = bb_items
738
752
. iter ( )
739
753
. map ( |item| match item. top_elts . get_tt ( item. idx ) {
@@ -755,15 +769,15 @@ pub(super) fn parse_tt(
755
769
) ,
756
770
) ;
757
771
}
758
- // Dump all possible `next_items` into `cur_items` for the next iteration.
759
- else if !next_items. is_empty ( ) {
760
- // Now process the next token
772
+
773
+ if !next_items. is_empty ( ) {
774
+ // Dump all possible `next_items` into `cur_items` for the next iteration. Then process
775
+ // the next token.
761
776
cur_items. extend ( next_items. drain ( ..) ) ;
762
777
parser. to_mut ( ) . bump ( ) ;
763
- }
764
- // Finally, we have the case where we need to call the black-box parser to get some
765
- // nonterminal.
766
- else {
778
+ } else {
779
+ // Finally, we have the case where we need to call the black-box parser to get some
780
+ // nonterminal.
767
781
assert_eq ! ( bb_items. len( ) , 1 ) ;
768
782
769
783
let mut item = bb_items. pop ( ) . unwrap ( ) ;
0 commit comments