1
Fork 0

Slightly improved macro diagnostics + Indentation fixes

This commit is contained in:
Jonas Schievink 2015-08-15 19:37:25 +02:00
parent c1e865c9df
commit 5e8d39ebfd
2 changed files with 51 additions and 47 deletions

View file

@ -401,7 +401,7 @@ pub fn parse(sess: &ParseSess,
} }
} }
TtToken(sp, SubstNt(..)) => { TtToken(sp, SubstNt(..)) => {
return Error(sp, "Cannot transcribe in macro LHS".to_string()) return Error(sp, "missing fragment specifier".to_string())
} }
seq @ TtDelimited(..) | seq @ TtToken(_, DocComment(..)) => { seq @ TtDelimited(..) | seq @ TtToken(_, DocComment(..)) => {
let lower_elts = mem::replace(&mut ei.top_elts, Tt(seq)); let lower_elts = mem::replace(&mut ei.top_elts, Tt(seq));
@ -440,20 +440,24 @@ pub fn parse(sess: &ParseSess,
} else { } else {
if (!bb_eis.is_empty() && !next_eis.is_empty()) if (!bb_eis.is_empty() && !next_eis.is_empty())
|| bb_eis.len() > 1 { || bb_eis.len() > 1 {
let nts = bb_eis.iter().map(|ei| { let nts = bb_eis.iter().map(|ei| match ei.top_elts.get_tt(ei.idx) {
match ei.top_elts.get_tt(ei.idx) { TtToken(_, MatchNt(bind, name, _, _)) => {
TtToken(_, MatchNt(bind, name, _, _)) => {
format!("{} ('{}')", name, bind) format!("{} ('{}')", name, bind)
} }
_ => panic!() _ => panic!()
} }).collect::<Vec<String>>().join(" or "); }).collect::<Vec<String>>().join(" or ");
return Error(sp, format!( return Error(sp, format!(
"local ambiguity: multiple parsing options: \ "local ambiguity: multiple parsing options: {}",
built-in NTs {} or {} other options.", match next_eis.len() {
nts, next_eis.len()).to_string()); 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),
}
))
} else if bb_eis.is_empty() && next_eis.is_empty() { } else if bb_eis.is_empty() && next_eis.is_empty() {
return Failure(sp, format!("no rules expected the token `{}`", return Failure(sp, format!("no rules expected the token `{}`",
pprust::token_to_string(&tok)).to_string()); pprust::token_to_string(&tok)));
} else if !next_eis.is_empty() { } else if !next_eis.is_empty() {
/* Now process the next token */ /* Now process the next token */
while !next_eis.is_empty() { while !next_eis.is_empty() {
@ -465,14 +469,14 @@ pub fn parse(sess: &ParseSess,
let mut ei = bb_eis.pop().unwrap(); let mut ei = bb_eis.pop().unwrap();
match ei.top_elts.get_tt(ei.idx) { match ei.top_elts.get_tt(ei.idx) {
TtToken(span, MatchNt(_, ident, _, _)) => { TtToken(span, MatchNt(_, ident, _, _)) => {
let match_cur = ei.match_cur; let match_cur = ei.match_cur;
(&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal( (&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal(
parse_nt(&mut rust_parser, span, &ident.name.as_str())))); parse_nt(&mut rust_parser, span, &ident.name.as_str()))));
ei.idx += 1; ei.idx += 1;
ei.match_cur += 1; ei.match_cur += 1;
} }
_ => panic!() _ => panic!()
} }
cur_eis.push(ei); cur_eis.push(ei);
@ -499,37 +503,37 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal {
// check at the beginning and the parser checks after each bump // check at the beginning and the parser checks after each bump
panictry!(p.check_unknown_macro_variable()); panictry!(p.check_unknown_macro_variable());
match name { match name {
"item" => match p.parse_item() { "item" => match p.parse_item() {
Some(i) => token::NtItem(i), Some(i) => token::NtItem(i),
None => panic!(p.fatal("expected an item keyword")) None => panic!(p.fatal("expected an item keyword"))
}, },
"block" => token::NtBlock(panictry!(p.parse_block())), "block" => token::NtBlock(panictry!(p.parse_block())),
"stmt" => match p.parse_stmt() { "stmt" => match p.parse_stmt() {
Some(s) => token::NtStmt(s), Some(s) => token::NtStmt(s),
None => panic!(p.fatal("expected a statement")) None => panic!(p.fatal("expected a statement"))
}, },
"pat" => token::NtPat(p.parse_pat()), "pat" => token::NtPat(p.parse_pat()),
"expr" => token::NtExpr(p.parse_expr()), "expr" => token::NtExpr(p.parse_expr()),
"ty" => token::NtTy(p.parse_ty()), "ty" => token::NtTy(p.parse_ty()),
// this could be handled like a token, since it is one // this could be handled like a token, since it is one
"ident" => match p.token { "ident" => match p.token {
token::Ident(sn,b) => { panictry!(p.bump()); token::NtIdent(Box::new(sn),b) } token::Ident(sn,b) => { panictry!(p.bump()); token::NtIdent(Box::new(sn),b) }
_ => {
let token_str = pprust::token_to_string(&p.token);
panic!(p.fatal(&format!("expected ident, found {}",
&token_str[..])))
}
},
"path" => {
token::NtPath(Box::new(panictry!(p.parse_path(LifetimeAndTypesWithoutColons))))
},
"meta" => token::NtMeta(p.parse_meta_item()),
_ => { _ => {
let token_str = pprust::token_to_string(&p.token); panic!(p.span_fatal_help(sp,
panic!(p.fatal(&format!("expected ident, found {}",
&token_str[..])))
}
},
"path" => {
token::NtPath(Box::new(panictry!(p.parse_path(LifetimeAndTypesWithoutColons))))
}
"meta" => token::NtMeta(p.parse_meta_item()),
_ => {
panic!(p.span_fatal_help(sp,
&format!("invalid fragment specifier `{}`", name), &format!("invalid fragment specifier `{}`", name),
"valid fragment specifiers are `ident`, `block`, \ "valid fragment specifiers are `ident`, `block`, \
`stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \ `stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \
and `item`")) and `item`"))
} }
} }
} }

View file

@ -8,7 +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.
macro_rules! test { ($a, $b) => (()); } //~ ERROR Cannot transcribe macro_rules! test { ($a, $b) => (()); } //~ ERROR missing fragment
fn main() { fn main() {
test!() test!()