From 84a91b860330c2b83fd0546b33a949079d422166 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 20 Mar 2014 11:21:17 -0700 Subject: syntax: Tidy up parsing the new attribute syntax --- src/libsyntax/parse/attr.rs | 46 ++++++++++++++++------------------------- src/libsyntax/parse/comments.rs | 12 +++++------ src/libsyntax/parse/lexer.rs | 30 ++++++++++++++++----------- 3 files changed, 41 insertions(+), 47 deletions(-) (limited to 'src/libsyntax/parse') 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 { - 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 { + 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) -> 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; } -- cgit 1.4.1-3-g733a5