diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_expand/src/mbe/macro_parser.rs | 573 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/mbe/macro_rules.rs | 54 |
2 files changed, 323 insertions, 304 deletions
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 8cc81f1eca8..7b5835fce54 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -492,319 +492,334 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool { } } -/// Process the matcher positions of `cur_items` until it is empty. In the process, this will -/// produce more items in `next_items` and `bb_items`. -/// -/// For more info about the how this happens, see the module-level doc comments and the inline -/// comments of this function. -/// -/// # Parameters -/// -/// - `cur_items`: the set of current items to be processed. This should be empty by the end of a -/// successful execution of this function. -/// - `next_items`: the set of newly generated items. These are used to replenish `cur_items` in -/// the function `parse`. -/// - `bb_items`: the set of items that are waiting for the black-box parser. -/// - `token`: the current token of the parser. -/// -/// # Returns -/// -/// `Some(result)` if everything is finished, `None` otherwise. Note that matches are kept track of -/// through the items generated. -fn parse_tt_inner<'root, 'tt>( - sess: &ParseSess, - ms: &[TokenTree], - cur_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, - next_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, - bb_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, - token: &Token, -) -> Option<NamedParseResult> { - // Matcher positions that would be valid if the macro invocation was over now. Only modified if - // `token == Eof`. - let mut eof_items = EofItems::None; - - while let Some(mut item) = cur_items.pop() { - // When unzipped trees end, remove them. This corresponds to backtracking out of a - // delimited submatcher into which we already descended. When backtracking out again, we - // need to advance the "dot" past the delimiters in the outer matcher. - while item.idx >= item.top_elts.len() { - match item.stack.pop() { - Some(MatcherTtFrame { elts, idx }) => { - item.top_elts = elts; - item.idx = idx + 1; +pub struct TtParser; + +impl TtParser { + /// Process the matcher positions of `cur_items` until it is empty. In the process, this will + /// produce more items in `next_items` and `bb_items`. + /// + /// For more info about the how this happens, see the module-level doc comments and the inline + /// comments of this function. + /// + /// # Parameters + /// + /// - `cur_items`: the set of current items to be processed. This should be empty by the end of + /// a successful execution of this function. + /// - `next_items`: the set of newly generated items. These are used to replenish `cur_items` in + /// the function `parse`. + /// - `bb_items`: the set of items that are waiting for the black-box parser. + /// - `token`: the current token of the parser. + /// + /// # Returns + /// + /// `Some(result)` if everything is finished, `None` otherwise. Note that matches are kept + /// track of through the items generated. + fn parse_tt_inner<'root, 'tt>( + &self, + sess: &ParseSess, + ms: &[TokenTree], + cur_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, + next_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, + bb_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, + token: &Token, + ) -> Option<NamedParseResult> { + // Matcher positions that would be valid if the macro invocation was over now. Only + // modified if `token == Eof`. + let mut eof_items = EofItems::None; + + while let Some(mut item) = cur_items.pop() { + // When unzipped trees end, remove them. This corresponds to backtracking out of a + // delimited submatcher into which we already descended. When backtracking out again, we + // need to advance the "dot" past the delimiters in the outer matcher. + while item.idx >= item.top_elts.len() { + match item.stack.pop() { + Some(MatcherTtFrame { elts, idx }) => { + item.top_elts = elts; + item.idx = idx + 1; + } + None => break, } - None => break, } - } - // Get the current position of the "dot" (`idx`) in `item` and the number of token trees in - // the matcher (`len`). - let idx = item.idx; - let len = item.top_elts.len(); - - if idx < len { - // We are in the middle of a matcher. Compare the matcher's current tt against `token`. - match item.top_elts.get_tt(idx) { - TokenTree::Sequence(sp, seq) => { - let op = seq.kleene.op; - if op == mbe::KleeneOp::ZeroOrMore || op == mbe::KleeneOp::ZeroOrOne { - // Allow for the possibility of zero matches of this sequence. - let mut new_item = item.clone(); - new_item.match_cur += seq.num_captures; - new_item.idx += 1; - for idx in item.match_cur..item.match_cur + seq.num_captures { - new_item.push_match(idx, MatchedSeq(Lrc::new(smallvec![]))); + // Get the current position of the "dot" (`idx`) in `item` and the number of token + // trees in the matcher (`len`). + let idx = item.idx; + let len = item.top_elts.len(); + + if idx < len { + // We are in the middle of a matcher. Compare the matcher's current tt against + // `token`. + match item.top_elts.get_tt(idx) { + TokenTree::Sequence(sp, seq) => { + let op = seq.kleene.op; + if op == mbe::KleeneOp::ZeroOrMore || op == mbe::KleeneOp::ZeroOrOne { + // Allow for the possibility of zero matches of this sequence. + let mut new_item = item.clone(); + new_item.match_cur += seq.num_captures; + new_item.idx += 1; + for idx in item.match_cur..item.match_cur + seq.num_captures { + new_item.push_match(idx, MatchedSeq(Lrc::new(smallvec![]))); + } + cur_items.push(new_item); } - cur_items.push(new_item); + + // Allow for the possibility of one or more matches of this sequence. + cur_items.push(MatcherPosHandle::Box(Box::new(MatcherPos::repetition( + item, sp, seq, + )))); } - // Allow for the possibility of one or more matches of this sequence. - cur_items.push(MatcherPosHandle::Box(Box::new(MatcherPos::repetition( - item, sp, seq, - )))); - } + TokenTree::MetaVarDecl(span, _, None) => { + // E.g. `$e` instead of `$e:expr`. + if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() { + return Some(Error(span, "missing fragment specifier".to_string())); + } + } - TokenTree::MetaVarDecl(span, _, None) => { - // E.g. `$e` instead of `$e:expr`. - if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() { - return Some(Error(span, "missing fragment specifier".to_string())); + TokenTree::MetaVarDecl(_, _, Some(kind)) => { + // Built-in nonterminals never start with these tokens, so we can eliminate + // them from consideration. + // + // We use the span of the metavariable declaration to determine any + // edition-specific matching behavior for non-terminals. + if Parser::nonterminal_may_begin_with(kind, token) { + bb_items.push(item); + } } - } - TokenTree::MetaVarDecl(_, _, Some(kind)) => { - // Built-in nonterminals never start with these tokens, so we can eliminate - // them from consideration. - // - // We use the span of the metavariable declaration to determine any - // edition-specific matching behavior for non-terminals. - if Parser::nonterminal_may_begin_with(kind, token) { - bb_items.push(item); + seq @ (TokenTree::Delimited(..) + | TokenTree::Token(Token { kind: DocComment(..), .. })) => { + // To descend into a delimited submatcher or a doc comment, we push the + // current matcher onto a stack and push a new item containing the + // submatcher onto `cur_items`. + // + // At the beginning of the loop, if we reach the end of the delimited + // submatcher, we pop the stack to backtrack out of the descent. + let lower_elts = mem::replace(&mut item.top_elts, Tt(seq)); + let idx = item.idx; + item.stack.push(MatcherTtFrame { elts: lower_elts, idx }); + item.idx = 0; + cur_items.push(item); } - } - seq @ (TokenTree::Delimited(..) - | TokenTree::Token(Token { kind: DocComment(..), .. })) => { - // To descend into a delimited submatcher or a doc comment, we push the current - // matcher onto a stack and push a new item containing the submatcher onto - // `cur_items`. - // - // At the beginning of the loop, if we reach the end of the delimited - // submatcher, we pop the stack to backtrack out of the descent. - let lower_elts = mem::replace(&mut item.top_elts, Tt(seq)); - let idx = item.idx; - item.stack.push(MatcherTtFrame { elts: lower_elts, idx }); - item.idx = 0; - cur_items.push(item); + TokenTree::Token(t) => { + // If the token matches, we can just advance the parser. Otherwise, this + // match hash failed, there is nothing to do, and hopefully another item in + // `cur_items` will match. + if token_name_eq(&t, token) { + item.idx += 1; + next_items.push(item); + } + } + + // These cannot appear in a matcher. + TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => unreachable!(), + } + } else if let Some(repetition) = &item.repetition { + // We are past the end of a repetition. + debug_assert!(idx <= len + 1); + debug_assert!(matches!(item.top_elts, Tt(TokenTree::Sequence(..)))); + + if idx == len { + // Add all matches from the sequence to `up`, and move the "dot" past the + // repetition in `up`. This allows for the case where the sequence matching is + // finished. + let mut new_pos = repetition.up.clone(); + for idx in item.match_lo..item.match_hi { + let sub = item.matches[idx].clone(); + new_pos.push_match(idx, MatchedSeq(sub)); + } + new_pos.match_cur = item.match_hi; + new_pos.idx += 1; + cur_items.push(new_pos); } - TokenTree::Token(t) => { - // If the token matches, we can just advance the parser. Otherwise, this match - // hash failed, there is nothing to do, and hopefully another item in - // `cur_items` will match. - if token_name_eq(&t, token) { + if idx == len && repetition.sep.is_some() { + if repetition.sep.as_ref().map_or(false, |sep| token_name_eq(token, sep)) { + // The matcher has a separator, and it matches the current token. We can + // advance past the separator token. item.idx += 1; next_items.push(item); } + } else if repetition.seq_op != mbe::KleeneOp::ZeroOrOne { + // We don't need a separator. Move the "dot" back to the beginning of the + // matcher and try to match again UNLESS we are only allowed to have _one_ + // repetition. + item.match_cur = item.match_lo; + item.idx = 0; + cur_items.push(item); } - - // These cannot appear in a matcher. - TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => unreachable!(), - } - } else if let Some(repetition) = &item.repetition { - // We are past the end of a repetition. - debug_assert!(idx <= len + 1); - debug_assert!(matches!(item.top_elts, Tt(TokenTree::Sequence(..)))); - - if idx == len { - // Add all matches from the sequence to `up`, and move the "dot" past the - // repetition in `up`. This allows for the case where the sequence matching is - // finished. - let mut new_pos = repetition.up.clone(); - for idx in item.match_lo..item.match_hi { - let sub = item.matches[idx].clone(); - new_pos.push_match(idx, MatchedSeq(sub)); + } else { + // We are past the end of the matcher, and not in a repetition. Look for end of + // input. + debug_assert_eq!(idx, len); + if *token == token::Eof { + eof_items = match eof_items { + EofItems::None => EofItems::One(item), + EofItems::One(_) | EofItems::Multiple => EofItems::Multiple, + } } - new_pos.match_cur = item.match_hi; - new_pos.idx += 1; - cur_items.push(new_pos); } + } - if idx == len && repetition.sep.is_some() { - if repetition.sep.as_ref().map_or(false, |sep| token_name_eq(token, sep)) { - // The matcher has a separator, and it matches the current token. We can - // advance past the separator token. - item.idx += 1; - next_items.push(item); + // If we reached the end of input, check that there is EXACTLY ONE possible matcher. + // Otherwise, either the parse is ambiguous (which is an error) or there is a syntax error. + if *token == token::Eof { + Some(match eof_items { + EofItems::One(mut eof_item) => { + let matches = + eof_item.matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap()); + nameize(sess, ms, matches) } - } else if repetition.seq_op != mbe::KleeneOp::ZeroOrOne { - // We don't need a separator. Move the "dot" back to the beginning of the - // matcher and try to match again UNLESS we are only allowed to have _one_ - // repetition. - item.match_cur = item.match_lo; - item.idx = 0; - cur_items.push(item); - } - } else { - // We are past the end of the matcher, and not in a repetition. Look for end of input. - debug_assert_eq!(idx, len); - if *token == token::Eof { - eof_items = match eof_items { - EofItems::None => EofItems::One(item), - EofItems::One(_) | EofItems::Multiple => EofItems::Multiple, + EofItems::Multiple => { + Error(token.span, "ambiguity: multiple successful parses".to_string()) } - } + EofItems::None => Failure( + Token::new( + token::Eof, + if token.span.is_dummy() { token.span } else { token.span.shrink_to_hi() }, + ), + "missing tokens in macro arguments", + ), + }) + } else { + None } } - // If we reached the end of input, check that there is EXACTLY ONE possible matcher. Otherwise, - // either the parse is ambiguous (which is an error) or there is a syntax error. - if *token == token::Eof { - Some(match eof_items { - EofItems::One(mut eof_item) => { - let matches = - eof_item.matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap()); - nameize(sess, ms, matches) + /// Use the given slice of token trees (`ms`) as a matcher. Match the token stream from the + /// given `parser` against it and return the match. + pub(super) fn parse_tt( + &self, + parser: &mut Cow<'_, Parser<'_>>, + ms: &[TokenTree], + macro_name: Ident, + ) -> NamedParseResult { + // A queue of possible matcher positions. We initialize it with the matcher position in + // which the "dot" is before the first token of the first token tree in `ms`. + // `parse_tt_inner` then processes all of these possible matcher positions and produces + // possible next positions into `next_items`. After some post-processing, the contents of + // `next_items` replenish `cur_items` and we start over again. + // + // This MatcherPos instance is allocated on the stack. All others -- and there are + // frequently *no* others! -- are allocated on the heap. + let mut initial = MatcherPos::new(ms); + let mut cur_items = smallvec![MatcherPosHandle::Ref(&mut initial)]; + + loop { + let mut next_items = SmallVec::new(); + + // Matcher positions black-box parsed by `Parser`. + let mut bb_items = SmallVec::new(); + + // Process `cur_items` until either we have finished the input or we need to get some + // parsing from the black-box parser done. + if let Some(result) = self.parse_tt_inner( + parser.sess, + ms, + &mut cur_items, + &mut next_items, + &mut bb_items, + &parser.token, + ) { + return result; } - EofItems::Multiple => { - Error(token.span, "ambiguity: multiple successful parses".to_string()) - } - EofItems::None => Failure( - Token::new( - token::Eof, - if token.span.is_dummy() { token.span } else { token.span.shrink_to_hi() }, - ), - "missing tokens in macro arguments", - ), - }) - } else { - None - } -} -/// Use the given slice of token trees (`ms`) as a matcher. Match the token stream from the given -/// `parser` against it and return the match. -pub(super) fn parse_tt( - parser: &mut Cow<'_, Parser<'_>>, - ms: &[TokenTree], - macro_name: Ident, -) -> NamedParseResult { - // A queue of possible matcher positions. We initialize it with the matcher position in which - // the "dot" is before the first token of the first token tree in `ms`. `parse_tt_inner` then - // processes all of these possible matcher positions and produces possible next positions into - // `next_items`. After some post-processing, the contents of `next_items` replenish `cur_items` - // and we start over again. - // - // This MatcherPos instance is allocated on the stack. All others -- and there are frequently - // *no* others! -- are allocated on the heap. - let mut initial = MatcherPos::new(ms); - let mut cur_items = smallvec![MatcherPosHandle::Ref(&mut initial)]; - - loop { - let mut next_items = SmallVec::new(); - - // Matcher positions black-box parsed by `Parser`. - let mut bb_items = SmallVec::new(); - - // Process `cur_items` until either we have finished the input or we need to get some - // parsing from the black-box parser done. - if let Some(result) = parse_tt_inner( - parser.sess, - ms, - &mut cur_items, - &mut next_items, - &mut bb_items, - &parser.token, - ) { - return result; - } - - // `parse_tt_inner` handled all cur_items, so it's empty. - assert!(cur_items.is_empty()); + // `parse_tt_inner` handled all cur_items, so it's empty. + assert!(cur_items.is_empty()); + + // Error messages here could be improved with links to original rules. + match (next_items.len(), bb_items.len()) { + (0, 0) => { + // There are no possible next positions AND we aren't waiting for the black-box + // parser: syntax error. + return Failure( + parser.token.clone(), + "no rules expected this token in macro call", + ); + } - // Error messages here could be improved with links to original rules. - match (next_items.len(), bb_items.len()) { - (0, 0) => { - // There are no possible next positions AND we aren't waiting for the black-box - // parser: syntax error. - return Failure(parser.token.clone(), "no rules expected this token in macro call"); - } + (_, 0) => { + // Dump all possible `next_items` into `cur_items` for the next iteration. Then + // process the next token. + cur_items.extend(next_items.drain(..)); + parser.to_mut().bump(); + } - (_, 0) => { - // Dump all possible `next_items` into `cur_items` for the next iteration. Then - // process the next token. - cur_items.extend(next_items.drain(..)); - parser.to_mut().bump(); - } + (0, 1) => { + // We need to call the black-box parser to get some nonterminal. + let mut item = bb_items.pop().unwrap(); + if let TokenTree::MetaVarDecl(span, _, Some(kind)) = + item.top_elts.get_tt(item.idx) + { + let match_cur = item.match_cur; + // We use the span of the metavariable declaration to determine any + // edition-specific matching behavior for non-terminals. + let nt = match parser.to_mut().parse_nonterminal(kind) { + Err(mut err) => { + err.span_label( + span, + format!( + "while parsing argument for this `{kind}` macro fragment" + ), + ) + .emit(); + return ErrorReported; + } + Ok(nt) => nt, + }; + item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt))); + item.idx += 1; + item.match_cur += 1; + } else { + unreachable!() + } + cur_items.push(item); + } - (0, 1) => { - // We need to call the black-box parser to get some nonterminal. - let mut item = bb_items.pop().unwrap(); - if let TokenTree::MetaVarDecl(span, _, Some(kind)) = item.top_elts.get_tt(item.idx) - { - let match_cur = item.match_cur; - // We use the span of the metavariable declaration to determine any - // edition-specific matching behavior for non-terminals. - let nt = match parser.to_mut().parse_nonterminal(kind) { - Err(mut err) => { - err.span_label( - span, - format!("while parsing argument for this `{kind}` macro fragment"), - ) - .emit(); - return ErrorReported; - } - Ok(nt) => nt, - }; - item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt))); - item.idx += 1; - item.match_cur += 1; - } else { - unreachable!() + (_, _) => { + // Too many possibilities! + return self.bb_items_ambiguity_error( + macro_name, + next_items, + bb_items, + parser.token.span, + ); } - cur_items.push(item); } - (_, _) => { - // Too many possibilities! - return bb_items_ambiguity_error( - macro_name, - next_items, - bb_items, - parser.token.span, - ); - } + assert!(!cur_items.is_empty()); } - - assert!(!cur_items.is_empty()); } -} -fn bb_items_ambiguity_error<'root, 'tt>( - macro_name: Ident, - next_items: SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, - bb_items: SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, - token_span: rustc_span::Span, -) -> NamedParseResult { - let nts = bb_items - .iter() - .map(|item| match item.top_elts.get_tt(item.idx) { - TokenTree::MetaVarDecl(_, bind, Some(kind)) => { - format!("{} ('{}')", kind, bind) - } - _ => panic!(), - }) - .collect::<Vec<String>>() - .join(" or "); - - Error( - token_span, - format!( - "local ambiguity when calling macro `{macro_name}`: multiple parsing options: {}", - match next_items.len() { - 0 => format!("built-in NTs {}.", nts), - 1 => format!("built-in NTs {} or 1 other option.", nts), - n => format!("built-in NTs {} or {} other options.", nts, n), - } - ), - ) + fn bb_items_ambiguity_error<'root, 'tt>( + &self, + macro_name: Ident, + next_items: SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, + bb_items: SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, + token_span: rustc_span::Span, + ) -> NamedParseResult { + let nts = bb_items + .iter() + .map(|item| match item.top_elts.get_tt(item.idx) { + TokenTree::MetaVarDecl(_, bind, Some(kind)) => { + format!("{} ('{}')", kind, bind) + } + _ => panic!(), + }) + .collect::<Vec<String>>() + .join(" or "); + + Error( + token_span, + format!( + "local ambiguity when calling macro `{macro_name}`: multiple parsing options: {}", + match next_items.len() { + 0 => format!("built-in NTs {}.", nts), + 1 => format!("built-in NTs {} or 1 other option.", nts), + n => format!("built-in NTs {} or {} other options.", nts, n), + } + ), + ) + } } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index b93edf8da7a..eaf02607e70 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -3,8 +3,7 @@ use crate::base::{SyntaxExtension, SyntaxExtensionKind}; use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind}; use crate::mbe; use crate::mbe::macro_check; -use crate::mbe::macro_parser::parse_tt; -use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success}; +use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success, TtParser}; use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq}; use crate::mbe::transcribe::transcribe; @@ -246,6 +245,7 @@ fn generic_extension<'cx>( // this situation.) let parser = parser_from_cx(sess, arg.clone()); + let tt_parser = TtParser; for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers let lhs_tt = match *lhs { @@ -259,7 +259,7 @@ fn generic_extension<'cx>( // are not recorded. On the first `Success(..)`ful matcher, the spans are merged. let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut()); - match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt, name) { + match tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs_tt, name) { Success(named_matches) => { // The matcher was `Success(..)`ful. // Merge the gated spans from parsing the matcher with the pre-existing ones. @@ -352,9 +352,11 @@ fn generic_extension<'cx>( mbe::TokenTree::Delimited(_, ref delim) => &delim.tts, _ => continue, }; - if let Success(_) = - parse_tt(&mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), lhs_tt, name) - { + if let Success(_) = tt_parser.parse_tt( + &mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), + lhs_tt, + name, + ) { if comma_span.is_dummy() { err.note("you might be missing a comma"); } else { @@ -447,25 +449,27 @@ pub fn compile_declarative_macro( ]; let parser = Parser::new(&sess.parse_sess, body, true, rustc_parse::MACRO_ARGUMENTS); - let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram, def.ident) { - Success(m) => m, - Failure(token, msg) => { - let s = parse_failure_msg(&token); - let sp = token.span.substitute_dummy(def.span); - sess.parse_sess.span_diagnostic.struct_span_err(sp, &s).span_label(sp, msg).emit(); - return mk_syn_ext(Box::new(macro_rules_dummy_expander)); - } - Error(sp, msg) => { - sess.parse_sess - .span_diagnostic - .struct_span_err(sp.substitute_dummy(def.span), &msg) - .emit(); - return mk_syn_ext(Box::new(macro_rules_dummy_expander)); - } - ErrorReported => { - return mk_syn_ext(Box::new(macro_rules_dummy_expander)); - } - }; + let tt_parser = TtParser; + let argument_map = + match tt_parser.parse_tt(&mut Cow::Borrowed(&parser), &argument_gram, def.ident) { + Success(m) => m, + Failure(token, msg) => { + let s = parse_failure_msg(&token); + let sp = token.span.substitute_dummy(def.span); + sess.parse_sess.span_diagnostic.struct_span_err(sp, &s).span_label(sp, msg).emit(); + return mk_syn_ext(Box::new(macro_rules_dummy_expander)); + } + Error(sp, msg) => { + sess.parse_sess + .span_diagnostic + .struct_span_err(sp.substitute_dummy(def.span), &msg) + .emit(); + return mk_syn_ext(Box::new(macro_rules_dummy_expander)); + } + ErrorReported => { + return mk_syn_ext(Box::new(macro_rules_dummy_expander)); + } + }; let mut valid = true; |
