use ast;
use ast::{TokenTree, Name};
-use ast::{TtDelimited, TtSequence, TtToken};
use codemap::{BytePos, mk_sp, Span};
use codemap;
use parse::lexer::*; //resolve bug?
use parse::ParseSess;
-use parse::attr::ParserAttr;
use parse::parser::{LifetimeAndTypesWithoutColons, Parser};
use parse::token::{Eof, DocComment, MatchNt, SubstNt};
use parse::token::{Token, Nonterminal};
impl TokenTreeOrTokenTreeVec {
fn len(&self) -> usize {
- match self {
- &TtSeq(ref v) => v.len(),
- &Tt(ref tt) => tt.len(),
+ match *self {
+ TtSeq(ref v) => v.len(),
+ Tt(ref tt) => tt.len(),
}
}
fn get_tt(&self, index: usize) -> TokenTree {
- match self {
- &TtSeq(ref v) => v[index].clone(),
- &Tt(ref tt) => tt.get_tt(index),
+ match *self {
+ TtSeq(ref v) => v[index].clone(),
+ Tt(ref tt) => tt.get_tt(index),
}
}
}
pub fn count_names(ms: &[TokenTree]) -> usize {
ms.iter().fold(0, |count, elt| {
- count + match elt {
- &TtSequence(_, ref seq) => {
+ count + match *elt {
+ TokenTree::Sequence(_, ref seq) => {
seq.num_captures
}
- &TtDelimited(_, ref delim) => {
+ TokenTree::Delimited(_, ref delim) => {
count_names(&delim.tts)
}
- &TtToken(_, MatchNt(..)) => {
+ TokenTree::Token(_, MatchNt(..)) => {
1
}
- &TtToken(_, _) => 0,
+ TokenTree::Token(_, _) => 0,
}
})
}
}
pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>])
- -> HashMap<Name, Rc<NamedMatch>> {
+ -> ParseResult<HashMap<Name, Rc<NamedMatch>>> {
fn n_rec(p_s: &ParseSess, m: &TokenTree, res: &[Rc<NamedMatch>],
- ret_val: &mut HashMap<Name, Rc<NamedMatch>>, idx: &mut usize) {
- match m {
- &TtSequence(_, ref seq) => {
+ ret_val: &mut HashMap<Name, Rc<NamedMatch>>, idx: &mut usize)
+ -> Result<(), (codemap::Span, String)> {
+ match *m {
+ TokenTree::Sequence(_, ref seq) => {
for next_m in &seq.tts {
- n_rec(p_s, next_m, res, ret_val, idx)
+ try!(n_rec(p_s, next_m, res, ret_val, idx))
}
}
- &TtDelimited(_, ref delim) => {
+ TokenTree::Delimited(_, ref delim) => {
for next_m in &delim.tts {
- n_rec(p_s, next_m, res, ret_val, idx)
+ try!(n_rec(p_s, next_m, res, ret_val, idx));
}
}
- &TtToken(sp, MatchNt(bind_name, _, _, _)) => {
+ TokenTree::Token(sp, MatchNt(bind_name, _, _, _)) => {
match ret_val.entry(bind_name.name) {
Vacant(spot) => {
spot.insert(res[*idx].clone());
*idx += 1;
}
Occupied(..) => {
- panic!(p_s.span_diagnostic
- .span_fatal(sp,
- &format!("duplicated bind name: {}",
- bind_name)))
+ return Err((sp, format!("duplicated bind name: {}", bind_name)))
}
}
}
- &TtToken(_, SubstNt(..)) => panic!("Cannot fill in a NT"),
- &TtToken(_, _) => (),
+ TokenTree::Token(sp, SubstNt(..)) => {
+ return Err((sp, "missing fragment specifier".to_string()))
+ }
+ TokenTree::Token(_, _) => (),
}
+
+ Ok(())
}
+
let mut ret_val = HashMap::new();
let mut idx = 0;
- for m in ms { n_rec(p_s, m, res, &mut ret_val, &mut idx) }
- ret_val
+ for m in ms {
+ match n_rec(p_s, m, res, &mut ret_val, &mut idx) {
+ Ok(_) => {},
+ Err((sp, msg)) => return Error(sp, msg),
+ }
+ }
+
+ Success(ret_val)
}
pub enum ParseResult<T> {
Success(T),
+ /// Arm failed to match
Failure(codemap::Span, String),
+ /// Fatal error (malformed macro?). Abort compilation.
Error(codemap::Span, String)
}
} else {
match ei.top_elts.get_tt(idx) {
/* need to descend into sequence */
- TtSequence(sp, seq) => {
+ TokenTree::Sequence(sp, seq) => {
if seq.op == ast::ZeroOrMore {
let mut new_ei = ei.clone();
new_ei.match_cur += seq.num_captures;
match_hi: ei_t.match_cur + seq.num_captures,
up: Some(ei_t),
sp_lo: sp.lo,
- top_elts: Tt(TtSequence(sp, seq)),
+ top_elts: Tt(TokenTree::Sequence(sp, seq)),
}));
}
- TtToken(_, MatchNt(..)) => {
+ TokenTree::Token(_, MatchNt(..)) => {
// Built-in nonterminals never start with these tokens,
// so we can eliminate them from consideration.
match tok {
_ => bb_eis.push(ei),
}
}
- TtToken(sp, SubstNt(..)) => {
+ TokenTree::Token(sp, SubstNt(..)) => {
return Error(sp, "missing fragment specifier".to_string())
}
- seq @ TtDelimited(..) | seq @ TtToken(_, DocComment(..)) => {
+ seq @ TokenTree::Delimited(..) | seq @ TokenTree::Token(_, DocComment(..)) => {
let lower_elts = mem::replace(&mut ei.top_elts, Tt(seq));
let idx = ei.idx;
ei.stack.push(MatcherTtFrame {
ei.idx = 0;
cur_eis.push(ei);
}
- TtToken(_, ref t) => {
+ TokenTree::Token(_, ref t) => {
let mut ei_t = ei.clone();
if token_name_eq(t,&tok) {
ei_t.idx += 1;
for dv in &mut (&mut eof_eis[0]).matches {
v.push(dv.pop().unwrap());
}
- return Success(nameize(sess, ms, &v[..]));
+ return nameize(sess, ms, &v[..]);
} else if eof_eis.len() > 1 {
return Error(sp, "ambiguity: multiple successful parses".to_string());
} else {
if (!bb_eis.is_empty() && !next_eis.is_empty())
|| bb_eis.len() > 1 {
let nts = bb_eis.iter().map(|ei| match ei.top_elts.get_tt(ei.idx) {
- TtToken(_, MatchNt(bind, name, _, _)) => {
+ TokenTree::Token(_, MatchNt(bind, name, _, _)) => {
format!("{} ('{}')", name, bind)
}
_ => panic!()
let mut ei = bb_eis.pop().unwrap();
match ei.top_elts.get_tt(ei.idx) {
- TtToken(span, MatchNt(_, ident, _, _)) => {
+ TokenTree::Token(span, MatchNt(_, ident, _, _)) => {
let match_cur = ei.match_cur;
(&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal(
parse_nt(&mut rust_parser, span, &ident.name.as_str()))));
// check at the beginning and the parser checks after each bump
panictry!(p.check_unknown_macro_variable());
match name {
- "item" => match p.parse_item() {
+ "item" => match panictry!(p.parse_item()) {
Some(i) => token::NtItem(i),
None => panic!(p.fatal("expected an item keyword"))
},
"block" => token::NtBlock(panictry!(p.parse_block())),
- "stmt" => match p.parse_stmt() {
+ "stmt" => match panictry!(p.parse_stmt()) {
Some(s) => token::NtStmt(s),
None => panic!(p.fatal("expected a statement"))
},
- "pat" => token::NtPat(p.parse_pat()),
- "expr" => token::NtExpr(p.parse_expr()),
- "ty" => token::NtTy(p.parse_ty()),
+ "pat" => token::NtPat(panictry!(p.parse_pat())),
+ "expr" => token::NtExpr(panictry!(p.parse_expr())),
+ "ty" => token::NtTy(panictry!(p.parse_ty())),
// this could be handled like a token, since it is one
"ident" => match p.token {
token::Ident(sn,b) => { panictry!(p.bump()); token::NtIdent(Box::new(sn),b) }
"path" => {
token::NtPath(Box::new(panictry!(p.parse_path(LifetimeAndTypesWithoutColons))))
},
- "meta" => token::NtMeta(p.parse_meta_item()),
+ "meta" => token::NtMeta(panictry!(p.parse_meta_item())),
_ => {
panic!(p.span_fatal_help(sp,
&format!("invalid fragment specifier `{}`", name),