]> git.proxmox.com Git - rustc.git/blobdiff - src/libsyntax/ext/tt/macro_parser.rs
Imported Upstream version 1.6.0+dfsg1
[rustc.git] / src / libsyntax / ext / tt / macro_parser.rs
index 8dec9ae1e98750b1e6d604278ba8596987db749e..5b8307eb6c6f2a1f4e4a93dbdea595b8971ec3c6 100644 (file)
@@ -80,12 +80,10 @@ use self::TokenTreeOrTokenTreeVec::*;
 
 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};
@@ -109,16 +107,16 @@ enum TokenTreeOrTokenTreeVec {
 
 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),
         }
     }
 }
@@ -146,17 +144,17 @@ pub struct MatcherPos {
 
 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,
         }
     })
 }
@@ -202,47 +200,58 @@ pub enum NamedMatch {
 }
 
 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)
 }
 
@@ -363,7 +372,7 @@ pub fn parse(sess: &ParseSess,
             } 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;
@@ -389,10 +398,10 @@ pub fn parse(sess: &ParseSess,
                             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 {
@@ -400,10 +409,10 @@ pub fn parse(sess: &ParseSess,
                             _ => 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 {
@@ -413,7 +422,7 @@ pub fn parse(sess: &ParseSess,
                         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;
@@ -431,7 +440,7 @@ pub fn parse(sess: &ParseSess,
                 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 {
@@ -441,7 +450,7 @@ pub fn parse(sess: &ParseSess,
             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!()
@@ -469,7 +478,7 @@ pub fn parse(sess: &ParseSess,
 
                 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()))));
@@ -503,18 +512,18 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal {
     // 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) }
@@ -527,7 +536,7 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal {
         "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),