about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorDaniel Fagnan <dnfagnan@gmail.com>2014-02-24 19:42:40 -0700
committerAlex Crichton <alex@alexcrichton.com>2014-03-20 18:06:53 -0700
commit4e00cf613428d24d305a89e4f8e79b70ea8e8322 (patch)
tree183c414832596437bfc0e6a04b81f8542cbd53c0 /src/libsyntax/parse
parent6eae7df43cd21b76fe91eeaf6ef2af9bd2a8fafc (diff)
downloadrust-4e00cf613428d24d305a89e4f8e79b70ea8e8322.tar.gz
rust-4e00cf613428d24d305a89e4f8e79b70ea8e8322.zip
Added new attribute syntax with backward compatibility.
Signed-off-by: Daniel Fagnan <dnfagnan@gmail.com>
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/attr.rs36
-rw-r--r--src/libsyntax/parse/comments.rs8
-rw-r--r--src/libsyntax/parse/lexer.rs18
3 files changed, 51 insertions, 11 deletions
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index c30ab4bda27..92b93fd88dd 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -38,9 +38,6 @@ impl<'a> ParserAttr for Parser<'a> {
                 attrs.push(self.parse_attribute(false));
               }
               token::POUND => {
-                if self.look_ahead(1, |t| *t != token::LBRACKET) {
-                    break;
-                }
                 attrs.push(self.parse_attribute(false));
               }
               token::DOC_COMMENT(s) => {
@@ -68,6 +65,7 @@ impl<'a> ParserAttr for Parser<'a> {
     fn parse_attribute(&mut self, permit_inner: bool) -> ast::Attribute {
         debug!("parse_attributes: permit_inner={:?} self.token={:?}",
                permit_inner, self.token);
+        let mut warned = false;
         let (span, value) = match self.token {
             INTERPOLATED(token::NtAttr(attr)) => {
                 assert!(attr.node.style == ast::AttrOuter);
@@ -77,9 +75,22 @@ impl<'a> ParserAttr for Parser<'a> {
             token::POUND => {
                 let lo = self.span.lo;
                 self.bump();
+
+                if self.eat(&token::NOT) {
+                    if !permit_inner {
+                        self.fatal("an inner attribute was not permitted in this context.");
+                    }
+                } else {
+                    warned = true;
+                    // NOTE: uncomment this after a stage0 snap
+                    //self.warn("The syntax for inner attributes have changed.
+                    //    Use `#![lang(foo)]` instead.");
+                }
+
                 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)
             }
@@ -89,12 +100,23 @@ impl<'a> ParserAttr for Parser<'a> {
                                    token_str));
             }
         };
-        let style = if permit_inner && self.token == token::SEMI {
-            self.bump();
+
+        let style = if permit_inner {
+
+            if self.eat(&token::SEMI) {
+                // Only warn the user once if the syntax is the old one.
+                if !warned {
+                    // NOTE: uncomment this after a stage0 snap
+                    //self.warn("This uses the old attribute syntax. Semicolons
+                    //  are not longer required.");
+                }
+            }
+
             ast::AttrInner
         } else {
             ast::AttrOuter
         };
+
         return Spanned {
             span: span,
             node: ast::Attribute_ {
@@ -125,10 +147,6 @@ impl<'a> ParserAttr for Parser<'a> {
                     self.parse_attribute(true)
                 }
                 token::POUND => {
-                    if self.look_ahead(1, |t| *t != token::LBRACKET) {
-                        // This is an extension
-                        break;
-                    }
                     self.parse_attribute(true)
                 }
                 token::DOC_COMMENT(s) => {
diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs
index 8abc01b6d75..1221d8401be 100644
--- a/src/libsyntax/parse/comments.rs
+++ b/src/libsyntax/parse/comments.rs
@@ -12,7 +12,7 @@ use ast;
 use codemap::{BytePos, CharPos, CodeMap, Pos};
 use diagnostic;
 use parse::lexer::{is_whitespace, with_str_from, Reader};
-use parse::lexer::{StringReader, bump, is_eof, nextch_is, TokenAndSpan};
+use parse::lexer::{StringReader, bump, peek, is_eof, nextch_is, TokenAndSpan};
 use parse::lexer::{is_line_non_doc_comment, is_block_non_doc_comment};
 use parse::lexer;
 use parse::token;
@@ -331,7 +331,11 @@ fn consume_comment(rdr: &StringReader,
     } else if rdr.curr_is('/') && nextch_is(rdr, '*') {
         read_block_comment(rdr, code_to_the_left, comments);
     } else if rdr.curr_is('#') && nextch_is(rdr, '!') {
-        read_shebang_comment(rdr, code_to_the_left, comments);
+        // Make sure the following token is **not** the beginning
+        // of an inner attribute, which starts with the same syntax.
+        if peek(rdr, 2).unwrap() != '[' {
+            read_shebang_comment(rdr, code_to_the_left, comments);
+        }
     } else { fail!(); }
     debug!("<<< consume comment");
 }
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index 58ec6acc3ac..061d460af5e 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -271,9 +271,21 @@ pub fn bump(rdr: &StringReader) {
         rdr.curr.set(None);
     }
 }
+
+// EFFECT: Peek 'n' characters ahead.
+pub fn peek(rdr: &StringReader, n: uint) -> Option<char> {
+    let offset = byte_offset(rdr, rdr.pos.get()).to_uint() + (n - 1);
+    if offset < (rdr.filemap.src).len() {
+        Some(rdr.filemap.src.char_at(offset))
+    } else {
+        None
+    }
+}
+
 pub fn is_eof(rdr: &StringReader) -> bool {
     rdr.curr.get().is_none()
 }
+
 pub fn nextch(rdr: &StringReader) -> Option<char> {
     let offset = byte_offset(rdr, rdr.pos.get()).to_uint();
     if offset < rdr.filemap.deref().src.len() {
@@ -370,6 +382,12 @@ fn consume_any_line_comment(rdr: &StringReader)
         }
     } else if rdr.curr_is('#') {
         if nextch_is(rdr, '!') {
+
+            // Parse an inner attribute.
+            if peek(rdr, 2).unwrap() == '[' {
+                return None;
+            }
+
             // I guess this is the only way to figure out if
             // we're at the beginning of the file...
             let cmap = CodeMap::new();