summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-11-03 03:06:03 +0000
committerbors <bors@rust-lang.org>2015-11-03 03:06:03 +0000
commitb7fbfb658e0e3e3be37c5b6704fd6b4d5991ae8c (patch)
tree9795a4c94d2336c920d9be3f12d62df0292b273e /src/libsyntax/parse
parent749625ad6d15d0254b90e3d16f79d1cb1e260969 (diff)
parente7d3ae606ed496144554dae499b69207da3b09c5 (diff)
downloadrust-b7fbfb658e0e3e3be37c5b6704fd6b4d5991ae8c.tar.gz
rust-b7fbfb658e0e3e3be37c5b6704fd6b4d5991ae8c.zip
Auto merge of #29285 - eefriedman:libsyntax-panic, r=nrc
A set of commits which pushes some panics out of core parser methods, and into users of those parser methods.
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/attr.rs88
-rw-r--r--src/libsyntax/parse/lexer/comments.rs2
-rw-r--r--src/libsyntax/parse/lexer/mod.rs70
-rw-r--r--src/libsyntax/parse/mod.rs20
-rw-r--r--src/libsyntax/parse/parser.rs50
5 files changed, 111 insertions, 119 deletions
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index 219360093d1..5df2478d487 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -12,30 +12,21 @@ use attr;
 use ast;
 use codemap::{spanned, Spanned, mk_sp, Span};
 use parse::common::*; //resolve bug?
+use parse::PResult;
 use parse::token;
 use parse::parser::{Parser, TokenType};
 use ptr::P;
 
