@@ -429,22 +429,46 @@ fn inner_parse_loop(
429
429
Success ( ( ) )
430
430
}
431
431
432
+ /// Parse the given set of token trees (`ms`), possibly consuming additional token trees from the
433
+ /// tokenstream (`tts`).
434
+ ///
435
+ /// # Parameters
436
+ ///
437
+ /// - `sess`: The session into which errors are emitted
438
+ /// - `tts`: The tokenstream from which additional token trees may be consumed if needed
439
+ /// - `ms`: The token trees we want to parse as macros
440
+ /// - `directory`: Information about the file locations (needed for the black-box parser)
441
+ /// - `recurse_into_modules`: Whether or not to recurse into modules (needed for the black-box
442
+ /// parser)
432
443
pub fn parse (
433
444
sess : & ParseSess ,
434
445
tts : TokenStream ,
435
446
ms : & [ TokenTree ] ,
436
447
directory : Option < Directory > ,
437
448
recurse_into_modules : bool ,
438
449
) -> NamedParseResult {
450
+ // Create a parser that can be used for the "black box" parts.
439
451
let mut parser = Parser :: new ( sess, tts, directory, recurse_into_modules, true ) ;
452
+
453
+ // A queue of possible matcher positions. We initialize it with the matcher position in which
454
+ // the "dot" is before the first token of the first token tree. `inner_parse_loop` then
455
+ // processes all of these possible matcher positions and produces posible next positions into
456
+ // `next_items`. After some post-processing, the contents of `next_items` replenish
457
+ // `cur_items` and we start over again.
440
458
let mut cur_items = SmallVector :: one ( initial_matcher_pos ( ms. to_owned ( ) , parser. span . lo ( ) ) ) ;
441
- let mut next_items = Vec :: new ( ) ; // or proceed normally
459
+ let mut next_items = Vec :: new ( ) ;
442
460
443
461
loop {
444
- let mut bb_items = SmallVector :: new ( ) ; // black-box parsed by parser.rs
462
+ // Matcher positions black-box parsed by parser.rs (`parser`)
463
+ let mut bb_items = SmallVector :: new ( ) ;
464
+
465
+ // Matcher positions that would be valid if the macro invocation was over now
445
466
let mut eof_items = SmallVector :: new ( ) ;
446
467
assert ! ( next_items. is_empty( ) ) ;
447
468
469
+ // Process `cur_items` until either we have finished the input or we need to get some
470
+ // parsing from the black-box parser done. The result is that `next_items` will contain a
471
+ // bunch of possible next matcher positions in `next_items`.
448
472
match inner_parse_loop (
449
473
sess,
450
474
& mut cur_items,
@@ -462,7 +486,12 @@ pub fn parse(
462
486
// inner parse loop handled all cur_items, so it's empty
463
487
assert ! ( cur_items. is_empty( ) ) ;
464
488
465
- /* error messages here could be improved with links to orig. rules */
489
+ // We need to do some post processing after the `inner_parser_loop`.
490
+ //
491
+ // Error messages here could be improved with links to original rules.
492
+
493
+ // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise,
494
+ // either the parse is ambiguous (which should never happen) or their is a syntax error.
466
495
if token_name_eq ( & parser. token , & token:: Eof ) {
467
496
if eof_items. len ( ) == 1 {
468
497
let matches = eof_items[ 0 ]
@@ -478,7 +507,10 @@ pub fn parse(
478
507
} else {
479
508
return Failure ( parser. span , token:: Eof ) ;
480
509
}
481
- } else if ( !bb_items. is_empty ( ) && !next_items. is_empty ( ) ) || bb_items. len ( ) > 1 {
510
+ }
511
+ // Another possibility is that we need to call out to parse some rust nonterminal
512
+ // (black-box) parser. However, if there is not EXACTLY ONE of these, something is wrong.
513
+ else if ( !bb_items. is_empty ( ) && !next_items. is_empty ( ) ) || bb_items. len ( ) > 1 {
482
514
let nts = bb_items
483
515
. iter ( )
484
516
. map ( |item| match item. top_elts . get_tt ( item. idx ) {
@@ -499,15 +531,23 @@ pub fn parse(
499
531
}
500
532
) ,
501
533
) ;
502
- } else if bb_items. is_empty ( ) && next_items. is_empty ( ) {
534
+ }
535
+ // If there are no posible next positions AND we aren't waiting for the black-box parser,
536
+ // then their is a syntax error.
537
+ else if bb_items. is_empty ( ) && next_items. is_empty ( ) {
503
538
return Failure ( parser. span , parser. token ) ;
504
- } else if !next_items. is_empty ( ) {
505
- /* Now process the next token */
539
+ }
540
+ // Dump all possible `next_items` into `cur_items` for the next iteration.
541
+ else if !next_items. is_empty ( ) {
542
+ // Now process the next token
506
543
cur_items. extend ( next_items. drain ( ..) ) ;
507
544
parser. bump ( ) ;
508
- } else
509
- /* bb_items.len() == 1 */
510
- {
545
+ }
546
+ // Finally, we have the case where we need to call the black-box parser to get some
547
+ // nonterminal.
548
+ else {
549
+ assert_eq ! ( bb_items. len( ) , 1 ) ;
550
+
511
551
let mut item = bb_items. pop ( ) . unwrap ( ) ;
512
552
if let TokenTree :: MetaVarDecl ( span, _, ident) = item. top_elts . get_tt ( item. idx ) {
513
553
let match_cur = item. match_cur ;
@@ -595,6 +635,18 @@ fn may_begin_with(name: &str, token: &Token) -> bool {
595
635
}
596
636
}
597
637
638
+ /// A call to the "black-box" parser to parse some rust nonterminal.
639
+ ///
640
+ /// # Parameters
641
+ ///
642
+ /// - `p`: the "black-box" parser to use
643
+ /// - `sp`: the `Span` we want to parse
644
+ /// - `name`: the name of the metavar _matcher_ we want to match (e.g. `tt`, `ident`, `block`,
645
+ /// etc...)
646
+ ///
647
+ /// # Returns
648
+ ///
649
+ /// The parsed nonterminal.
598
650
fn parse_nt < ' a > ( p : & mut Parser < ' a > , sp : Span , name : & str ) -> Nonterminal {
599
651
if name == "tt" {
600
652
return token:: NtTT ( p. parse_token_tree ( ) ) ;
0 commit comments