Skip to content

Commit 2772a29

Browse files
committed
rustc: Support outer attributes on items that are defined as statements
Issue #487
1 parent b8a5440 commit 2772a29

File tree

2 files changed

+127
-10
lines changed

2 files changed

+127
-10
lines changed

src/comp/front/parser.rs

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import std::str;
55
import std::option;
66
import std::option::some;
77
import std::option::none;
8+
import std::either;
9+
import std::either::left;
10+
import std::either::right;
811
import std::map::hashmap;
912
import driver::session;
1013
import util::common;
@@ -816,14 +819,9 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
816819
hi = es.span.hi;
817820
ex = ast::expr_bind(e, es.node, p.get_ann());
818821
} else if (p.peek() == token::POUND) {
819-
p.bump();
820-
auto pth = parse_path(p);
821-
auto es =
822-
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
823-
parse_expr, p);
824-
hi = es.span.hi;
825-
auto ext_span = rec(lo=lo, hi=hi);
826-
ex = expand_syntax_ext(p, ext_span, pth, es.node, none);
822+
auto ex_ext = parse_syntax_ext(p);
823+
lo = ex_ext.span.lo;
824+
ex = ex_ext.node;
827825
} else if (eat_word(p, "fail")) {
828826
auto msg;
829827
alt (p.peek()) {
@@ -917,6 +915,21 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
917915
ret @spanned(lo, hi, ex);
918916
}
919917

918+
fn parse_syntax_ext(&parser p) -> @ast::expr {
919+
auto lo = p.get_lo_pos();
920+
expect(p, token::POUND);
921+
ret parse_syntax_ext_inner(p, lo);
922+
}
923+
924+
fn parse_syntax_ext_inner(&parser p, uint lo) -> @ast::expr {
925+
auto pth = parse_path(p);
926+
auto es = parse_seq(token::LPAREN, token::RPAREN,
927+
some(token::COMMA), parse_expr, p);
928+
auto hi = es.span.hi;
929+
auto ext_span = rec(lo=lo, hi=hi);
930+
auto ex = expand_syntax_ext(p, ext_span, pth, es.node, none);
931+
ret @spanned(lo, hi, ex);
932+
}
920933

921934
/*
922935
* FIXME: This is a crude approximation of the syntax-extension system,
@@ -1423,7 +1436,22 @@ fn parse_source_stmt(&parser p) -> @ast::stmt {
14231436
auto hi = p.get_span();
14241437
ret @spanned(lo, decl.span.hi, ast::stmt_decl(decl, p.get_ann()));
14251438
} else {
1426-
alt (parse_item(p, [])) {
1439+
1440+
auto item_attrs;
1441+
alt (parse_attrs_or_ext(p)) {
1442+
case (none) {
1443+
item_attrs = [];
1444+
}
1445+
case (some(left(?attrs))) {
1446+
item_attrs = attrs;
1447+
}
1448+
case (some(right(?ext))) {
1449+
ret @spanned(lo, ext.span.hi,
1450+
ast::stmt_expr(ext, p.get_ann()));
1451+
}
1452+
}
1453+
1454+
alt (parse_item(p, item_attrs)) {
14271455
case (got_item(?i)) {
14281456
auto hi = i.span.hi;
14291457
auto decl = @spanned(lo, hi, ast::decl_item(i));
@@ -1936,6 +1964,26 @@ fn parse_item(&parser p, vec[ast::attribute] attrs) -> parsed_item {
19361964
} else { ret no_item; }
19371965
}
19381966

1967+
// A type to distingush between the parsing of item attributes or syntax
1968+
// extensions, which both begin with token.POUND
1969+
type attr_or_ext = option::t[either::t[vec[ast::attribute],
1970+
@ast::expr]];
1971+
1972+
fn parse_attrs_or_ext(&parser p) -> attr_or_ext {
1973+
if (p.peek() == token::POUND) {
1974+
auto lo = p.get_lo_pos();
1975+
p.bump();
1976+
if (p.peek() == token::LBRACKET) {
1977+
auto first_attr = parse_attribute_inner(p, lo);
1978+
ret some(left([first_attr] + parse_attributes(p)));
1979+
} else {
1980+
ret some(right(parse_syntax_ext_inner(p, lo)));
1981+
}
1982+
} else {
1983+
ret none;
1984+
}
1985+
}
1986+
19391987
fn parse_attributes(&parser p) -> vec[ast::attribute] {
19401988
let vec[ast::attribute] attrs = [];
19411989
while (p.peek() == token::POUND) { attrs += [parse_attribute(p)]; }
@@ -1945,6 +1993,10 @@ fn parse_attributes(&parser p) -> vec[ast::attribute] {
19451993
fn parse_attribute(&parser p) -> ast::attribute {
19461994
auto lo = p.get_lo_pos();
19471995
expect(p, token::POUND);
1996+
ret parse_attribute_inner(p, lo);
1997+
}
1998+
1999+
fn parse_attribute_inner(&parser p, uint lo) -> ast::attribute {
19482000
expect(p, token::LBRACKET);
19492001
auto meta_item = parse_meta_item(p);
19502002
expect(p, token::RBRACKET);

src/test/run-pass/item-attributes.rs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,69 @@ mod test_multi_attr_outer {
5252
obj o() { }
5353
}
5454

55-
fn main() { }
55+
mod test_stmt_single_attr_outer {
56+
57+
fn f() {
58+
59+
#[attr = "val"]
60+
const int x = 10;
61+
62+
#[attr = "val"]
63+
fn f() {}
64+
65+
/* FIXME: Issue #493
66+
#[attr = "val"]
67+
mod mod1 {
68+
}
69+
70+
#[attr = "val"]
71+
native "rust" mod rustrt {
72+
}
73+
*/
74+
75+
#[attr = "val"]
76+
type t = obj { };
77+
78+
#[attr = "val"]
79+
obj o() { }
80+
81+
}
82+
}
83+
84+
mod test_stmt_multi_attr_outer {
85+
86+
fn f() {
87+
88+
#[attr1 = "val"]
89+
#[attr2 = "val"]
90+
const int x = 10;
91+
92+
#[attr1 = "val"]
93+
#[attr2 = "val"]
94+
fn f() {}
95+
96+
/* FIXME: Issue #493
97+
#[attr1 = "val"]
98+
#[attr2 = "val"]
99+
mod mod1 {
100+
}
101+
102+
#[attr1 = "val"]
103+
#[attr2 = "val"]
104+
native "rust" mod rustrt {
105+
}
106+
*/
107+
108+
#[attr1 = "val"]
109+
#[attr2 = "val"]
110+
type t = obj { };
111+
112+
#[attr1 = "val"]
113+
#[attr2 = "val"]
114+
obj o() { }
115+
116+
}
117+
}
118+
119+
fn main() {
120+
}

0 commit comments

Comments
 (0)