提交 09c3e820 编写于 作者: N Nicholas Nethercote

Refactor the second half of `parse_tt`.

The current structure makes it hard to tell that there are just four
distinct code paths, depending on how many items there are in `bb_items`
and `next_items`. This commit introduces a `match` that clarifies
things.
上级 352e6213
...@@ -744,70 +744,77 @@ pub(super) fn parse_tt( ...@@ -744,70 +744,77 @@ pub(super) fn parse_tt(
// unnecessary implicit clone later in `Rc::make_mut`. // unnecessary implicit clone later in `Rc::make_mut`.
drop(eof_items); drop(eof_items);
// If there are no possible next positions AND we aren't waiting for the black-box parser, match (next_items.len(), bb_items.len()) {
// then there is a syntax error. (0, 0) => {
if bb_items.is_empty() && next_items.is_empty() { // There are no possible next positions AND we aren't waiting for the black-box
return Failure(parser.token.clone(), "no rules expected this token in macro call"); // parser: syntax error.
} return Failure(parser.token.clone(), "no rules expected this token in macro call");
}
if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 { (_, 0) => {
// We need to call out to parse some rust nonterminal (black-box) parser. But something // Dump all possible `next_items` into `cur_items` for the next iteration. Then
// is wrong, because there is not EXACTLY ONE of these. // process the next token.
let nts = bb_items cur_items.extend(next_items.drain(..));
.iter() parser.to_mut().bump();
.map(|item| match item.top_elts.get_tt(item.idx) { }
TokenTree::MetaVarDecl(_, bind, Some(kind)) => format!("{} ('{}')", kind, bind),
_ => panic!(),
})
.collect::<Vec<String>>()
.join(" or ");
return Error(
parser.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),
}
),
);
}
if !next_items.is_empty() { (0, 1) => {
// Dump all possible `next_items` into `cur_items` for the next iteration. Then process // We need to call the black-box parser to get some nonterminal.
// the next token. let mut item = bb_items.pop().unwrap();
cur_items.extend(next_items.drain(..)); if let TokenTree::MetaVarDecl(span, _, Some(kind)) = item.top_elts.get_tt(item.idx)
parser.to_mut().bump(); {
} else { let match_cur = item.match_cur;
// Finally, we have the case where we need to call the black-box parser to get some // We use the span of the metavariable declaration to determine any
// nonterminal. // edition-specific matching behavior for non-terminals.
assert_eq!(bb_items.len(), 1); let nt = match parser.to_mut().parse_nonterminal(kind) {
Err(mut err) => {
let mut item = bb_items.pop().unwrap(); err.span_label(
if let TokenTree::MetaVarDecl(span, _, Some(kind)) = item.top_elts.get_tt(item.idx) { span,
let match_cur = item.match_cur; format!(
// We use the span of the metavariable declaration to determine any "while parsing argument for this `{}` macro fragment",
// edition-specific matching behavior for non-terminals. kind
let nt = match parser.to_mut().parse_nonterminal(kind) { ),
Err(mut err) => { )
err.span_label( .emit();
span, return ErrorReported;
format!("while parsing argument for this `{}` macro fragment", kind), }
) Ok(nt) => nt,
.emit(); };
return ErrorReported; item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt)));
} item.idx += 1;
Ok(nt) => nt, item.match_cur += 1;
}; } else {
item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt))); unreachable!()
item.idx += 1; }
item.match_cur += 1; cur_items.push(item);
} else { }
unreachable!()
(_, _) => {
// We need to call the black-box parser to get some nonterminal, but something is
// wrong.
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 ");
return Error(
parser.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),
}
),
);
} }
cur_items.push(item);
} }
assert!(!cur_items.is_empty()); assert!(!cur_items.is_empty());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册