Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update attribute syntax parsing #13037

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/compiletest/compiletest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#[feature(phase)];

#[allow(non_camel_case_types)];
#[allow(deprecated_owned_vector)]; // NOTE: remove after stage0
#[deny(warnings)];

extern crate test;
Expand Down
1 change: 1 addition & 0 deletions src/libarena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
html_root_url = "http://static.rust-lang.org/doc/master")];
#[allow(missing_doc)];
#[feature(managed_boxes)];
#[allow(deprecated_owned_vector)]; // NOTE: remove after stage0

extern crate collections;

Expand Down
1 change: 1 addition & 0 deletions src/libgreen/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@
// NB this does *not* include globs, please keep it that way.
#[feature(macro_rules, phase)];
#[allow(visible_private_types)];
#[allow(deprecated_owned_vector)]; // NOTE: remove after stage0

#[cfg(test)] #[phase(syntax, link)] extern crate log;
extern crate rand;
Expand Down
1 change: 1 addition & 0 deletions src/librustuv/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ via `close` and `delete` methods.
#[feature(macro_rules)];
#[deny(unused_result, unused_must_use)];
#[allow(visible_private_types)];
#[allow(deprecated_owned_vector)]; // NOTE: remove after stage0

#[cfg(test)] extern crate green;

Expand Down
44 changes: 26 additions & 18 deletions src/libsyntax/parse/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand All @@ -61,40 +58,55 @@ 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 (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();

let style = if self.eat(&token::NOT) {
if !permit_inner {
self.span_err(self.span,
"an inner attribute is not permitted in \
this context");
}
ast::AttrInner
} else {
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();
self.fatal(format!("expected `\\#` but found `{}`",
token_str));
}
};
let style = if permit_inner && self.token == token::SEMI {
self.bump();
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,
node: ast::Attribute_ {
Expand Down Expand Up @@ -125,10 +137,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) => {
Expand Down
4 changes: 3 additions & 1 deletion src/libsyntax/parse/comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
26 changes: 25 additions & 1 deletion src/libsyntax/parse/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -271,9 +272,11 @@ pub fn bump(rdr: &StringReader) {
rdr.curr.set(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() {
Expand All @@ -286,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');

Expand Down Expand Up @@ -370,6 +388,12 @@ fn consume_any_line_comment(rdr: &StringReader)
}
} else if rdr.curr_is('#') {
if nextch_is(rdr, '!') {

// Parse an inner attribute.
if nextnextch_is(rdr, '[') {
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();
Expand Down
1 change: 1 addition & 0 deletions src/libtest/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
html_root_url = "http://static.rust-lang.org/doc/master")];

#[feature(asm, macro_rules)];
#[allow(deprecated_owned_vector)]; // NOTE: remove after stage0

extern crate collections;
extern crate getopts;
Expand Down
14 changes: 14 additions & 0 deletions src/test/compile-fail/attr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {}

#![lang(foo)] //~ ERROR an inner attribute is not permitted in this context
fn foo() {}
2 changes: 1 addition & 1 deletion src/test/compile-fail/column-offset-1-based.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

# //~ ERROR 11:1: 11:2 error: expected item
# //~ ERROR 11:1: 11:2 error: expected `[` but found `<eof>`
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-1655.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern:expected item
// error-pattern:expected `[` but found `~`
mod blade_runner {
#~[doc(
brief = "Blade Runner is probably the best movie ever",
Expand Down
16 changes: 16 additions & 0 deletions src/test/run-pass/attr-mix-new.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[foo(bar)]
mod foo {
#![feature(globs)]
}

pub fn main() {}
5 changes: 5 additions & 0 deletions src/test/run-pass/attr-shebang.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#![allow(unknown_features)]
#![feature(bogus)]
pub fn main() { }
// ignore-license
// ignore-fast
15 changes: 15 additions & 0 deletions src/test/run-pass/attr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-fast

#[main]
fn foo() {
}