Skip to content

Commit

Permalink
auto merge of #13037 : alexcrichton/rust/attr-syntax, r=brson
Browse files Browse the repository at this point in the history
This will require a snapshot to finish, but these commits update the parser to parse attributes of the form `#![...]`

Thanks to @thehydroimpulse for all the initial work!

cc #2569
  • Loading branch information
bors committed Mar 21, 2014
2 parents 6eae7df + 84a91b8 commit 739f22f
Show file tree
Hide file tree
Showing 14 changed files with 111 additions and 22 deletions.
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() {
}

0 comments on commit 739f22f

Please sign in to comment.