Skip to content

Commit 0d7f193

Browse files
committed
Added a bunch of comments to macro_parser.rs
1 parent ac0c16d commit 0d7f193

File tree

1 file changed

+62
-10
lines changed

1 file changed

+62
-10
lines changed

src/libsyntax/ext/tt/macro_parser.rs

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -429,22 +429,46 @@ fn inner_parse_loop(
429429
Success(())
430430
}
431431

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)
432443
pub fn parse(
433444
sess: &ParseSess,
434445
tts: TokenStream,
435446
ms: &[TokenTree],
436447
directory: Option<Directory>,
437448
recurse_into_modules: bool,
438449
) -> NamedParseResult {
450+
// Create a parser that can be used for the "black box" parts.
439451
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.
440458
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();
442460

443461
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
445466
let mut eof_items = SmallVector::new();
446467
assert!(next_items.is_empty());
447468

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`.
448472
match inner_parse_loop(
449473
sess,
450474
&mut cur_items,
@@ -462,7 +486,12 @@ pub fn parse(
462486
// inner parse loop handled all cur_items, so it's empty
463487
assert!(cur_items.is_empty());
464488

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.
466495
if token_name_eq(&parser.token, &token::Eof) {
467496
if eof_items.len() == 1 {
468497
let matches = eof_items[0]
@@ -478,7 +507,10 @@ pub fn parse(
478507
} else {
479508
return Failure(parser.span, token::Eof);
480509
}
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 {
482514
let nts = bb_items
483515
.iter()
484516
.map(|item| match item.top_elts.get_tt(item.idx) {
@@ -499,15 +531,23 @@ pub fn parse(
499531
}
500532
),
501533
);
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() {
503538
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
506543
cur_items.extend(next_items.drain(..));
507544
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+
511551
let mut item = bb_items.pop().unwrap();
512552
if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) {
513553
let match_cur = item.match_cur;
@@ -595,6 +635,18 @@ fn may_begin_with(name: &str, token: &Token) -> bool {
595635
}
596636
}
597637

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.
598650
fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
599651
if name == "tt" {
600652
return token::NtTT(p.parse_token_tree());

0 commit comments

Comments
 (0)