Skip to content

Commit c13ca42

Browse files
committed
Move eof_items handling entirely within inner_parse_loop.
Also rename `inner_parse_loop` as `parse_tt_inner`, because it's no longer just a loop.
1 parent 9f0798b commit c13ca42

File tree

1 file changed

+40
-50
lines changed

1 file changed

+40
-50
lines changed

compiler/rustc_expand/src/mbe/macro_parser.rs

Lines changed: 40 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl<'tt> TokenTreeOrTokenTreeSlice<'tt> {
122122

123123
/// An unzipping of `TokenTree`s... see the `stack` field of `MatcherPos`.
124124
///
125-
/// This is used by `inner_parse_loop` to keep track of delimited submatchers that we have
125+
/// This is used by `parse_tt_inner` to keep track of delimited submatchers that we have
126126
/// descended into.
127127
#[derive(Clone)]
128128
struct MatcherTtFrame<'tt> {
@@ -480,21 +480,24 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
480480
/// successful execution of this function.
481481
/// - `next_items`: the set of newly generated items. These are used to replenish `cur_items` in
482482
/// the function `parse`.
483-
/// - `eof_items`: the set of items that would be valid if this was the EOF.
484483
/// - `bb_items`: the set of items that are waiting for the black-box parser.
485484
/// - `token`: the current token of the parser.
486485
///
487486
/// # Returns
488487
///
489-
/// A `ParseResult`. Note that matches are kept track of through the items generated.
490-
fn inner_parse_loop<'root, 'tt>(
488+
/// `Some(result)` if everything is finished, `None` otherwise. Note that matches are kept track of
489+
/// through the items generated.
490+
fn parse_tt_inner<'root, 'tt>(
491491
sess: &ParseSess,
492+
ms: &[TokenTree],
492493
cur_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
493494
next_items: &mut Vec<MatcherPosHandle<'root, 'tt>>,
494495
bb_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
495-
eof_items: &mut EofItems<'root, 'tt>,
496496
token: &Token,
497-
) -> Result<(), (rustc_span::Span, String)> {
497+
) -> Option<NamedParseResult> {
498+
// Matcher positions that would be valid if the macro invocation was over now
499+
let mut eof_items = EofItems::None;
500+
498501
// Pop items from `cur_items` until it is empty.
499502
while let Some(mut item) = cur_items.pop() {
500503
// When unzipped trees end, remove them. This corresponds to backtracking out of a
@@ -566,7 +569,7 @@ fn inner_parse_loop<'root, 'tt>(
566569
} else {
567570
// If we are not in a repetition, then being at the end of a matcher means that we
568571
// have reached the potential end of the input.
569-
*eof_items = match eof_items {
572+
eof_items = match eof_items {
570573
EofItems::None => EofItems::One(item),
571574
EofItems::One(_) | EofItems::Multiple => EofItems::Multiple,
572575
}
@@ -614,7 +617,7 @@ fn inner_parse_loop<'root, 'tt>(
614617
// We need to match a metavar (but the identifier is invalid)... this is an error
615618
TokenTree::MetaVarDecl(span, _, None) => {
616619
if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() {
617-
return Err((span, "missing fragment specifier".to_string()));
620+
return Some(Error(span, "missing fragment specifier".to_string()));
618621
}
619622
}
620623

@@ -663,8 +666,29 @@ fn inner_parse_loop<'root, 'tt>(
663666
}
664667
}
665668

666-
// Yay a successful parse (so far)!
667-
Ok(())
669+
// If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise,
670+
// either the parse is ambiguous (which should never happen) or there is a syntax error.
671+
if *token == token::Eof {
672+
Some(match eof_items {
673+
EofItems::One(mut eof_item) => {
674+
let matches =
675+
eof_item.matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap());
676+
nameize(sess, ms, matches)
677+
}
678+
EofItems::Multiple => {
679+
Error(token.span, "ambiguity: multiple successful parses".to_string())
680+
}
681+
EofItems::None => Failure(
682+
Token::new(
683+
token::Eof,
684+
if token.span.is_dummy() { token.span } else { token.span.shrink_to_hi() },
685+
),
686+
"missing tokens in macro arguments",
687+
),
688+
})
689+
} else {
690+
None
691+
}
668692
}
669693

670694
/// Use the given sequence of token trees (`ms`) as a matcher. Match the token
@@ -675,7 +699,7 @@ pub(super) fn parse_tt(
675699
macro_name: Ident,
676700
) -> NamedParseResult {
677701
// A queue of possible matcher positions. We initialize it with the matcher position in which
678-
// the "dot" is before the first token of the first token tree in `ms`. `inner_parse_loop` then
702+
// the "dot" is before the first token of the first token tree in `ms`. `parse_tt_inner` then
679703
// processes all of these possible matcher positions and produces possible next positions into
680704
// `next_items`. After some post-processing, the contents of `next_items` replenish `cur_items`
681705
// and we start over again.
@@ -692,61 +716,27 @@ pub(super) fn parse_tt(
692716
// Matcher positions black-box parsed by parser.rs (`parser`)
693717
let mut bb_items = SmallVec::new();
694718

695-
// Matcher positions that would be valid if the macro invocation was over now
696-
let mut eof_items = EofItems::None;
697-
698719
// Process `cur_items` until either we have finished the input or we need to get some
699720
// parsing from the black-box parser done. The result is that `next_items` will contain a
700721
// bunch of possible next matcher positions in `next_items`.
701-
match inner_parse_loop(
722+
if let Some(result) = parse_tt_inner(
702723
parser.sess,
724+
ms,
703725
&mut cur_items,
704726
&mut next_items,
705727
&mut bb_items,
706-
&mut eof_items,
707728
&parser.token,
708729
) {
709-
Ok(()) => {}
710-
Err((sp, msg)) => return Error(sp, msg),
730+
return result;
711731
}
712732

713-
// inner parse loop handled all cur_items, so it's empty
733+
// `parse_tt_inner` handled all cur_items, so it's empty.
714734
assert!(cur_items.is_empty());
715735

716-
// We need to do some post processing after the `inner_parse_loop`.
736+
// We need to do some post processing after the `parse_tt_inner`.
717737
//
718738
// Error messages here could be improved with links to original rules.
719739

720-
// If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise,
721-
// either the parse is ambiguous (which should never happen) or there is a syntax error.
722-
if parser.token == token::Eof {
723-
return match eof_items {
724-
EofItems::One(mut eof_item) => {
725-
let matches =
726-
eof_item.matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap());
727-
nameize(parser.sess, ms, matches)
728-
}
729-
EofItems::Multiple => {
730-
Error(parser.token.span, "ambiguity: multiple successful parses".to_string())
731-
}
732-
EofItems::None => Failure(
733-
Token::new(
734-
token::Eof,
735-
if parser.token.span.is_dummy() {
736-
parser.token.span
737-
} else {
738-
parser.token.span.shrink_to_hi()
739-
},
740-
),
741-
"missing tokens in macro arguments",
742-
),
743-
};
744-
}
745-
// Performance hack: `eof_items` may share matchers via `Rc` with other things that we want
746-
// to modify. Dropping `eof_items` now may drop these refcounts to 1, preventing an
747-
// unnecessary implicit clone later in `Rc::make_mut`.
748-
drop(eof_items);
749-
750740
match (next_items.len(), bb_items.len()) {
751741
(0, 0) => {
752742
// There are no possible next positions AND we aren't waiting for the black-box

0 commit comments

Comments
 (0)