Skip to content

Commit 138dc30

Browse files
committed
libsyntax: Parse "extern mod foo;"
1 parent 3506685 commit 138dc30

File tree

2 files changed

+107
-37
lines changed

2 files changed

+107
-37
lines changed

src/libsyntax/parse/parser.rs

+100-37
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ enum item_or_view_item {
111111
iovi_view_item(@view_item)
112112
}
113113

114+
enum view_item_parse_mode {
115+
VIEW_ITEMS_AND_ITEMS_ALLOWED,
116+
VIEW_ITEMS_ALLOWED,
117+
IMPORTS_AND_ITEMS_ALLOWED
118+
}
119+
114120
/* The expr situation is not as complex as I thought it would be.
115121
The important thing is to make sure that lookahead doesn't balk
116122
at INTERPOLATED tokens */
@@ -2054,7 +2060,7 @@ class parser {
20542060

20552061
let item_attrs = vec::append(first_item_attrs, item_attrs);
20562062

2057-
match self.parse_item_or_view_item(item_attrs) {
2063+
match self.parse_item_or_view_item(item_attrs, true) {
20582064
iovi_item(i) => {
20592065
let mut hi = i.span.hi;
20602066
let decl = @spanned(lo, hi, decl_item(i));
@@ -2141,8 +2147,17 @@ class parser {
21412147
+first_item_attrs: ~[attribute]) -> blk {
21422148
let mut stmts = ~[];
21432149
let mut expr = none;
2144-
let {attrs_remaining, view_items} =
2145-
self.parse_view(first_item_attrs, true);
2150+
2151+
let {attrs_remaining, view_items, items: items} =
2152+
self.parse_items_and_view_items(first_item_attrs,
2153+
IMPORTS_AND_ITEMS_ALLOWED);
2154+
2155+
for items.each |item| {
2156+
let decl = @spanned(item.span.lo, item.span.hi, decl_item(item));
2157+
push(stmts, @spanned(item.span.lo, item.span.hi,
2158+
stmt_decl(decl, self.get_id())));
2159+
}
2160+
21462161
let mut initial_attrs = attrs_remaining;
21472162

21482163
if self.token == token::RBRACE && !vec::is_empty(initial_attrs) {
@@ -2709,9 +2724,11 @@ class parser {
27092724
fn parse_mod_items(term: token::token,
27102725
+first_item_attrs: ~[attribute]) -> _mod {
27112726
// Shouldn't be any view items since we've already parsed an item attr
2712-
let {attrs_remaining, view_items} =
2713-
self.parse_view(first_item_attrs, false);
2714-
let mut items: ~[@item] = ~[];
2727+
let {attrs_remaining, view_items, items: starting_items} =
2728+
self.parse_items_and_view_items(first_item_attrs,
2729+
VIEW_ITEMS_AND_ITEMS_ALLOWED);
2730+
let mut items: ~[@item] = move starting_items;
2731+
27152732
let mut first = true;
27162733
while self.token != term {
27172734
let mut attrs = self.parse_outer_attributes();
@@ -2721,7 +2738,7 @@ class parser {
27212738
}
27222739
debug!("parse_mod_items: parse_item_or_view_item(attrs=%?)",
27232740
attrs);
2724-
match self.parse_item_or_view_item(attrs) {
2741+
match self.parse_item_or_view_item(attrs, true) {
27252742
iovi_item(item) => vec::push(items, item),
27262743
iovi_view_item(view_item) => {
27272744
self.span_fatal(view_item.span, ~"view items must be \
@@ -2797,8 +2814,10 @@ class parser {
27972814
fn parse_foreign_mod_items(+first_item_attrs: ~[attribute]) ->
27982815
foreign_mod {
27992816
// Shouldn't be any view items since we've already parsed an item attr
2800-
let {attrs_remaining, view_items} =
2801-
self.parse_view(first_item_attrs, false);
2817+
let {attrs_remaining, view_items, items: _} =
2818+
self.parse_items_and_view_items(first_item_attrs,
2819+
VIEW_ITEMS_ALLOWED);
2820+
28022821
let mut items: ~[@foreign_item] = ~[];
28032822
let mut initial_attrs = attrs_remaining;
28042823
while self.token != token::RBRACE {
@@ -2813,7 +2832,8 @@ class parser {
28132832

28142833
fn parse_item_foreign_mod(lo: uint,
28152834
visibility: visibility,
2816-
attrs: ~[attribute])
2835+
attrs: ~[attribute],
2836+
items_allowed: bool)
28172837
-> item_or_view_item {
28182838
if self.is_keyword(~"mod") {
28192839
self.expect_keyword(~"mod");
@@ -2823,7 +2843,7 @@ class parser {
28232843
let ident = self.parse_ident();
28242844

28252845
// extern mod { ... }
2826-
if self.eat(token::LBRACE) {
2846+
if items_allowed && self.eat(token::LBRACE) {
28272847
let extra_attrs = self.parse_inner_attrs_and_next();
28282848
let m = self.parse_foreign_mod_items(extra_attrs.next);
28292849
self.expect(token::RBRACE);
@@ -2836,6 +2856,7 @@ class parser {
28362856

28372857
// extern mod foo;
28382858
let metadata = self.parse_optional_meta();
2859+
self.expect(token::SEMI);
28392860
return iovi_view_item(@{
28402861
node: view_item_use(ident, metadata, self.get_id()),
28412862
attrs: attrs,
@@ -3033,7 +3054,8 @@ class parser {
30333054
}
30343055
}
30353056

3036-
fn parse_item_or_view_item(+attrs: ~[attribute]) -> item_or_view_item {
3057+
fn parse_item_or_view_item(+attrs: ~[attribute], items_allowed: bool)
3058+
-> item_or_view_item {
30373059
maybe_whole!{iovi self,nt_item};
30383060
let lo = self.span.lo;
30393061

@@ -3046,25 +3068,26 @@ class parser {
30463068
visibility = inherited;
30473069
}
30483070

3049-
if self.eat_keyword(~"const") {
3071+
if items_allowed && self.eat_keyword(~"const") {
30503072
let (ident, item_, extra_attrs) = self.parse_item_const();
30513073
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
30523074
visibility,
30533075
maybe_append(attrs, extra_attrs)));
3054-
} else if self.is_keyword(~"fn") &&
3076+
} else if items_allowed &&
3077+
self.is_keyword(~"fn") &&
30553078
!self.fn_expr_lookahead(self.look_ahead(1u)) {
30563079
self.bump();
30573080
let (ident, item_, extra_attrs) = self.parse_item_fn(impure_fn);
30583081
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
30593082
visibility,
30603083
maybe_append(attrs, extra_attrs)));
3061-
} else if self.eat_keyword(~"pure") {
3084+
} else if items_allowed && self.eat_keyword(~"pure") {
30623085
self.expect_keyword(~"fn");
30633086
let (ident, item_, extra_attrs) = self.parse_item_fn(pure_fn);
30643087
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
30653088
visibility,
30663089
maybe_append(attrs, extra_attrs)));
3067-
} else if self.is_keyword(~"unsafe")
3090+
} else if items_allowed && self.is_keyword(~"unsafe")
30683091
&& self.look_ahead(1u) != token::LBRACE {
30693092
self.bump();
30703093
self.expect_keyword(~"fn");
@@ -3073,54 +3096,57 @@ class parser {
30733096
visibility,
30743097
maybe_append(attrs, extra_attrs)));
30753098
} else if self.eat_keyword(~"extern") {
3076-
// XXX: "extern mod foo;" syntax as a "use" replacement.
3077-
if self.eat_keyword(~"fn") {
3099+
if items_allowed && self.eat_keyword(~"fn") {
30783100
let (ident, item_, extra_attrs) =
30793101
self.parse_item_fn(extern_fn);
30803102
return iovi_item(self.mk_item(lo, self.last_span.hi, ident,
30813103
item_, visibility,
30823104
maybe_append(attrs,
30833105
extra_attrs)));
30843106
}
3085-
return self.parse_item_foreign_mod(lo, visibility, attrs);
3086-
} else if self.eat_keyword(~"mod") || self.eat_keyword(~"module") {
3107+
return self.parse_item_foreign_mod(lo, visibility, attrs,
3108+
items_allowed);
3109+
} else if items_allowed && (self.eat_keyword(~"mod") ||
3110+
self.eat_keyword(~"module")) {
30873111
let (ident, item_, extra_attrs) = self.parse_item_mod();
30883112
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
30893113
visibility,
30903114
maybe_append(attrs, extra_attrs)));
3091-
} else if self.eat_keyword(~"type") {
3115+
} else if items_allowed && self.eat_keyword(~"type") {
30923116
let (ident, item_, extra_attrs) = self.parse_item_type();
30933117
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
30943118
visibility,
30953119
maybe_append(attrs, extra_attrs)));
3096-
} else if self.eat_keyword(~"enum") {
3120+
} else if items_allowed && self.eat_keyword(~"enum") {
30973121
let (ident, item_, extra_attrs) = self.parse_item_enum();
30983122
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
30993123
visibility,
31003124
maybe_append(attrs, extra_attrs)));
3101-
} else if self.eat_keyword(~"iface") {
3125+
} else if items_allowed && self.eat_keyword(~"iface") {
31023126
self.warn(~"`iface` is deprecated; use `trait`");
31033127
let (ident, item_, extra_attrs) = self.parse_item_trait();
31043128
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
31053129
visibility,
31063130
maybe_append(attrs, extra_attrs)));
3107-
} else if self.eat_keyword(~"trait") {
3131+
} else if items_allowed && self.eat_keyword(~"trait") {
31083132
let (ident, item_, extra_attrs) = self.parse_item_trait();
31093133
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
31103134
visibility,
31113135
maybe_append(attrs, extra_attrs)));
3112-
} else if self.eat_keyword(~"impl") {
3136+
} else if items_allowed && self.eat_keyword(~"impl") {
31133137
let (ident, item_, extra_attrs) = self.parse_item_impl();
31143138
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
31153139
visibility,
31163140
maybe_append(attrs, extra_attrs)));
3117-
} else if self.eat_keyword(~"class") || self.eat_keyword(~"struct") {
3141+
} else if items_allowed &&
3142+
(self.eat_keyword(~"class") || self.eat_keyword(~"struct")) {
31183143
let (ident, item_, extra_attrs) = self.parse_item_class();
31193144
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
31203145
visibility,
31213146
maybe_append(attrs, extra_attrs)));
31223147
} else if self.eat_keyword(~"use") {
31233148
let view_item = self.parse_use();
3149+
self.expect(token::SEMI);
31243150
return iovi_view_item(@{
31253151
node: view_item,
31263152
attrs: attrs,
@@ -3129,6 +3155,7 @@ class parser {
31293155
});
31303156
} else if self.eat_keyword(~"import") {
31313157
let view_paths = self.parse_view_paths();
3158+
self.expect(token::SEMI);
31323159
return iovi_view_item(@{
31333160
node: view_item_import(view_paths),
31343161
attrs: attrs,
@@ -3137,15 +3164,16 @@ class parser {
31373164
});
31383165
} else if self.eat_keyword(~"export") {
31393166
let view_paths = self.parse_view_paths();
3167+
self.expect(token::SEMI);
31403168
return iovi_view_item(@{
31413169
node: view_item_export(view_paths),
31423170
attrs: attrs,
31433171
vis: visibility,
31443172
span: mk_sp(lo, self.last_span.hi)
31453173
});
3146-
} else if !self.is_any_keyword(copy self.token)
3174+
} else if items_allowed && (!self.is_any_keyword(copy self.token)
31473175
&& self.look_ahead(1) == token::NOT
3148-
&& is_plain_ident(self.look_ahead(2)) {
3176+
&& is_plain_ident(self.look_ahead(2))) {
31493177
// item macro.
31503178
let pth = self.parse_path_without_tps();
31513179
self.expect(token::NOT);
@@ -3173,7 +3201,7 @@ class parser {
31733201
}
31743202

31753203
fn parse_item(+attrs: ~[attribute]) -> option<@ast::item> {
3176-
match self.parse_item_or_view_item(attrs) {
3204+
match self.parse_item_or_view_item(attrs, true) {
31773205
iovi_none =>
31783206
none,
31793207
iovi_view_item(_) =>
@@ -3296,18 +3324,53 @@ class parser {
32963324
vis: vis, span: mk_sp(lo, self.last_span.hi)}
32973325
}
32983326

3299-
fn parse_view(+first_item_attrs: ~[attribute],
3300-
only_imports: bool) -> {attrs_remaining: ~[attribute],
3301-
view_items: ~[@view_item]} {
3327+
fn parse_items_and_view_items(+first_item_attrs: ~[attribute],
3328+
mode: view_item_parse_mode)
3329+
-> {attrs_remaining: ~[attribute],
3330+
view_items: ~[@view_item],
3331+
items: ~[@item]} {
33023332
let mut attrs = vec::append(first_item_attrs,
33033333
self.parse_outer_attributes());
3304-
let mut items = ~[];
3305-
while if only_imports { self.is_keyword(~"import") }
3306-
else { self.is_view_item() } {
3307-
vec::push(items, self.parse_view_item(attrs));
3334+
3335+
let items_allowed;
3336+
match mode {
3337+
VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED =>
3338+
items_allowed = true,
3339+
VIEW_ITEMS_ALLOWED =>
3340+
items_allowed = false
3341+
}
3342+
3343+
let (view_items, items) = (dvec(), dvec());
3344+
loop {
3345+
match self.parse_item_or_view_item(attrs, items_allowed) {
3346+
iovi_none =>
3347+
break,
3348+
iovi_view_item(view_item) => {
3349+
match mode {
3350+
VIEW_ITEMS_AND_ITEMS_ALLOWED |
3351+
VIEW_ITEMS_ALLOWED => {}
3352+
IMPORTS_AND_ITEMS_ALLOWED =>
3353+
match view_item.node {
3354+
view_item_import(_) => {}
3355+
view_item_export(_) | view_item_use(*) =>
3356+
self.fatal(~"exports and \"extern mod\" \
3357+
declarations are not \
3358+
allowed here")
3359+
}
3360+
}
3361+
view_items.push(view_item);
3362+
}
3363+
iovi_item(item) => {
3364+
assert items_allowed;
3365+
items.push(item)
3366+
}
3367+
}
33083368
attrs = self.parse_outer_attributes();
33093369
}
3310-
{attrs_remaining: attrs, view_items: items}
3370+
3371+
{attrs_remaining: attrs,
3372+
view_items: vec::from_mut(dvec::unwrap(view_items)),
3373+
items: vec::from_mut(dvec::unwrap(items))}
33113374
}
33123375

33133376
// Parses a source module as a crate
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extern mod std;
2+
use std::map::hashmap;
3+
4+
fn main() {
5+
io::println("Hello world!");
6+
}
7+

0 commit comments

Comments
 (0)