rustc: Support outer attributes on items that are defined as statements
Issue #487
This commit is contained in:
parent
b8a5440b2d
commit
2772a29e92
2 changed files with 127 additions and 10 deletions
|
@ -5,6 +5,9 @@ import std::str;
|
||||||
import std::option;
|
import std::option;
|
||||||
import std::option::some;
|
import std::option::some;
|
||||||
import std::option::none;
|
import std::option::none;
|
||||||
|
import std::either;
|
||||||
|
import std::either::left;
|
||||||
|
import std::either::right;
|
||||||
import std::map::hashmap;
|
import std::map::hashmap;
|
||||||
import driver::session;
|
import driver::session;
|
||||||
import util::common;
|
import util::common;
|
||||||
|
@ -816,14 +819,9 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
|
||||||
hi = es.span.hi;
|
hi = es.span.hi;
|
||||||
ex = ast::expr_bind(e, es.node, p.get_ann());
|
ex = ast::expr_bind(e, es.node, p.get_ann());
|
||||||
} else if (p.peek() == token::POUND) {
|
} else if (p.peek() == token::POUND) {
|
||||||
p.bump();
|
auto ex_ext = parse_syntax_ext(p);
|
||||||
auto pth = parse_path(p);
|
lo = ex_ext.span.lo;
|
||||||
auto es =
|
ex = ex_ext.node;
|
||||||
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);
|
|
||||||
} else if (eat_word(p, "fail")) {
|
} else if (eat_word(p, "fail")) {
|
||||||
auto msg;
|
auto msg;
|
||||||
alt (p.peek()) {
|
alt (p.peek()) {
|
||||||
|
@ -917,6 +915,21 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
|
||||||
ret @spanned(lo, hi, ex);
|
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,
|
* 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();
|
auto hi = p.get_span();
|
||||||
ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_ann()));
|
ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_ann()));
|
||||||
} else {
|
} 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)) {
|
case (got_item(?i)) {
|
||||||
auto hi = i.span.hi;
|
auto hi = i.span.hi;
|
||||||
auto decl = @spanned(lo, hi, ast::decl_item(i));
|
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; }
|
} 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] {
|
fn parse_attributes(&parser p) -> vec[ast::attribute] {
|
||||||
let vec[ast::attribute] attrs = [];
|
let vec[ast::attribute] attrs = [];
|
||||||
while (p.peek() == token::POUND) { attrs += [parse_attribute(p)]; }
|
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 {
|
fn parse_attribute(&parser p) -> ast::attribute {
|
||||||
auto lo = p.get_lo_pos();
|
auto lo = p.get_lo_pos();
|
||||||
expect(p, token::POUND);
|
expect(p, token::POUND);
|
||||||
|
ret parse_attribute_inner(p, lo);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_attribute_inner(&parser p, uint lo) -> ast::attribute {
|
||||||
expect(p, token::LBRACKET);
|
expect(p, token::LBRACKET);
|
||||||
auto meta_item = parse_meta_item(p);
|
auto meta_item = parse_meta_item(p);
|
||||||
expect(p, token::RBRACKET);
|
expect(p, token::RBRACKET);
|
||||||
|
|
|
@ -52,4 +52,69 @@ mod test_multi_attr_outer {
|
||||||
obj o() { }
|
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…
Add table
Add a link
Reference in a new issue