Skip to content

Commit 628e80d

Browse files
committed
syntax: Extract attribute parsing to its own mod
1 parent 3d6c791 commit 628e80d

File tree

6 files changed

+140
-116
lines changed

6 files changed

+140
-116
lines changed

src/librustsyntax/parse.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ fn parse_crate_from_crate_file(input: str, cfg: ast::crate_cfg,
8686
let p = new_parser_from_file(sess, cfg, input, parser::CRATE_FILE);
8787
let lo = p.span.lo;
8888
let prefix = path::dirname(p.reader.filemap.name);
89-
let leading_attrs = parser::parse_inner_attrs_and_next(p);
89+
let leading_attrs = attr::parse_inner_attrs_and_next(p);
9090
let crate_attrs = leading_attrs.inner;
9191
let first_cdir_attr = leading_attrs.next;
9292
let cdirs = parser::parse_crate_directives(

src/librustsyntax/parse/attr.rs

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import either::{either, left, right};
2+
import parser::{parse_seq,
3+
seq_sep,
4+
expect,
5+
parse_lit,
6+
parse_ident,
7+
parse_syntax_ext_naked,
8+
spanned};
9+
10+
export attr_or_ext;
11+
export parse_outer_attributes;
12+
export parse_outer_attrs_or_ext;
13+
export parse_inner_attrs_and_next;
14+
export parse_optional_meta;
15+
16+
// A type to distingush between the parsing of item attributes or syntax
17+
// extensions, which both begin with token.POUND
18+
type attr_or_ext = option<either<[ast::attribute], @ast::expr>>;
19+
20+
fn parse_outer_attrs_or_ext(
21+
p: parser,
22+
first_item_attrs: [ast::attribute]) -> attr_or_ext {
23+
let expect_item_next = vec::is_not_empty(first_item_attrs);
24+
if p.token == token::POUND {
25+
let lo = p.span.lo;
26+
if p.look_ahead(1u) == token::LBRACKET {
27+
p.bump();
28+
let first_attr = parse_attribute_naked(p, ast::attr_outer, lo);
29+
ret some(left([first_attr] + parse_outer_attributes(p)));
30+
} else if !(p.look_ahead(1u) == token::LT
31+
|| p.look_ahead(1u) == token::LBRACKET
32+
|| expect_item_next) {
33+
p.bump();
34+
ret some(right(parse_syntax_ext_naked(p, lo)));
35+
} else { ret none; }
36+
} else { ret none; }
37+
}
38+
39+
// Parse attributes that appear before an item
40+
fn parse_outer_attributes(p: parser) -> [ast::attribute] {
41+
let mut attrs: [ast::attribute] = [];
42+
while p.token == token::POUND {
43+
attrs += [parse_attribute(p, ast::attr_outer)];
44+
}
45+
ret attrs;
46+
}
47+
48+
fn parse_attribute(p: parser, style: ast::attr_style) -> ast::attribute {
49+
let lo = p.span.lo;
50+
expect(p, token::POUND);
51+
ret parse_attribute_naked(p, style, lo);
52+
}
53+
54+
fn parse_attribute_naked(p: parser, style: ast::attr_style, lo: uint) ->
55+
ast::attribute {
56+
expect(p, token::LBRACKET);
57+
let meta_item = parse_meta_item(p);
58+
expect(p, token::RBRACKET);
59+
let mut hi = p.span.hi;
60+
ret spanned(lo, hi, {style: style, value: *meta_item});
61+
}
62+
63+
// Parse attributes that appear after the opening of an item, each terminated
64+
// by a semicolon. In addition to a vector of inner attributes, this function
65+
// also returns a vector that may contain the first outer attribute of the
66+
// next item (since we can't know whether the attribute is an inner attribute
67+
// of the containing item or an outer attribute of the first contained item
68+
// until we see the semi).
69+
fn parse_inner_attrs_and_next(p: parser) ->
70+
{inner: [ast::attribute], next: [ast::attribute]} {
71+
let mut inner_attrs: [ast::attribute] = [];
72+
let mut next_outer_attrs: [ast::attribute] = [];
73+
while p.token == token::POUND {
74+
if p.look_ahead(1u) != token::LBRACKET {
75+
// This is an extension
76+
break;
77+
}
78+
let attr = parse_attribute(p, ast::attr_inner);
79+
if p.token == token::SEMI {
80+
p.bump();
81+
inner_attrs += [attr];
82+
} else {
83+
// It's not really an inner attribute
84+
let outer_attr =
85+
spanned(attr.span.lo, attr.span.hi,
86+
{style: ast::attr_outer, value: attr.node.value});
87+
next_outer_attrs += [outer_attr];
88+
break;
89+
}
90+
}
91+
ret {inner: inner_attrs, next: next_outer_attrs};
92+
}
93+
94+
fn parse_meta_item(p: parser) -> @ast::meta_item {
95+
let lo = p.span.lo;
96+
let ident = parse_ident(p);
97+
alt p.token {
98+
token::EQ {
99+
p.bump();
100+
let lit = parse_lit(p);
101+
let mut hi = p.span.hi;
102+
ret @spanned(lo, hi, ast::meta_name_value(ident, lit));
103+
}
104+
token::LPAREN {
105+
let inner_items = parse_meta_seq(p);
106+
let mut hi = p.span.hi;
107+
ret @spanned(lo, hi, ast::meta_list(ident, inner_items));
108+
}
109+
_ {
110+
let mut hi = p.span.hi;
111+
ret @spanned(lo, hi, ast::meta_word(ident));
112+
}
113+
}
114+
}
115+
116+
fn parse_meta_seq(p: parser) -> [@ast::meta_item] {
117+
ret parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
118+
parse_meta_item, p).node;
119+
}
120+
121+
fn parse_optional_meta(p: parser) -> [@ast::meta_item] {
122+
alt p.token { token::LPAREN { ret parse_meta_seq(p); } _ { ret []; } }
123+
}

src/librustsyntax/parse/eval.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import attr;
21
import parser::{parser,
3-
parse_inner_attrs_and_next,
42
parse_mod_items, SOURCE_FILE};
3+
import attr::parse_inner_attrs_and_next;
54

65
export eval_crate_directives_to_mod;
76

@@ -81,7 +80,7 @@ fn parse_companion_mod(cx: ctx, prefix: str, suffix: option<str>)
8180
}
8281

