Skip to content

Commit f3996d3

Browse files
committed
rustc: Parse inner attributes of modules
Issue #487
1 parent 0efd7fa commit f3996d3

File tree

3 files changed

+93
-17
lines changed

3 files changed

+93
-17
lines changed

src/comp/front/eval.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ fn eval_crate_directive(ctx cx, env e, @ast::crate_directive cdir, str prefix,
287287
auto p0 =
288288
new_parser(cx.sess, e, start_id, full_path, cx.chpos,
289289
cx.next_ann);
290-
auto m0 = parse_mod_items(p0, token::EOF);
290+
auto m0 = parse_mod_items(p0, token::EOF, []);
291291
auto next_id = p0.next_def_id();
292292
// Thread defids and chpos through the parsers
293293

src/comp/front/parser.rs

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -955,10 +955,10 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
955955
fn parse_syntax_ext(&parser p) -> @ast::expr {
956956
auto lo = p.get_lo_pos();
957957
expect(p, token::POUND);
958-
ret parse_syntax_ext_inner(p, lo);
958+
ret parse_syntax_ext_naked(p, lo);
959959
}
960960

961-
fn parse_syntax_ext_inner(&parser p, uint lo) -> @ast::expr {
961+
fn parse_syntax_ext_naked(&parser p, uint lo) -> @ast::expr {
962962
auto pth = parse_path(p);
963963
auto es = parse_seq(token::LPAREN, token::RPAREN,
964964
some(token::COMMA), parse_expr, p);
@@ -1496,7 +1496,7 @@ fn parse_source_stmt(&parser p) -> @ast::stmt {
14961496
} else {
14971497

14981498
auto item_attrs;
1499-
alt (parse_attrs_or_ext(p)) {
1499+
alt (parse_outer_attrs_or_ext(p)) {
15001500
case (none) {
15011501
item_attrs = [];
15021502
}
@@ -1799,11 +1799,14 @@ fn parse_item_obj(&parser p, ast::layer lyr, vec[ast::attribute] attrs) ->
17991799
p.next_def_id()), attrs);
18001800
}
18011801

1802-
fn parse_mod_items(&parser p, token::token term) -> ast::_mod {
1802+
fn parse_mod_items(&parser p, token::token term,
1803+
vec[ast::attribute] first_item_attrs) -> ast::_mod {
18031804
auto view_items = parse_view(p);
18041805
let vec[@ast::item] items = [];
1806+
auto initial_attrs = first_item_attrs;
18051807
while (p.peek() != term) {
1806-
auto attrs = parse_attributes(p);
1808+
auto attrs = initial_attrs + parse_outer_attributes(p);
1809+
initial_attrs = [];
18071810
alt (parse_item(p, attrs)) {
18081811
case (got_item(?i)) { vec::push(items, i); }
18091812
case (_) {
@@ -1830,10 +1833,13 @@ fn parse_item_mod(&parser p, vec[ast::attribute] attrs) -> @ast::item {
18301833
auto lo = p.get_last_lo_pos();
18311834
auto id = parse_ident(p);
18321835
expect(p, token::LBRACE);
1833-
auto m = parse_mod_items(p, token::RBRACE);
1836+
auto inner_attrs = parse_inner_attributes(p);
1837+
auto first_item_outer_attrs = inner_attrs._1;
1838+
auto m = parse_mod_items(p, token::RBRACE,
1839+
first_item_outer_attrs);
18341840
auto hi = p.get_hi_pos();
18351841
expect(p, token::RBRACE);
1836-
ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs);
1842+
ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs._0);
18371843
}
18381844

18391845
fn parse_item_native_type(&parser p) -> @ast::native_item {
@@ -2039,41 +2045,67 @@ fn parse_item(&parser p, vec[ast::attribute] attrs) -> parsed_item {
20392045
type attr_or_ext = option::t[either::t[vec[ast::attribute],
20402046
@ast::expr]];
20412047

2042-
fn parse_attrs_or_ext(&parser p) -> attr_or_ext {
2048+
fn parse_outer_attrs_or_ext(&parser p) -> attr_or_ext {
20432049
if (p.peek() == token::POUND) {
20442050
auto lo = p.get_lo_pos();
20452051
p.bump();
20462052
if (p.peek() == token::LBRACKET) {
2047-
auto first_attr = parse_attribute_inner(p, lo);
2048-
ret some(left([first_attr] + parse_attributes(p)));
2053+
auto first_attr = parse_attribute_naked(p, lo);
2054+
ret some(left([first_attr] + parse_outer_attributes(p)));
20492055
} else {
2050-
ret some(right(parse_syntax_ext_inner(p, lo)));
2056+
ret some(right(parse_syntax_ext_naked(p, lo)));
20512057
}
20522058
} else {
20532059
ret none;
20542060
}
20552061
}
20562062

2057-
fn parse_attributes(&parser p) -> vec[ast::attribute] {
2063+
// Parse attributes that appear before an item
2064+
fn parse_outer_attributes(&parser p) -> vec[ast::attribute] {
20582065
let vec[ast::attribute] attrs = [];
2059-
while (p.peek() == token::POUND) { attrs += [parse_attribute(p)]; }
2066+
while (p.peek() == token::POUND) {
2067+
attrs += [parse_attribute(p)];
2068+
}
20602069
ret attrs;
20612070
}
20622071

20632072
fn parse_attribute(&parser p) -> ast::attribute {
20642073
auto lo = p.get_lo_pos();
20652074
expect(p, token::POUND);
2066-
ret parse_attribute_inner(p, lo);
2075+
ret parse_attribute_naked(p, lo);
20672076
}
20682077

2069-
fn parse_attribute_inner(&parser p, uint lo) -> ast::attribute {
2078+
fn parse_attribute_naked(&parser p, uint lo) -> ast::attribute {
20702079
expect(p, token::LBRACKET);
20712080
auto meta_item = parse_meta_item(p);
20722081
expect(p, token::RBRACKET);
20732082
auto hi = p.get_hi_pos();
20742083
ret spanned(lo, hi, rec(style=ast::attr_outer, value=*meta_item));
20752084
}
20762085

2086+
// Parse attributes that appear after the opening of an item, each terminated
2087+
// by a semicolon. In addition to a vector of inner attributes, this function
2088+
// also returns a vector that may contain the first outer attribute of the
2089+
// next item (since we can't know whether the attribute is an inner attribute
2090+
// of the containing item or an outer attribute of the first contained item
2091+
// until we see the semi).
2092+
fn parse_inner_attributes(&parser p) -> tup(vec[ast::attribute],
2093+
vec[ast::attribute]) {
2094+
let vec[ast::attribute] inner_attrs = [];
2095+
let vec[ast::attribute] next_outer_attrs = [];
2096+
while (p.peek() == token::POUND) {
2097+
auto attr = parse_attribute(p);
2098+
if (p.peek() == token::SEMI) {
2099+
p.bump();
2100+
inner_attrs += [attr];
2101+
} else {
2102+
next_outer_attrs += [attr];
2103+
break;
2104+
}
2105+
}
2106+
ret tup(inner_attrs, next_outer_attrs);
2107+
}
2108+
20772109
fn parse_meta_item(&parser p) -> @ast::meta_item {
20782110
auto lo = p.get_lo_pos();
20792111
auto ident = parse_ident(p);
@@ -2234,7 +2266,7 @@ fn parse_native_view(&parser p) -> vec[@ast::view_item] {
22342266

22352267
fn parse_crate_from_source_file(&parser p) -> @ast::crate {
22362268
auto lo = p.get_lo_pos();
2237-
auto m = parse_mod_items(p, token::EOF);
2269+
auto m = parse_mod_items(p, token::EOF, []);
22382270
let vec[@ast::crate_directive] cdirs = [];
22392271
ret @spanned(lo, p.get_lo_pos(), rec(directives=cdirs, module=m));
22402272
}

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,5 +116,49 @@ mod test_stmt_multi_attr_outer {
116116
}
117117
}
118118

119+
mod test_attr_inner {
120+
121+
mod m {
122+
// This is an attribute of mod m
123+
#[attr = "val"];
124+
}
125+
}
126+
127+
mod test_attr_inner_then_outer {
128+
129+
mod m {
130+
// This is an attribute of mod m
131+
#[attr = "val"];
132+
// This is an attribute of fn f
133+
#[attr = "val"]
134+
fn f() {
135+
}
136+
}
137+
}
138+
139+
mod test_attr_inner_then_outer_multi {
140+
mod m {
141+
// This is an attribute of mod m
142+
#[attr1 = "val"];
143+
#[attr2 = "val"];
144+
// This is an attribute of fn f
145+
#[attr1 = "val"]
146+
#[attr2 = "val"]
147+
fn f() {
148+
}
149+
}
150+
}
151+
119152
fn main() {
120153
}
154+
155+
//
156+
// Local Variables:
157+
// mode: rust
158+
// fill-column: 78;
159+
// indent-tabs-mode: nil
160+
// c-basic-offset: 4
161+
// buffer-file-coding-system: utf-8-unix
162+
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
163+
// End:
164+
//

0 commit comments

Comments
 (0)