rustc: Support outer attributes on items that are defined as statements
Issue #487
This commit is contained in:
parent
b8a5440b2d
commit
2772a29e92
@ -5,6 +5,9 @@
|
||||
import std::option;
|
||||
import std::option::some;
|
||||
import std::option::none;
|
||||
import std::either;
|
||||
import std::either::left;
|
||||
import std::either::right;
|
||||
import std::map::hashmap;
|
||||
import driver::session;
|
||||
import util::common;
|
||||
@ -816,14 +819,9 @@ fn parse_expr_opt(&parser p) -> option::t[@ast::expr] {
|
||||
hi = es.span.hi;
|
||||
ex = ast::expr_bind(e, es.node, p.get_ann());
|
||||
} else if (p.peek() == token::POUND) {
|
||||
p.bump();
|
||||
auto pth = parse_path(p);
|
||||
auto es =
|
||||
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
|
||||
parse_expr, p);
|
||||
hi = es.span.hi;
|
||||
auto ext_span = rec(lo=lo, hi=hi);
|
||||
ex = expand_syntax_ext(p, ext_span, pth, es.node, none);
|
||||
auto ex_ext = parse_syntax_ext(p);
|
||||
lo = ex_ext.span.lo;
|
||||
ex = ex_ext.node;
|
||||
} else if (eat_word(p, "fail")) {
|
||||
auto msg;
|
||||
alt (p.peek()) {
|
||||
@ -917,6 +915,21 @@ fn parse_expr_opt(&parser p) -> option::t[@ast::expr] {
|
||||
ret @spanned(lo, hi, ex);
|
||||
}
|
||||
|
||||
fn parse_syntax_ext(&parser p) -> @ast::expr {
|
||||
auto lo = p.get_lo_pos();
|
||||
expect(p, token::POUND);
|
||||
ret parse_syntax_ext_inner(p, lo);
|
||||
}
|
||||
|
||||
fn parse_syntax_ext_inner(&parser p, uint lo) -> @ast::expr {
|
||||
auto pth = parse_path(p);
|
||||
auto es = parse_seq(token::LPAREN, token::RPAREN,
|
||||
some(token::COMMA), parse_expr, p);
|
||||
auto hi = es.span.hi;
|
||||
auto ext_span = rec(lo=lo, hi=hi);
|
||||
auto ex = expand_syntax_ext(p, ext_span, pth, es.node, none);
|
||||
ret @spanned(lo, hi, ex);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: This is a crude approximation of the syntax-extension system,
|
||||
@ -1423,7 +1436,22 @@ fn parse_source_stmt(&parser p) -> @ast::stmt {
|
||||
auto hi = p.get_span();
|
||||
ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_ann()));
|
||||
} else {
|
||||
alt (parse_item(p, [])) {
|
||||
|
||||
auto item_attrs;
|
||||
alt (parse_attrs_or_ext(p)) {
|
||||
case (none) {
|
||||
item_attrs = [];
|
||||
}
|
||||
case (some(left(?attrs))) {
|
||||
item_attrs = attrs;
|
||||
}
|
||||
case (some(right(?ext))) {
|
||||
ret @spanned(lo, ext.span.hi,
|
||||
ast::stmt_expr(ext, p.get_ann()));
|
||||
}
|
||||
}
|
||||
|
||||
alt (parse_item(p, item_attrs)) {
|
||||
case (got_item(?i)) {
|
||||
auto hi = i.span.hi;
|
||||
auto decl = @spanned(lo, hi, ast::decl_item(i));
|
||||
@ -1936,6 +1964,26 @@ fn parse_item(&parser p, vec[ast::attribute] attrs) -> parsed_item {
|
||||
} else { ret no_item; }
|
||||
}
|
||||
|
||||
// A type to distingush between the parsing of item attributes or syntax
|
||||
// extensions, which both begin with token.POUND
|
||||
type attr_or_ext = option::t[either::t[vec[ast::attribute],
|
||||
@ast::expr]];
|
||||
|
||||
fn parse_attrs_or_ext(&parser p) -> attr_or_ext {
|
||||
if (p.peek() == token::POUND) {
|
||||
auto lo = p.get_lo_pos();
|
||||
p.bump();
|
||||
if (p.peek() == token::LBRACKET) {
|
||||
auto first_attr = parse_attribute_inner(p, lo);
|
||||
ret some(left([first_attr] + parse_attributes(p)));
|
||||
} else {
|
||||
ret some(right(parse_syntax_ext_inner(p, lo)));
|
||||
}
|
||||
} else {
|
||||
ret none;
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_attributes(&parser p) -> vec[ast::attribute] {
|
||||
let vec[ast::attribute] attrs = [];
|
||||
while (p.peek() == token::POUND) { attrs += [parse_attribute(p)]; }
|
||||
@ -1945,6 +1993,10 @@ fn parse_attributes(&parser p) -> vec[ast::attribute] {
|
||||
fn parse_attribute(&parser p) -> ast::attribute {
|
||||
auto lo = p.get_lo_pos();
|
||||
expect(p, token::POUND);
|
||||
ret parse_attribute_inner(p, lo);
|
||||
}
|
||||
|
||||
fn parse_attribute_inner(&parser p, uint lo) -> ast::attribute {
|
||||
expect(p, token::LBRACKET);
|
||||
auto meta_item = parse_meta_item(p);
|
||||
expect(p, token::RBRACKET);
|
||||
|
@ -52,4 +52,69 @@ mod mod1 {
|
||||
obj o() { }
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
mod test_stmt_single_attr_outer {
|
||||
|
||||
fn f() {
|
||||
|
||||
#[attr = "val"]
|
||||
const int x = 10;
|
||||
|
||||
#[attr = "val"]
|
||||
fn f() {}
|
||||
|
||||
/* FIXME: Issue #493
|
||||
#[attr = "val"]
|
||||
mod mod1 {
|
||||
}
|
||||
|
||||
#[attr = "val"]
|
||||
native "rust" mod rustrt {
|
||||
}
|
||||
*/
|
||||
|
||||
#[attr = "val"]
|
||||
type t = obj { };
|
||||
|
||||
#[attr = "val"]
|
||||
obj o() { }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
mod test_stmt_multi_attr_outer {
|
||||
|
||||
fn f() {
|
||||
|
||||
#[attr1 = "val"]
|
||||
#[attr2 = "val"]
|
||||
const int x = 10;
|
||||
|
||||
#[attr1 = "val"]
|
||||
#[attr2 = "val"]
|
||||
fn f() {}
|
||||
|
||||
/* FIXME: Issue #493
|
||||
#[attr1 = "val"]
|
||||
#[attr2 = "val"]
|
||||
mod mod1 {
|
||||
}
|
||||
|
||||
#[attr1 = "val"]
|
||||
#[attr2 = "val"]
|
||||
native "rust" mod rustrt {
|
||||
}
|
||||
*/
|
||||
|
||||
#[attr1 = "val"]
|
||||
#[attr2 = "val"]
|
||||
type t = obj { };
|
||||
|
||||
#[attr1 = "val"]
|
||||
#[attr2 = "val"]
|
||||
obj o() { }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user