-/// A parser that can parse attributes.
-pub trait ParserAttr {
-    fn parse_outer_attributes(&mut self) -> Vec<ast::Attribute>;
-    fn parse_inner_attributes(&mut self) -> Vec<ast::Attribute>;
-    fn parse_attribute(&mut self, permit_inner: bool) -> ast::Attribute;
-    fn parse_meta_item(&mut self) -> P<ast::MetaItem>;
-    fn parse_meta_seq(&mut self) -> Vec<P<ast::MetaItem>>;
-    fn parse_optional_meta(&mut self) -> Vec<P<ast::MetaItem>>;
-}
-
-impl<'a> ParserAttr for Parser<'a> {
+impl<'a> Parser<'a> {
     /// Parse attributes that appear before an item
-    fn parse_outer_attributes(&mut self) -> Vec<ast::Attribute> {
+    pub fn parse_outer_attributes(&mut self) -> PResult<Vec<ast::Attribute>> {
         let mut attrs: Vec<ast::Attribute> = Vec::new();
         loop {
             debug!("parse_outer_attributes: self.token={:?}",
                    self.token);
             match self.token {
               token::Pound => {
-                attrs.push(self.parse_attribute(false));
+                attrs.push(try!(self.parse_attribute(false)));
               }
               token::DocComment(s) => {
                 let attr = ::attr::mk_sugared_doc_attr(
@@ -45,32 +36,32 @@ impl<'a> ParserAttr for Parser<'a> {
                     self.span.hi
                 );
                 if attr.node.style != ast::AttrStyle::Outer {
-                  panic!(self.fatal("expected outer comment"));
+                  return Err(self.fatal("expected outer comment"));
                 }
                 attrs.push(attr);
-                panictry!(self.bump());
+                try!(self.bump());
               }
               _ => break
             }
         }
-        return attrs;
+        return Ok(attrs);
     }
 
     /// Matches `attribute = # ! [ meta_item ]`
     ///
     /// If permit_inner is true, then a leading `!` indicates an inner
     /// attribute
-    fn parse_attribute(&mut self, permit_inner: bool) -> ast::Attribute {
+    pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<ast::Attribute> {
         debug!("parse_attributes: permit_inner={:?} self.token={:?}",
                permit_inner, self.token);
         let (span, value, mut style) = match self.token {
             token::Pound => {
                 let lo = self.span.lo;
-                panictry!(self.bump());
+                try!(self.bump());
 
                 if permit_inner { self.expected_tokens.push(TokenType::Token(token::Not)); }
                 let style = if self.token == token::Not {
-                    panictry!(self.bump());
+                    try!(self.bump());
                     if !permit_inner {
                         let span = self.span;
                         self.span_err(span,
@@ -84,27 +75,27 @@ impl<'a> ParserAttr for Parser<'a> {
                     ast::AttrStyle::Outer
                 };
 
-                panictry!(self.expect(&token::OpenDelim(token::Bracket)));
-                let meta_item = self.parse_meta_item();
+                try!(self.expect(&token::OpenDelim(token::Bracket)));
+                let meta_item = try!(self.parse_meta_item());
                 let hi = self.span.hi;
-                panictry!(self.expect(&token::CloseDelim(token::Bracket)));
+                try!(self.expect(&token::CloseDelim(token::Bracket)));
 
                 (mk_sp(lo, hi), meta_item, style)
             }
             _ => {
                 let token_str = self.this_token_to_string();
-                panic!(self.fatal(&format!("expected `#`, found `{}`", token_str)));
+                return Err(self.fatal(&format!("expected `#`, found `{}`", token_str)));
             }
         };
 
         if permit_inner && self.token == token::Semi {
-            panictry!(self.bump());
+            try!(self.bump());
             self.span_warn(span, "this inner attribute syntax is deprecated. \
                            The new syntax is `#![foo]`, with a bang and no semicolon");
             style = ast::AttrStyle::Inner;
         }
 
-        return Spanned {
+        Ok(Spanned {
             span: span,
             node: ast::Attribute_ {
                 id: attr::mk_attr_id(),
@@ -112,7 +103,7 @@ impl<'a> ParserAttr for Parser<'a> {
                 value: value,
                 is_sugared_doc: false
             }
-        };
+        })
     }
 
     /// Parse attributes that appear after the opening of an item. These should
@@ -120,7 +111,7 @@ impl<'a> ParserAttr for Parser<'a> {
     /// terminated by a semicolon.
 
     /// matches inner_attrs*
-    fn parse_inner_attributes(&mut self) -> Vec<ast::Attribute> {
+    pub fn parse_inner_attributes(&mut self) -> PResult<Vec<ast::Attribute>> {
         let mut attrs: Vec<ast::Attribute> = vec![];
         loop {
             match self.token {
@@ -130,7 +121,7 @@ impl<'a> ParserAttr for Parser<'a> {
                         break;
                     }
 
-                    let attr = self.parse_attribute(true);
+                    let attr = try!(self.parse_attribute(true));
                     assert!(attr.node.style == ast::AttrStyle::Inner);
                     attrs.push(attr);
                 }
@@ -141,7 +132,7 @@ impl<'a> ParserAttr for Parser<'a> {
                     let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), str, lo, hi);
                     if attr.node.style == ast::AttrStyle::Inner {
                         attrs.push(attr);
-                        panictry!(self.bump());
+                        try!(self.bump());
                     } else {
                         break;
                     }
@@ -149,13 +140,13 @@ impl<'a> ParserAttr for Parser<'a> {
                 _ => break
             }
         }
-        attrs
+        Ok(attrs)
     }
 
     /// matches meta_item = IDENT
     /// | IDENT = lit
     /// | IDENT meta_seq
-    fn parse_meta_item(&mut self) -> P<ast::MetaItem> {
+    pub fn parse_meta_item(&mut self) -> PResult<P<ast::MetaItem>> {
         let nt_meta = match self.token {
             token::Interpolated(token::NtMeta(ref e)) => {
                 Some(e.clone())
@@ -165,19 +156,19 @@ impl<'a> ParserAttr for Parser<'a> {
 
         match nt_meta {
             Some(meta) => {
-                panictry!(self.bump());
-                return meta;
+                try!(self.bump());
+                return Ok(meta);
             }
             None => {}
         }
 
         let lo = self.span.lo;
-        let ident = panictry!(self.parse_ident());
+        let ident = try!(self.parse_ident());
         let name = self.id_to_interned_str(ident);
         match self.token {
             token::Eq => {
-                panictry!(self.bump());
-                let lit = panictry!(self.parse_lit());
+                try!(self.bump());
+                let lit = try!(self.parse_lit());
                 // FIXME #623 Non-string meta items are not serialized correctly;
                 // just forbid them for now
                 match lit.node {
@@ -189,32 +180,25 @@ impl<'a> ParserAttr for Parser<'a> {
                     }
                 }
                 let hi = self.span.hi;
-                P(spanned(lo, hi, ast::MetaNameValue(name, lit)))
+                Ok(P(spanned(lo, hi, ast::MetaNameValue(name, lit))))
             }
             token::OpenDelim(token::Paren) => {
-                let inner_items = self.parse_meta_seq();
+                let inner_items = try!(self.parse_meta_seq());
                 let hi = self.span.hi;
-                P(spanned(lo, hi, ast::MetaList(name, inner_items)))
+                Ok(P(spanned(lo, hi, ast::MetaList(name, inner_items))))
             }
             _ => {
                 let hi = self.last_span.hi;
-                P(spanned(lo, hi, ast::MetaWord(name)))
+                Ok(P(spanned(lo, hi, ast::MetaWord(name))))
             }
         }
     }
 
     /// matches meta_seq = ( COMMASEP(meta_item) )
-    fn parse_meta_seq(&mut self) -> Vec<P<ast::MetaItem>> {
-        panictry!(self.parse_seq(&token::OpenDelim(token::Paren),
-                       &token::CloseDelim(token::Paren),
-                       seq_sep_trailing_allowed(token::Comma),
-                       |p| Ok(p.parse_meta_item()))).node
-    }
-
-    fn parse_optional_meta(&mut self) -> Vec<P<ast::MetaItem>> {
-        match self.token {
-            token::OpenDelim(token::Paren) => self.parse_meta_seq(),
-            _ => Vec::new()
-        }
+    fn parse_meta_seq(&mut self) -> PResult<Vec<P<ast::MetaItem>>> {
+        self.parse_unspanned_seq(&token::OpenDelim(token::Paren),
+                                 &token::CloseDelim(token::Paren),
+                                 seq_sep_trailing_allowed(token::Comma),
+                                 |p| p.parse_meta_item())
     }
 }
diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs
index 137996a35ee..e5e2c3a986d 100644
--- a/src/libsyntax/parse/lexer/comments.rs
+++ b/src/libsyntax/parse/lexer/comments.rs
@@ -270,7 +270,7 @@ fn read_block_comment(rdr: &mut StringReader,
         while level > 0 {
             debug!("=== block comment level {}", level);
             if rdr.is_eof() {
-                rdr.fatal("unterminated block comment");
+                panic!(rdr.fatal("unterminated block comment"));
             }
             if rdr.curr_is('\n') {
                 trim_whitespace_prefix_and_push_line(&mut lines,
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 490822b934e..9e38ffe7f0d 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -11,6 +11,7 @@
 use ast;
 use codemap::{BytePos, CharPos, CodeMap, Pos, Span};
 use codemap;
+use diagnostic::FatalError;
 use diagnostic::SpanHandler;
 use ext::tt::transcribe::tt_next_token;
 use parse::token::str_to_ident;
@@ -30,7 +31,7 @@ pub trait Reader {
     fn is_eof(&self) -> bool;
     fn next_token(&mut self) -> TokenAndSpan;
     /// Report a fatal error with the current span.
-    fn fatal(&self, &str) -> !;
+    fn fatal(&self, &str) -> FatalError;
     /// Report a non-fatal error with the current span.
     fn err(&self, &str);
     fn peek(&self) -> TokenAndSpan;
@@ -86,7 +87,7 @@ impl<'a> Reader for StringReader<'a> {
         self.advance_token();
         ret_val
     }
-    fn fatal(&self, m: &str) -> ! {
+    fn fatal(&self, m: &str) -> FatalError {
         self.fatal_span(self.peek_span, m)
     }
     fn err(&self, m: &str) {
@@ -110,8 +111,8 @@ impl<'a> Reader for TtReader<'a> {
         debug!("TtReader: r={:?}", r);
         r
     }
-    fn fatal(&self, m: &str) -> ! {
-        panic!(self.sp_diag.span_fatal(self.cur_span, m));
+    fn fatal(&self, m: &str) -> FatalError {
+        self.sp_diag.span_fatal(self.cur_span, m)
     }
     fn err(&self, m: &str) {
         self.sp_diag.span_err(self.cur_span, m);
@@ -163,8 +164,8 @@ impl<'a> StringReader<'a> {
     }
 
     /// Report a fatal lexical error with a given span.
-    pub fn fatal_span(&self, sp: Span, m: &str) -> ! {
-        panic!(self.span_diagnostic.span_fatal(sp, m))
+    pub fn fatal_span(&self, sp: Span, m: &str) -> FatalError {
+        self.span_diagnostic.span_fatal(sp, m)
     }
 
     /// Report a lexical error with a given span.
@@ -178,7 +179,7 @@ impl<'a> StringReader<'a> {
     }
 
     /// Report a fatal error spanning [`from_pos`, `to_pos`).
-    fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> ! {
+    fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> FatalError {
         self.fatal_span(codemap::mk_sp(from_pos, to_pos), m)
     }
 
@@ -194,11 +195,11 @@ impl<'a> StringReader<'a> {
 
     /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
     /// escaped character to the error message
-    fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> ! {
+    fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> FatalError {
         let mut m = m.to_string();
         m.push_str(": ");
         for c in c.escape_default() { m.push(c) }
-        self.fatal_span_(from_pos, to_pos, &m[..]);
+        self.fatal_span_(from_pos, to_pos, &m[..])
     }
 
     /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
@@ -212,12 +213,12 @@ impl<'a> StringReader<'a> {
 
     /// Report a lexical error spanning [`from_pos`, `to_pos`), appending the
     /// offending string to the error message
-    fn fatal_span_verbose(&self, from_pos: BytePos, to_pos: BytePos, mut m: String) -> ! {
+    fn fatal_span_verbose(&self, from_pos: BytePos, to_pos: BytePos, mut m: String) -> FatalError {
         m.push_str(": ");
         let from = self.byte_offset(from_pos).to_usize();
         let to = self.byte_offset(to_pos).to_usize();
         m.push_str(&self.source_text[from..to]);
-        self.fatal_span_(from_pos, to_pos, &m[..]);
+        self.fatal_span_(from_pos, to_pos, &m[..])
     }
 
     /// Advance peek_tok and peek_span to refer to the next token, and
@@ -538,7 +539,7 @@ impl<'a> StringReader<'a> {
                     "unterminated block comment"
                 };
                 let last_bpos = self.last_pos;
-                self.fatal_span_(start_bpos, last_bpos, msg);
+                panic!(self.fatal_span_(start_bpos, last_bpos, msg));
             }
             let n = self.curr.unwrap();
             match n {
@@ -682,7 +683,9 @@ impl<'a> StringReader<'a> {
         for _ in 0..n_digits {
             if self.is_eof() {
                 let last_bpos = self.last_pos;
-                self.fatal_span_(start_bpos, last_bpos, "unterminated numeric character escape");
+                panic!(self.fatal_span_(start_bpos,
+                                        last_bpos,
+                                        "unterminated numeric character escape"));
             }
             if self.curr_is(delim) {
                 let last_bpos = self.last_pos;
@@ -835,15 +838,15 @@ impl<'a> StringReader<'a> {
             let c = match self.curr {
                 Some(c) => c,
                 None => {
-                    self.fatal_span_(start_bpos, self.last_pos,
-                                     "unterminated unicode escape (found EOF)");
+                    panic!(self.fatal_span_(start_bpos, self.last_pos,
+                                            "unterminated unicode escape (found EOF)"));
                 }
             };
             accum_int *= 16;
             accum_int += c.to_digit(16).unwrap_or_else(|| {
                 if c == delim {
-                    self.fatal_span_(self.last_pos, self.pos,
-                                     "unterminated unicode escape (needed a `}`)");
+                    panic!(self.fatal_span_(self.last_pos, self.pos,
+                                            "unterminated unicode escape (needed a `}`)"));
                 } else {
                     self.err_span_char(self.last_pos, self.pos,
                                    "invalid character in unicode escape", c);
@@ -1077,12 +1080,12 @@ impl<'a> StringReader<'a> {
             let valid = self.scan_char_or_byte(start, c2, /* ascii_only = */ false, '\'');
             if !self.curr_is('\'') {
                 let last_bpos = self.last_pos;
-                self.fatal_span_verbose(
+                panic!(self.fatal_span_verbose(
                                    // Byte offsetting here is okay because the
                                    // character before position `start` is an
                                    // ascii single quote.
                                    start - BytePos(1), last_bpos,
-                                   "unterminated character constant".to_string());
+                                   "unterminated character constant".to_string()));
             }
             let id = if valid { self.name_from(start) } else { token::intern("0") };
             self.bump(); // advance curr past token
@@ -1107,7 +1110,9 @@ impl<'a> StringReader<'a> {
             while !self.curr_is('"') {
                 if self.is_eof() {
                     let last_bpos = self.last_pos;
-                    self.fatal_span_(start_bpos, last_bpos, "unterminated double quote string");
+                    panic!(self.fatal_span_(start_bpos,
+                                            last_bpos,
+                                            "unterminated double quote string"));
                 }
 
                 let ch_start = self.last_pos;
@@ -1133,14 +1138,14 @@ impl<'a> StringReader<'a> {
 
             if self.is_eof() {
                 let last_bpos = self.last_pos;
-                self.fatal_span_(start_bpos, last_bpos, "unterminated raw string");
+                panic!(self.fatal_span_(start_bpos, last_bpos, "unterminated raw string"));
             } else if !self.curr_is('"') {
                 let last_bpos = self.last_pos;
                 let curr_char = self.curr.unwrap();
-                self.fatal_span_char(start_bpos, last_bpos,
+                panic!(self.fatal_span_char(start_bpos, last_bpos,
                                 "found invalid character; \
                                  only `#` is allowed in raw string delimitation",
-                                curr_char);
+                                curr_char));
             }
             self.bump();
             let content_start_bpos = self.last_pos;
@@ -1149,7 +1154,7 @@ impl<'a> StringReader<'a> {
             'outer: loop {
                 if self.is_eof() {
                     let last_bpos = self.last_pos;
-                    self.fatal_span_(start_bpos, last_bpos, "unterminated raw string");
+                    panic!(self.fatal_span_(start_bpos, last_bpos, "unterminated raw string"));
                 }
                 //if self.curr_is('"') {
                     //content_end_bpos = self.last_pos;
@@ -1218,7 +1223,7 @@ impl<'a> StringReader<'a> {
           c => {
               let last_bpos = self.last_pos;
               let bpos = self.pos;
-              self.fatal_span_char(last_bpos, bpos, "unknown start of token", c);
+              panic!(self.fatal_span_char(last_bpos, bpos, "unknown start of token", c));
           }
         }
     }
@@ -1271,9 +1276,9 @@ impl<'a> StringReader<'a> {
             // character before position `start` are an
             // ascii single quote and ascii 'b'.
             let last_pos = self.last_pos;
-            self.fatal_span_verbose(
+            panic!(self.fatal_span_verbose(
                 start - BytePos(2), last_pos,
-                "unterminated byte constant".to_string());
+                "unterminated byte constant".to_string()));
         }
 
         let id = if valid { self.name_from(start) } else { token::intern("?") };
@@ -1293,8 +1298,7 @@ impl<'a> StringReader<'a> {
         while !self.curr_is('"') {
             if self.is_eof() {
                 let last_pos = self.last_pos;
-                self.fatal_span_(start, last_pos,
-                                  "unterminated double quote byte string");
+                panic!(self.fatal_span_(start, last_pos, "unterminated double quote byte string"));
             }
 
             let ch_start = self.last_pos;
@@ -1318,14 +1322,14 @@ impl<'a> StringReader<'a> {
 
         if self.is_eof() {
             let last_pos = self.last_pos;
-            self.fatal_span_(start_bpos, last_pos, "unterminated raw string");
+            panic!(self.fatal_span_(start_bpos, last_pos, "unterminated raw string"));
         } else if !self.curr_is('"') {
             let last_pos = self.last_pos;
             let ch = self.curr.unwrap();
-            self.fatal_span_char(start_bpos, last_pos,
+            panic!(self.fatal_span_char(start_bpos, last_pos,
                             "found invalid character; \
                              only `#` is allowed in raw string delimitation",
-                            ch);
+                            ch));
         }
         self.bump();
         let content_start_bpos = self.last_pos;
@@ -1334,7 +1338,7 @@ impl<'a> StringReader<'a> {
             match self.curr {
                 None => {
                     let last_pos = self.last_pos;
-                    self.fatal_span_(start_bpos, last_pos, "unterminated raw string")
+                    panic!(self.fatal_span_(start_bpos, last_pos, "unterminated raw string"))
                 },
                 Some('"') => {
                     content_end_bpos = self.last_pos;
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 5beec702f8c..a468f0d1d98 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -13,7 +13,6 @@
 use ast;
 use codemap::{self, Span, CodeMap, FileMap};
 use diagnostic::{SpanHandler, Handler, Auto, FatalError};
-use parse::attr::ParserAttr;
 use parse::parser::Parser;
 use parse::token::InternedString;
 use ptr::P;
@@ -83,7 +82,8 @@ pub fn parse_crate_attrs_from_file(
     cfg: ast::CrateConfig,
     sess: &ParseSess
 ) -> Vec<ast::Attribute> {
-    new_parser_from_file(sess, cfg, input).parse_inner_attributes()
+    // FIXME: maybe_aborted?
+    panictry!(new_parser_from_file(sess, cfg, input).parse_inner_attributes())
 }
 
 pub fn parse_crate_from_source_str(name: String,
@@ -107,7 +107,7 @@ pub fn parse_crate_attrs_from_source_str(name: String,
                                            cfg,
                                            name,
                                            source);
-    maybe_aborted(p.parse_inner_attributes(), p)
+    maybe_aborted(panictry!(p.parse_inner_attributes()), p)
 }
 
 pub fn parse_expr_from_source_str(name: String,
@@ -116,7 +116,7 @@ pub fn parse_expr_from_source_str(name: String,
                                   sess: &ParseSess)
                                   -> P<ast::Expr> {
     let mut p = new_parser_from_source_str(sess, cfg, name, source);
-    maybe_aborted(p.parse_expr(), p)
+    maybe_aborted(panictry!(p.parse_expr_nopanic()), p)
 }
 
 pub fn parse_item_from_source_str(name: String,
@@ -125,7 +125,7 @@ pub fn parse_item_from_source_str(name: String,
                                   sess: &ParseSess)
                                   -> Option<P<ast::Item>> {
     let mut p = new_parser_from_source_str(sess, cfg, name, source);
-    maybe_aborted(p.parse_item(),p)
+    maybe_aborted(panictry!(p.parse_item_nopanic()), p)
 }
 
 pub fn parse_meta_from_source_str(name: String,
@@ -134,7 +134,7 @@ pub fn parse_meta_from_source_str(name: String,
                                   sess: &ParseSess)
                                   -> P<ast::MetaItem> {
     let mut p = new_parser_from_source_str(sess, cfg, name, source);
-    maybe_aborted(p.parse_meta_item(),p)
+    maybe_aborted(panictry!(p.parse_meta_item()), p)
 }
 
 pub fn parse_stmt_from_source_str(name: String,
@@ -148,7 +148,7 @@ pub fn parse_stmt_from_source_str(name: String,
         name,
         source
     );
-    maybe_aborted(p.parse_stmt(), p)
+    maybe_aborted(panictry!(p.parse_stmt_nopanic()), p)
 }
 
 // Warning: This parses with quote_depth > 0, which is not the default.
@@ -235,7 +235,7 @@ fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
             let msg = format!("couldn't read {:?}: {}", path.display(), e);
             match spanopt {
                 Some(sp) => panic!(sess.span_diagnostic.span_fatal(sp, &msg)),
-                None => sess.span_diagnostic.handler().fatal(&msg)
+                None => panic!(sess.span_diagnostic.handler().fatal(&msg))
             }
         }
     }
@@ -856,7 +856,7 @@ mod tests {
 
     #[test] fn parse_stmt_1 () {
         assert!(string_to_stmt("b;".to_string()) ==
-                   P(Spanned{
+                   Some(P(Spanned{
                        node: ast::StmtExpr(P(ast::Expr {
                            id: ast::DUMMY_NODE_ID,
                            node: ast::ExprPath(None, ast::Path {
@@ -871,7 +871,7 @@ mod tests {
                             }),
                            span: sp(0,1)}),
                                            ast::DUMMY_NODE_ID),
-                       span: sp(0,1)}))
+                       span: sp(0,1)})))
 
     }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index ba86f85c381..2401f6be78f 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -63,7 +63,6 @@ use codemap::{self, Span, BytePos, Spanned, spanned, mk_sp, CodeMap};
 use diagnostic;
 use ext::tt::macro_parser;
 use parse;
-use parse::attr::ParserAttr;
 use parse::classify;
 use parse::common::{SeqSep, seq_sep_none, seq_sep_trailing_allowed};
 use parse::lexer::{Reader, TokenAndSpan};
@@ -358,31 +357,36 @@ impl<'a> Parser<'a> {
     }
 
     // Panicing fns (for now!)
-    // This is so that the quote_*!() syntax extensions
-    pub fn parse_expr(&mut self) -> P<Expr> {
+    // These functions are used by the quote_*!() syntax extensions, but shouldn't
+    // be used otherwise.
+    pub fn parse_expr_panic(&mut self) -> P<Expr> {
         panictry!(self.parse_expr_nopanic())
     }
 
-    pub fn parse_item(&mut self) -> Option<P<Item>> {
+    pub fn parse_item_panic(&mut self) -> Option<P<Item>> {
         panictry!(self.parse_item_nopanic())
     }
 
-    pub fn parse_pat(&mut self) -> P<Pat> {
+    pub fn parse_pat_panic(&mut self) -> P<Pat> {
         panictry!(self.parse_pat_nopanic())
     }
 
-    pub fn parse_arm(&mut self) -> Arm {
+    pub fn parse_arm_panic(&mut self) -> Arm {
         panictry!(self.parse_arm_nopanic())
     }
 
-    pub fn parse_ty(&mut self) -> P<Ty> {
+    pub fn parse_ty_panic(&mut self) -> P<Ty> {
         panictry!(self.parse_ty_nopanic())
     }
 
-    pub fn parse_stmt(&mut self) -> Option<P<Stmt>> {
+    pub fn parse_stmt_panic(&mut self) -> Option<P<Stmt>> {
         panictry!(self.parse_stmt_nopanic())
     }
 
+    pub fn parse_attribute_panic(&mut self, permit_inner: bool) -> ast::Attribute {
+        panictry!(self.parse_attribute(permit_inner))
+    }
+
     /// Convert a token to a string using self's reader
     pub fn token_to_string(token: &token::Token) -> String {
         pprust::token_to_string(token)
@@ -1173,7 +1177,7 @@ impl<'a> Parser<'a> {
             seq_sep_none(),
             |p| -> PResult<P<TraitItem>> {
             maybe_whole!(no_clone p, NtTraitItem);
-            let mut attrs = p.parse_outer_attributes();
+            let mut attrs = try!(p.parse_outer_attributes());
             let lo = p.span.lo;
 
             let (name, node) = if try!(p.eat_keyword(keywords::Type)) {
@@ -2961,7 +2965,7 @@ impl<'a> Parser<'a> {
     pub fn parse_arm_nopanic(&mut self) -> PResult<Arm> {
         maybe_whole!(no_clone self, NtArm);
 
-        let attrs = self.parse_outer_attributes();
+        let attrs = try!(self.parse_outer_attributes());
         let pats = try!(self.parse_pats());
         let mut guard = None;
         if try!(self.eat_keyword(keywords::If) ){
@@ -3470,7 +3474,7 @@ impl<'a> Parser<'a> {
             }
         }
 
-        let attrs = self.parse_outer_attributes();
+        let attrs = try!(self.parse_outer_attributes());
         let lo = self.span.lo;
 
         Ok(Some(if self.check_keyword(keywords::Let) {
@@ -3612,7 +3616,7 @@ impl<'a> Parser<'a> {
 
         let lo = self.span.lo;
         try!(self.expect(&token::OpenDelim(token::Brace)));
-        Ok((self.parse_inner_attributes(),
+        Ok((try!(self.parse_inner_attributes()),
          try!(self.parse_block_tail(lo, DefaultBlock))))
     }
 
@@ -4436,7 +4440,7 @@ impl<'a> Parser<'a> {
     pub fn parse_impl_item(&mut self) -> PResult<P<ImplItem>> {
         maybe_whole!(no_clone self, NtImplItem);
 
-        let mut attrs = self.parse_outer_attributes();
+        let mut attrs = try!(self.parse_outer_attributes());
         let lo = self.span.lo;
         let vis = try!(self.parse_visibility());
         let (name, node) = if try!(self.eat_keyword(keywords::Type)) {
@@ -4613,7 +4617,7 @@ impl<'a> Parser<'a> {
             generics.where_clause = try!(self.parse_where_clause());
 
             try!(self.expect(&token::OpenDelim(token::Brace)));
-            let attrs = self.parse_inner_attributes();
+            let attrs = try!(self.parse_inner_attributes());
 
             let mut impl_items = vec![];
             while !try!(self.eat(&token::CloseDelim(token::Brace))) {
@@ -4732,7 +4736,7 @@ impl<'a> Parser<'a> {
             &token::CloseDelim(token::Paren),
             seq_sep_trailing_allowed(token::Comma),
             |p| {
-                let attrs = p.parse_outer_attributes();
+                let attrs = try!(p.parse_outer_attributes());
                 let lo = p.span.lo;
                 let struct_field_ = ast::StructField_ {
                     kind: UnnamedField(try!(p.parse_visibility())),
@@ -4774,7 +4778,7 @@ impl<'a> Parser<'a> {
     /// Parse an element of a struct definition
     fn parse_struct_decl_field(&mut self, allow_pub: bool) -> PResult<StructField> {
 
-        let attrs = self.parse_outer_attributes();
+        let attrs = try!(self.parse_outer_attributes());
 
         if try!(self.eat_keyword(keywords::Pub) ){
             if !allow_pub {
@@ -4846,7 +4850,7 @@ impl<'a> Parser<'a> {
             let mod_inner_lo = self.span.lo;
             let old_owns_directory = self.owns_directory;
             self.owns_directory = true;
-            let attrs = self.parse_inner_attributes();
+            let attrs = try!(self.parse_inner_attributes());
             let m = try!(self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo));
             self.owns_directory = old_owns_directory;
             self.pop_mod_path();
@@ -4995,7 +4999,7 @@ impl<'a> Parser<'a> {
                                               Some(name),
                                               id_sp);
         let mod_inner_lo = p0.span.lo;
-        let mod_attrs = p0.parse_inner_attributes();
+        let mod_attrs = try!(p0.parse_inner_attributes());
         let m0 = try!(p0.parse_mod_items(&token::Eof, mod_inner_lo));
         self.sess.included_mod_stack.borrow_mut().pop();
         Ok((ast::ItemMod(m0), mod_attrs))
@@ -5098,7 +5102,7 @@ impl<'a> Parser<'a> {
 
         let abi = opt_abi.unwrap_or(abi::C);
 
-        attrs.extend(self.parse_inner_attributes());
+        attrs.extend(try!(self.parse_inner_attributes()));
 
         let mut foreign_items = vec![];
         while let Some(item) = try!(self.parse_foreign_item()) {
@@ -5148,7 +5152,7 @@ impl<'a> Parser<'a> {
         let mut all_nullary = true;
         let mut any_disr = None;
         while self.token != token::CloseDelim(token::Brace) {
-            let variant_attrs = self.parse_outer_attributes();
+            let variant_attrs = try!(self.parse_outer_attributes());
             let vlo = self.span.lo;
 
             let struct_def;
@@ -5510,7 +5514,7 @@ impl<'a> Parser<'a> {
 
     /// Parse a foreign item.
     fn parse_foreign_item(&mut self) -> PResult<Option<P<ForeignItem>>> {
-        let attrs = self.parse_outer_attributes();
+        let attrs = try!(self.parse_outer_attributes());
         let lo = self.span.lo;
         let visibility = try!(self.parse_visibility());
 
@@ -5610,7 +5614,7 @@ impl<'a> Parser<'a> {
     }
 
     pub fn parse_item_nopanic(&mut self) -> PResult<Option<P<Item>>> {
-        let attrs = self.parse_outer_attributes();
+        let attrs = try!(self.parse_outer_attributes());
         self.parse_item_(attrs, true)
     }
 
@@ -5729,7 +5733,7 @@ impl<'a> Parser<'a> {
     pub fn parse_crate_mod(&mut self) -> PResult<Crate> {
         let lo = self.span.lo;
         Ok(ast::Crate {
-            attrs: self.parse_inner_attributes(),
+            attrs: try!(self.parse_inner_attributes()),
             module: try!(self.parse_mod_items(&token::Eof, lo)),
             config: self.cfg.clone(),
             span: mk_sp(lo, self.span.lo),