Fix #21356
This commit is contained in:
parent
dcaeb6aa23
commit
e3d099de6f
@ -8,8 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use ast::{TokenTree, TtDelimited, TtSequence, TtToken};
|
use ast::{self, TokenTree, TtDelimited, TtSequence, TtToken};
|
||||||
use ast;
|
|
||||||
use codemap::{Span, DUMMY_SP};
|
use codemap::{Span, DUMMY_SP};
|
||||||
use ext::base::{ExtCtxt, MacResult, SyntaxExtension};
|
use ext::base::{ExtCtxt, MacResult, SyntaxExtension};
|
||||||
use ext::base::{NormalTT, TTMacroExpander};
|
use ext::base::{NormalTT, TTMacroExpander};
|
||||||
@ -19,9 +18,8 @@ use ext::tt::macro_parser::{parse, parse_or_else};
|
|||||||
use parse::lexer::{new_tt_reader, new_tt_reader_with_doc_flag};
|
use parse::lexer::{new_tt_reader, new_tt_reader_with_doc_flag};
|
||||||
use parse::parser::Parser;
|
use parse::parser::Parser;
|
||||||
use parse::attr::ParserAttr;
|
use parse::attr::ParserAttr;
|
||||||
use parse::token::{special_idents, gensym_ident, NtTT, Token};
|
use parse::token::{self, special_idents, gensym_ident, NtTT, Token};
|
||||||
use parse::token::Token::*;
|
use parse::token::Token::*;
|
||||||
use parse::token;
|
|
||||||
use print;
|
use print;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
|
||||||
@ -333,16 +331,20 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
|
|||||||
|
|
||||||
let tok = if let TtToken(_, ref tok) = *token { tok } else { unreachable!() };
|
let tok = if let TtToken(_, ref tok) = *token { tok } else { unreachable!() };
|
||||||
// If T' is in the set FOLLOW(NT), continue. Else, reject.
|
// If T' is in the set FOLLOW(NT), continue. Else, reject.
|
||||||
match &next_token {
|
match (&next_token, is_in_follow(cx, &next_token, frag_spec.as_str())) {
|
||||||
&Eof => return Some((sp, tok.clone())),
|
(&Eof, _) => return Some((sp, tok.clone())),
|
||||||
_ if is_in_follow(cx, &next_token, frag_spec.as_str()) => continue,
|
(_, Ok(true)) => continue,
|
||||||
next => {
|
(next, Ok(false)) => {
|
||||||
cx.span_err(sp, format!("`${0}:{1}` is followed by `{2}`, which \
|
cx.span_err(sp, format!("`${0}:{1}` is followed by `{2}`, which \
|
||||||
is not allowed for `{1}` fragments",
|
is not allowed for `{1}` fragments",
|
||||||
name.as_str(), frag_spec.as_str(),
|
name.as_str(), frag_spec.as_str(),
|
||||||
token_to_string(next)).as_slice());
|
token_to_string(next)).as_slice());
|
||||||
continue
|
continue
|
||||||
},
|
},
|
||||||
|
(_, Err(msg)) => {
|
||||||
|
cx.span_err(sp, msg.as_slice());
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TtSequence(sp, ref seq) => {
|
TtSequence(sp, ref seq) => {
|
||||||
@ -409,12 +411,12 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
|
|||||||
last
|
last
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_in_follow(cx: &ExtCtxt, tok: &Token, frag: &str) -> bool {
|
fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result<bool, String> {
|
||||||
if let &CloseDelim(_) = tok {
|
if let &CloseDelim(_) = tok {
|
||||||
return true;
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
match frag {
|
Ok(match frag {
|
||||||
"item" => {
|
"item" => {
|
||||||
// since items *must* be followed by either a `;` or a `}`, we can
|
// since items *must* be followed by either a `;` or a `}`, we can
|
||||||
// accept anything after them
|
// accept anything after them
|
||||||
@ -453,7 +455,6 @@ fn is_in_follow(cx: &ExtCtxt, tok: &Token, frag: &str) -> bool {
|
|||||||
// harmless
|
// harmless
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
_ => cx.bug(format!("unrecognized builtin nonterminal {}",
|
_ => return Err(format!("unrecognized builtin nonterminal `{}`", frag)),
|
||||||
frag).as_slice()),
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user