pub enum ParseResult<T> {
Success(T),
- /// Arm failed to match
- Failure(syntax_pos::Span, String),
+ /// Arm failed to match. If the second parameter is `token::Eof`, it
+ /// indicates an unexpected end of macro invocation. Otherwise, it
+ /// indicates that no rules expected the given token.
+ Failure(syntax_pos::Span, Token),
/// Fatal error (malformed macro?). Abort compilation.
Error(syntax_pos::Span, String)
}
+pub fn parse_failure_msg(tok: Token) -> String {
+ match tok {
+ token::Eof => "unexpected end of macro invocation".to_string(),
+ _ => format!("no rules expected the token `{}`", pprust::token_to_string(&tok)),
+ }
+}
+
pub type NamedParseResult = ParseResult<HashMap<Ident, Rc<NamedMatch>>>;
-pub type PositionalParseResult = ParseResult<Vec<Rc<NamedMatch>>>;
/// Perform a token equality check, ignoring syntax context (that is, an
/// unhygienic comparison)
} else if eof_eis.len() > 1 {
return Error(sp, "ambiguity: multiple successful parses".to_string());
} else {
- return Failure(sp, "unexpected end of macro invocation".to_string());
+ return Failure(sp, token::Eof);
}
} 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 `{}`",
- pprust::token_to_string(&tok)));
+ return Failure(sp, tok);
} else if !next_eis.is_empty() {
/* Now process the next token */
while !next_eis.is_empty() {
use ext::placeholders;
use ext::tt::macro_parser::{Success, Error, Failure};
use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
-use ext::tt::macro_parser::parse;
+use ext::tt::macro_parser::{parse, parse_failure_msg};
use parse::ParseSess;
use parse::lexer::new_tt_reader;
use parse::parser::{Parser, Restrictions};
// Which arm's failure should we report? (the one furthest along)
let mut best_fail_spot = DUMMY_SP;
- let mut best_fail_msg = "internal error: ran no matchers".to_string();
+ let mut best_fail_tok = None;
for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers
let lhs_tt = match *lhs {
macro_ident: name
})
}
- Failure(sp, msg) => if sp.lo >= best_fail_spot.lo {
+ Failure(sp, tok) => if sp.lo >= best_fail_spot.lo {
best_fail_spot = sp;
- best_fail_msg = msg;
+ best_fail_tok = Some(tok);
},
Error(err_sp, ref msg) => {
cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..])
}
}
- cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg[..]);
+ let best_fail_msg = parse_failure_msg(best_fail_tok.expect("ran no matchers"));
+ cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg);
}
pub struct MacroRulesExpander;
let argument_map = match parse(sess, &Vec::new(), arg_reader, &argument_gram) {
Success(m) => m,
- Failure(sp, str) | Error(sp, str) => {
- panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &str));
+ Failure(sp, tok) => {
+ let s = parse_failure_msg(tok);
+ panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s));
+ }
+ Error(sp, s) => {
+ panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s));
}
};
use syntax::ext::build::AstBuilder;
use syntax::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
use syntax::ext::tt::macro_parser::{Success, Failure, Error};
+use syntax::ext::tt::macro_parser::parse_failure_msg;
use syntax::ptr::P;
use syntax_pos::Span;
use rustc_plugin::Registry;
_ => unreachable!()
}
}
- Failure(_, s) | Error(_, s) => {
- panic!("expected Success, but got Error/Failure: {}", s);
+ Failure(_, tok) => {
+ panic!("expected Success, but got Failure: {}", parse_failure_msg(tok));
+ }
+ Error(_, s) => {
+ panic!("expected Success, but got Error: {}", s);
}
};