8382
fn cdir_path_opt(id: str, attrs: [ast::attribute]) -> str {
84-
alt attr::first_attr_value_str_by_name(attrs, "path") {
83+
alt ::attr::first_attr_value_str_by_name(attrs, "path") {
8584
some(d) {
8685
ret d;
8786
}

src/librustsyntax/parse/parser.rs

Lines changed: 11 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import ast::spanned;
88
import ast_util::{mk_sp, ident_to_path};
99
import lexer::reader;
1010
import prec::{op_spec, as_prec};
11+
import attr::{parse_outer_attrs_or_ext,
12+
parse_inner_attrs_and_next,
13+
parse_outer_attributes,
14+
parse_optional_meta};
1115

1216
export expect;
1317
export file_type;
@@ -17,14 +21,19 @@ export parser;
1721
export parse_crate_directives;
1822
export parse_crate_mod;
1923
export parse_expr;
20-
export parse_inner_attrs_and_next;
2124
export parse_item;
2225
export parse_mod_items;
23-
export parse_outer_attributes;
2426
export parse_pat;
27+
export parse_seq;
2528
export parse_stmt;
2629
export parse_ty;
2730

31+
export spanned;
32+
export seq_sep;
33+
export parse_lit;
34+
export parse_ident;
35+
export parse_syntax_ext_naked;
36+
2837
// FIXME: #ast expects to find this here but it's actually defined in `parse`
2938
// Fixing this will be easier when we have export decls on individual items --
3039
// then parse can export this publicly, and everything else crate-visibly.
@@ -2385,115 +2394,6 @@ fn parse_item(p: parser, attrs: [ast::attribute]) -> option<@ast::item> {
23852394
else { ret none; }
23862395
}
23872396

2388-
// A type to distingush between the parsing of item attributes or syntax
2389-
// extensions, which both begin with token.POUND
2390-
type attr_or_ext = option<either<[ast::attribute], @ast::expr>>;
2391-
2392-
fn parse_outer_attrs_or_ext(
2393-
p: parser,
2394-
first_item_attrs: [ast::attribute]) -> attr_or_ext {
2395-
let expect_item_next = vec::is_not_empty(first_item_attrs);
2396-
if p.token == token::POUND {
2397-
let lo = p.span.lo;
2398-
if p.look_ahead(1u) == token::LBRACKET {
2399-
p.bump();
2400-
let first_attr = parse_attribute_naked(p, ast::attr_outer, lo);
2401-
ret some(left([first_attr] + parse_outer_attributes(p)));
2402-
} else if !(p.look_ahead(1u) == token::LT
2403-
|| p.look_ahead(1u) == token::LBRACKET
2404-
|| expect_item_next) {
2405-
p.bump();
2406-
ret some(right(parse_syntax_ext_naked(p, lo)));
2407-
} else { ret none; }
2408-
} else { ret none; }
2409-
}
2410-
2411-
// Parse attributes that appear before an item
2412-
fn parse_outer_attributes(p: parser) -> [ast::attribute] {
2413-
let mut attrs: [ast::attribute] = [];
2414-
while p.token == token::POUND {
2415-
attrs += [parse_attribute(p, ast::attr_outer)];
2416-
}
2417-
ret attrs;
2418-
}
2419-
2420-
fn parse_attribute(p: parser, style: ast::attr_style) -> ast::attribute {
2421-
let lo = p.span.lo;
2422-
expect(p, token::POUND);
2423-
ret parse_attribute_naked(p, style, lo);
2424-
}
2425-
2426-
fn parse_attribute_naked(p: parser, style: ast::attr_style, lo: uint) ->
2427-
ast::attribute {
2428-
expect(p, token::LBRACKET);
2429-
let meta_item = parse_meta_item(p);
2430-
expect(p, token::RBRACKET);
2431-
let mut hi = p.span.hi;
2432-
ret spanned(lo, hi, {style: style, value: *meta_item});
2433-
}
2434-
2435-
// Parse attributes that appear after the opening of an item, each terminated
2436-
// by a semicolon. In addition to a vector of inner attributes, this function
2437-
// also returns a vector that may contain the first outer attribute of the
2438-
// next item (since we can't know whether the attribute is an inner attribute
2439-
// of the containing item or an outer attribute of the first contained item
2440-
// until we see the semi).
2441-
fn parse_inner_attrs_and_next(p: parser) ->
2442-
{inner: [ast::attribute], next: [ast::attribute]} {
2443-
let mut inner_attrs: [ast::attribute] = [];
2444-
let mut next_outer_attrs: [ast::attribute] = [];
2445-
while p.token == token::POUND {
2446-
if p.look_ahead(1u) != token::LBRACKET {
2447-
// This is an extension
2448-
break;
2449-
}
2450-
let attr = parse_attribute(p, ast::attr_inner);
2451-
if p.token == token::SEMI {
2452-
p.bump();
2453-
inner_attrs += [attr];
2454-
} else {
2455-
// It's not really an inner attribute
2456-
let outer_attr =
2457-
spanned(attr.span.lo, attr.span.hi,
2458-
{style: ast::attr_outer, value: attr.node.value});
2459-
next_outer_attrs += [outer_attr];
2460-
break;
2461-
}
2462-
}
2463-
ret {inner: inner_attrs, next: next_outer_attrs};
2464-
}
2465-
2466-
fn parse_meta_item(p: parser) -> @ast::meta_item {
2467-
let lo = p.span.lo;
2468-
let ident = parse_ident(p);
2469-
alt p.token {
2470-
token::EQ {
2471-
p.bump();
2472-
let lit = parse_lit(p);
2473-
let mut hi = p.span.hi;
2474-
ret @spanned(lo, hi, ast::meta_name_value(ident, lit));
2475-
}
2476-
token::LPAREN {
2477-
let inner_items = parse_meta_seq(p);
2478-
let mut hi = p.span.hi;
2479-
ret @spanned(lo, hi, ast::meta_list(ident, inner_items));
2480-
}
2481-
_ {
2482-
let mut hi = p.span.hi;
2483-
ret @spanned(lo, hi, ast::meta_word(ident));
2484-
}
2485-
}
2486-
}
2487-
2488-
fn parse_meta_seq(p: parser) -> [@ast::meta_item] {
2489-
ret parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
2490-
parse_meta_item, p).node;
2491-
}
2492-
2493-
fn parse_optional_meta(p: parser) -> [@ast::meta_item] {
2494-
alt p.token { token::LPAREN { ret parse_meta_seq(p); } _ { ret []; } }
2495-
}
2496-
24972397
fn parse_use(p: parser) -> ast::view_item_ {
24982398
let ident = parse_ident(p);
24992399
let metadata = parse_optional_meta(p);

src/librustsyntax/rustsyntax.rc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,14 @@ mod parse {
2828
export comments;
2929
export prec;
3030
export classify;
31+
export attr;
3132

3233
mod eval;
3334
mod lexer;
3435
mod parser;
3536
mod token;
3637
mod comments;
38+
mod attr;
3739

3840
#[doc = "Functions dealing with operator precedence"]
3941
mod prec;

src/rustdoc/attr_parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ mod test {
3838
let parser = parse::new_parser_from_source_str(
3939
parse_sess, [], "-", codemap::fss_none, @source);
4040

41-
parser::parse_outer_attributes(parser)
41+
parse::attr::parse_outer_attributes(parser)
4242
}
4343
}
4444

0 commit comments

Comments
 (0)