about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/attr.rs131
-rw-r--r--src/libsyntax/parse/lexer.rs6
-rw-r--r--src/libsyntax/parse/parser.rs14
-rw-r--r--src/libsyntax/parse/token.rs3
4 files changed, 95 insertions, 59 deletions
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index 8cce5f15e67..f2489d80e1e 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -9,21 +9,17 @@
 // except according to those terms.
 
 use ast;
-use codemap::spanned;
+use codemap::{spanned, mk_sp};
 use codemap::BytePos;
 use parse::common::*; //resolve bug?
 use parse::token;
 use parse::parser::Parser;
+use parse::token::INTERPOLATED;
 
 // a parser that can parse attributes.
 pub trait parser_attr {
     fn parse_outer_attributes(&self) -> ~[ast::Attribute];
-    fn parse_attribute(&self, style: ast::AttrStyle) -> ast::Attribute;
-    fn parse_attribute_naked(
-        &self,
-        style: ast::AttrStyle,
-        lo: BytePos
-    ) -> ast::Attribute;
+    fn parse_attribute(&self, permit_inner: bool) -> ast::Attribute;
     fn parse_inner_attrs_and_next(&self) ->
         (~[ast::Attribute], ~[ast::Attribute]);
     fn parse_meta_item(&self) -> @ast::MetaItem;
@@ -37,12 +33,17 @@ impl parser_attr for Parser {
     fn parse_outer_attributes(&self) -> ~[ast::Attribute] {
         let mut attrs: ~[ast::Attribute] = ~[];
         loop {
+            debug!("parse_outer_attributes: self.token=%?",
+                   self.token);
             match *self.token {
+              token::INTERPOLATED(token::nt_attr(*)) => {
+                attrs.push(self.parse_attribute(false));
+              }
               token::POUND => {
                 if self.look_ahead(1, |t| *t != token::LBRACKET) {
                     break;
                 }
-                attrs.push(self.parse_attribute(ast::AttrOuter));
+                attrs.push(self.parse_attribute(false));
               }
               token::DOC_COMMENT(s) => {
                 let attr = ::attr::mk_sugared_doc_attr(
@@ -62,23 +63,49 @@ impl parser_attr for Parser {
         return attrs;
     }
 
-    // matches attribute = # attribute_naked
-    fn parse_attribute(&self, style: ast::AttrStyle) -> ast::Attribute {
-        let lo = self.span.lo;
-        self.expect(&token::POUND);
-        return self.parse_attribute_naked(style, lo);
+    // matches attribute = # [ meta_item ]
+    //
+    // if permit_inner is true, then a trailing `;` indicates an inner
+    // attribute
+    fn parse_attribute(&self, permit_inner: bool) -> ast::Attribute {
+        debug!("parse_attributes: permit_inner=%? self.token=%?",
+               permit_inner, self.token);
+        let (span, value) = match *self.token {
+            INTERPOLATED(token::nt_attr(attr)) => {
+                assert!(attr.node.style == ast::AttrOuter);
+                self.bump();
+                (attr.span, attr.node.value)
+            }
+            token::POUND => {
+                let lo = self.span.lo;
+                self.bump();
+                self.expect(&token::LBRACKET);
+                let meta_item = self.parse_meta_item();
+                self.expect(&token::RBRACKET);
+                let hi = self.span.hi;
+                (mk_sp(lo, hi), meta_item)
+            }
+            _ => {
+                self.fatal(fmt!("expected `#` but found `%s`",
+                                self.this_token_to_str()));
+            }
+        };
+        let style = if permit_inner && *self.token == token::SEMI {
+            self.bump();
+            ast::AttrInner
+        } else {
+            ast::AttrOuter
+        };
+        return spanned {
+            span: span,
+            node: ast::Attribute_ {
+                style: style,
+                value: value,
+                is_sugared_doc: false
+            }
+        };
     }
 
-    // matches attribute_naked = [ meta_item ]
-    fn parse_attribute_naked(&self, style: ast::AttrStyle, lo: BytePos) ->
-        ast::Attribute {
-        self.expect(&token::LBRACKET);
-        let meta_item = self.parse_meta_item();
-        self.expect(&token::RBRACKET);
-        let hi = self.span.hi;
-        return spanned(lo, hi, ast::Attribute_ { style: style,
-                                                 value: meta_item, is_sugared_doc: false }); }
-
     // Parse attributes that appear after the opening of an item, each
     // terminated by a semicolon. In addition to a vector of inner attributes,
     // this function also returns a vector that may contain the first outer
@@ -89,47 +116,37 @@ impl parser_attr for Parser {
     // matches inner_attrs* outer_attr?
     // you can make the 'next' field an Option, but the result is going to be
     // more useful as a vector.
-    fn parse_inner_attrs_and_next(&self) ->
-        (~[ast::Attribute], ~[ast::Attribute]) {
+    fn parse_inner_attrs_and_next(&self)
+                                  -> (~[ast::Attribute], ~[ast::Attribute]) {
         let mut inner_attrs: ~[ast::Attribute] = ~[];
         let mut next_outer_attrs: ~[ast::Attribute] = ~[];
         loop {
-            match *self.token {
-              token::POUND => {
-                if self.look_ahead(1, |t| *t != token::LBRACKET) {
-                    // This is an extension
-                    break;
+            let attr = match *self.token {
+                token::INTERPOLATED(token::nt_attr(*)) => {
+                    self.parse_attribute(true)
+                }
+                token::POUND => {
+                    if self.look_ahead(1, |t| *t != token::LBRACKET) {
+                        // This is an extension
+                        break;
+                    }
+                    self.parse_attribute(true)
                 }
-                let attr = self.parse_attribute(ast::AttrInner);
-                if *self.token == token::SEMI {
+                token::DOC_COMMENT(s) => {
                     self.bump();
-                    inner_attrs.push(attr);
-                } else {
-                    // It's not really an inner attribute
-                    let outer_attr =
-                        spanned(attr.span.lo, attr.span.hi,
-                            ast::Attribute_ { style: ast::AttrOuter,
-                                              value: attr.node.value,
-                                              is_sugared_doc: false });
-                    next_outer_attrs.push(outer_attr);
-                    break;
+                    ::attr::mk_sugared_doc_attr(self.id_to_str(s),
+                                                self.span.lo,
+                                                self.span.hi)
                 }
-              }
-              token::DOC_COMMENT(s) => {
-                let attr = ::attr::mk_sugared_doc_attr(
-                    self.id_to_str(s),
-                    self.span.lo,
-                    self.span.hi
-                );
-                self.bump();
-                if attr.node.style == ast::AttrInner {
-                  inner_attrs.push(attr);
-                } else {
-                  next_outer_attrs.push(attr);
-                  break;
+                _ => {
+                    break;
                 }
-              }
-              _ => break
+            };
+            if attr.node.style == ast::AttrInner {
+                inner_attrs.push(attr);
+            } else {
+                next_outer_attrs.push(attr);
+                break;
             }
         }
         (inner_attrs, next_outer_attrs)
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index 49deafeda40..bde568b2610 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -129,7 +129,11 @@ impl reader for StringReader {
 
 impl reader for TtReader {
     fn is_eof(@mut self) -> bool { self.cur_tok == token::EOF }
-    fn next_token(@mut self) -> TokenAndSpan { tt_next_token(self) }
+    fn next_token(@mut self) -> TokenAndSpan {
+        let r = tt_next_token(self);
+        debug!("TtReader: r=%?", r);
+        return r;
+    }
     fn fatal(@mut self, m: ~str) -> ! {
         self.sp_diag.span_fatal(self.cur_span, m);
     }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index d1916088a41..77c50a779c0 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[macro_escape];
+
 use abi;
 use abi::AbiSet;
 use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil};
@@ -4460,7 +4462,17 @@ impl Parser {
                                attrs: ~[Attribute],
                                macros_allowed: bool)
                                -> item_or_view_item {
-        maybe_whole!(iovi self, nt_item);
+        match *self.token {
+            INTERPOLATED(token::nt_item(item)) => {
+                self.bump();
+                let new_attrs = vec::append(attrs, item.attrs);
+                return iovi_item(@ast::item {
+                        attrs: new_attrs,
+                        ..(*item).clone()});
+            }
+            _ => {}
+        }
+
         let lo = self.span.lo;
 
         let visibility = self.parse_non_priv_visibility();
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index fd491c1e890..c554f111bf9 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -105,6 +105,7 @@ pub enum nonterminal {
     nt_expr(@ast::expr),
     nt_ty(   ast::Ty),
     nt_ident(ast::ident, bool),
+    nt_attr(@ast::Attribute),   // #[foo]
     nt_path( ast::Path),
     nt_tt(  @ast::token_tree), //needs @ed to break a circularity
     nt_matchers(~[ast::matcher])
@@ -205,6 +206,7 @@ pub fn to_str(input: @ident_interner, t: &Token) -> ~str {
       INTERPOLATED(ref nt) => {
         match nt {
             &nt_expr(e) => ::print::pprust::expr_to_str(e, input),
+            &nt_attr(e) => ::print::pprust::attribute_to_str(e, input),
             _ => {
                 ~"an interpolated " +
                     match (*nt) {
@@ -212,6 +214,7 @@ pub fn to_str(input: @ident_interner, t: &Token) -> ~str {
                       nt_block(*) => ~"block",
                       nt_stmt(*) => ~"statement",
                       nt_pat(*) => ~"pattern",
+                      nt_attr(*) => fail!("should have been handled"),
                       nt_expr(*) => fail!("should have been handled above"),
                       nt_ty(*) => ~"type",
                       nt_ident(*) => ~"identifier",