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.rs46
-rw-r--r--src/libsyntax/parse/comments.rs12
-rw-r--r--src/libsyntax/parse/lexer.rs30
3 files changed, 41 insertions, 47 deletions
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index 92b93fd88dd..8f7fb5749a1 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -58,41 +58,40 @@ impl<'a> ParserAttr for Parser<'a> {
         return attrs;
     }
 
-    // matches attribute = # [ meta_item ]
+    // matches attribute = # ! [ meta_item ]
     //
-    // if permit_inner is true, then a trailing `;` indicates an inner
+    // if permit_inner is true, then a leading `!` indicates an inner
     // attribute
     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 {
+        let (span, value, mut style) = match self.token {
             INTERPOLATED(token::NtAttr(attr)) => {
                 assert!(attr.node.style == ast::AttrOuter);
                 self.bump();
-                (attr.span, attr.node.value)
+                (attr.span, attr.node.value, ast::AttrOuter)
             }
             token::POUND => {
                 let lo = self.span.lo;
                 self.bump();
 
-                if self.eat(&token::NOT) {
+                let style = if self.eat(&token::NOT) {
                     if !permit_inner {
-                        self.fatal("an inner attribute was not permitted in this context.");
+                        self.span_err(self.span,
+                                      "an inner attribute is not permitted in \
+                                       this context");
                     }
+                    ast::AttrInner
                 } else {
-                    warned = true;
-                    // NOTE: uncomment this after a stage0 snap
-                    //self.warn("The syntax for inner attributes have changed.
-                    //    Use `#![lang(foo)]` instead.");
-                }
+                    ast::AttrOuter
+                };
 
                 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)
+                (mk_sp(lo, hi), meta_item, style)
             }
             _ => {
                 let token_str = self.this_token_to_str();
@@ -101,21 +100,12 @@ impl<'a> ParserAttr for Parser<'a> {
             }
         };
 
-        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
-        };
+        if permit_inner && self.eat(&token::SEMI) {
+            // NOTE: uncomment this after a stage0 snap
+            //self.warn("This uses the old attribute syntax. Semicolons
+            //  are not longer required.");
+            style = ast::AttrInner;
+        }
 
         return Spanned {
             span: span,
diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs
index 1221d8401be..43ae9b97350 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, peek, is_eof, nextch_is, TokenAndSpan};
+use parse::lexer::{StringReader, bump, is_eof, nextch_is, TokenAndSpan};
 use parse::lexer::{is_line_non_doc_comment, is_block_non_doc_comment};
 use parse::lexer;
 use parse::token;
@@ -319,7 +319,9 @@ fn read_block_comment(rdr: &StringReader,
 fn peeking_at_comment(rdr: &StringReader) -> bool {
     return (rdr.curr_is('/') && nextch_is(rdr, '/')) ||
          (rdr.curr_is('/') && nextch_is(rdr, '*')) ||
-         (rdr.curr_is('#') && nextch_is(rdr, '!'));
+         // consider shebangs comments, but not inner attributes
+         (rdr.curr_is('#') && nextch_is(rdr, '!') &&
+          !lexer::nextnextch_is(rdr, '['));
 }
 
 fn consume_comment(rdr: &StringReader,
@@ -331,11 +333,7 @@ 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, '!') {
-        // 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);
-        }
+        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 061d460af5e..ca2fbd24587 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -18,9 +18,10 @@ use parse::token::{str_to_ident};
 
 use std::cell::{Cell, RefCell};
 use std::char;
-use std::rc::Rc;
 use std::mem::replace;
 use std::num::from_str_radix;
+use std::rc::Rc;
+use std::str;
 
 pub use ext::tt::transcribe::{TtReader, new_tt_reader};
 
@@ -272,16 +273,6 @@ pub fn bump(rdr: &StringReader) {
     }
 }
 
-// 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()
 }
@@ -298,6 +289,21 @@ pub fn nextch_is(rdr: &StringReader, c: char) -> bool {
     nextch(rdr) == Some(c)
 }
 
+pub fn nextnextch(rdr: &StringReader) -> Option<char> {
+    let offset = byte_offset(rdr, rdr.pos.get()).to_uint();
+    let s = rdr.filemap.deref().src.as_slice();
+    if offset >= s.len() { return None }
+    let str::CharRange { next, .. } = s.char_range_at(offset);
+    if next < s.len() {
+        Some(s.char_at(next))
+    } else {
+        None
+    }
+}
+pub fn nextnextch_is(rdr: &StringReader, c: char) -> bool {
+    nextnextch(rdr) == Some(c)
+}
+
 fn hex_digit_val(c: Option<char>) -> int {
     let d = c.unwrap_or('\x00');
 
@@ -384,7 +390,7 @@ fn consume_any_line_comment(rdr: &StringReader)
         if nextch_is(rdr, '!') {
 
             // Parse an inner attribute.
-            if peek(rdr, 2).unwrap() == '[' {
+            if nextnextch_is(rdr, '[') {
                 return None;
             }