Skip to content

libsyntax: refactor the parser to consider foreign items as items #3704

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 55 additions & 35 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,10 @@ type item_info = (ident, item_, Option<~[attribute]>);
enum item_or_view_item {
iovi_none,
iovi_item(@item),
iovi_foreign_item(@foreign_item),
iovi_view_item(@view_item)
}

enum view_item_parse_mode {
VIEW_ITEMS_AND_ITEMS_ALLOWED,
VIEW_ITEMS_ALLOWED,
IMPORTS_AND_ITEMS_ALLOWED
}

/* The expr situation is not as complex as I thought it would be.
The important thing is to make sure that lookahead doesn't balk
at INTERPOLATED tokens */
Expand Down Expand Up @@ -2185,7 +2180,7 @@ impl parser {

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

match self.parse_item_or_view_item(item_attrs, true) {
match self.parse_item_or_view_item(item_attrs, true, false) {
iovi_item(i) => {
let mut hi = i.span.hi;
let decl = @spanned(lo, hi, decl_item(i));
Expand All @@ -2195,6 +2190,9 @@ impl parser {
self.span_fatal(vi.span, ~"view items must be declared at \
the top of the block");
}
iovi_foreign_item(_) => {
self.fatal(~"foreign items are not allowed here");
}
iovi_none() => { /* fallthrough */ }
}

Expand Down Expand Up @@ -2260,9 +2258,11 @@ impl parser {
let mut stmts = ~[];
let mut expr = None;

let {attrs_remaining, view_items, items: items} =
let {attrs_remaining, view_items, items: items, _} =
self.parse_items_and_view_items(first_item_attrs,
IMPORTS_AND_ITEMS_ALLOWED);
true, // items_allowed
false, // foreign_items_allowed
true); // restrict_to_imports

for items.each |item| {
let decl = @spanned(item.span.lo, item.span.hi, decl_item(*item));
Expand Down Expand Up @@ -2884,9 +2884,11 @@ impl parser {
fn parse_mod_items(term: token::token,
+first_item_attrs: ~[attribute]) -> _mod {
// Shouldn't be any view items since we've already parsed an item attr
let {attrs_remaining, view_items, items: starting_items} =
let {attrs_remaining, view_items, items: starting_items, _} =
self.parse_items_and_view_items(first_item_attrs,
VIEW_ITEMS_AND_ITEMS_ALLOWED);
true, // items_allowed
false, // foreign_items_allowed
false); // restrict_to_imports
let mut items: ~[@item] = move starting_items;

let mut first = true;
Expand All @@ -2898,7 +2900,7 @@ impl parser {
}
debug!("parse_mod_items: parse_item_or_view_item(attrs=%?)",
attrs);
match self.parse_item_or_view_item(attrs, true) {
match self.parse_item_or_view_item(attrs, true, false) {
iovi_item(item) => items.push(item),
iovi_view_item(view_item) => {
self.span_fatal(view_item.span, ~"view items must be \
Expand Down Expand Up @@ -2998,11 +3000,13 @@ impl parser {
+first_item_attrs: ~[attribute]) ->
foreign_mod {
// Shouldn't be any view items since we've already parsed an item attr
let {attrs_remaining, view_items, items: _} =
let {attrs_remaining, view_items, items: _, foreign_items} =
self.parse_items_and_view_items(first_item_attrs,
VIEW_ITEMS_ALLOWED);
false, // items_allowed
true, // foreign_items_allowed
false); // restrict_to_imports

let mut items: ~[@foreign_item] = ~[];
let mut items: ~[@foreign_item] = move foreign_items;
let mut initial_attrs = attrs_remaining;
while self.token != token::RBRACE {
let attrs = vec::append(initial_attrs,
Expand All @@ -3011,7 +3015,7 @@ impl parser {
items.push(self.parse_foreign_item(attrs));
}
return {sort: sort, view_items: view_items,
items: items};
items: items};
}

fn parse_item_foreign_mod(lo: uint,
Expand Down Expand Up @@ -3276,8 +3280,11 @@ impl parser {
}
}

fn parse_item_or_view_item(+attrs: ~[attribute], items_allowed: bool)
fn parse_item_or_view_item(+attrs: ~[attribute], items_allowed: bool,
foreign_items_allowed: bool)
-> item_or_view_item {
assert items_allowed != foreign_items_allowed;

maybe_whole!(iovi self,nt_item);
let lo = self.span.lo;

Expand All @@ -3295,6 +3302,9 @@ impl parser {
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
} else if foreign_items_allowed && self.is_keyword(~"const") {
let item = self.parse_item_foreign_const(visibility, attrs);
return iovi_foreign_item(item);
} else if items_allowed &&
self.is_keyword(~"fn") &&
!self.fn_expr_lookahead(self.look_ahead(1u)) {
Expand All @@ -3309,6 +3319,10 @@ impl parser {
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
} else if foreign_items_allowed &&
(self.is_keyword(~"fn") || self.is_keyword(~"pure")) {
let item = self.parse_item_foreign_fn(visibility, attrs);
return iovi_foreign_item(item);
} else if items_allowed && self.is_keyword(~"unsafe")
&& self.look_ahead(1u) != token::LBRACE {
self.bump();
Expand Down Expand Up @@ -3395,16 +3409,24 @@ impl parser {
return iovi_item(self.mk_item(lo, self.last_span.hi, id, item_,
visibility, attrs));
} else {
if visibility != inherited {
let mut s = ~"unmatched visibility `";
s += if visibility == public { ~"pub" } else { ~"priv" };
s += ~"`";
self.span_fatal(copy self.last_span, s);
}
return iovi_none;
};
}

fn parse_item(+attrs: ~[attribute]) -> Option<@ast::item> {
match self.parse_item_or_view_item(attrs, true) {
match self.parse_item_or_view_item(attrs, true, false) {
iovi_none =>
None,
iovi_view_item(_) =>
self.fatal(~"view items are not allowed here"),
iovi_foreign_item(_) =>
self.fatal(~"foreign items are not allowed here"),
iovi_item(item) =>
Some(item)
}
Expand Down Expand Up @@ -3536,31 +3558,24 @@ impl parser {
}

fn parse_items_and_view_items(+first_item_attrs: ~[attribute],
mode: view_item_parse_mode)
items_allowed: bool,
foreign_items_allowed: bool,
restricted_to_imports: bool)
-> {attrs_remaining: ~[attribute],
view_items: ~[@view_item],
items: ~[@item]} {
items: ~[@item],
foreign_items: ~[@foreign_item]} {
let mut attrs = vec::append(first_item_attrs,
self.parse_outer_attributes());

let items_allowed;
match mode {
VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED =>
items_allowed = true,
VIEW_ITEMS_ALLOWED =>
items_allowed = false
}

let (view_items, items) = (DVec(), DVec());
let (view_items, items, foreign_items) = (DVec(), DVec(), DVec());
loop {
match self.parse_item_or_view_item(attrs, items_allowed) {
match self.parse_item_or_view_item(attrs, items_allowed,
foreign_items_allowed) {
iovi_none =>
break,
iovi_view_item(view_item) => {
match mode {
VIEW_ITEMS_AND_ITEMS_ALLOWED |
VIEW_ITEMS_ALLOWED => {}
IMPORTS_AND_ITEMS_ALLOWED =>
if restricted_to_imports {
match view_item.node {
view_item_import(_) => {}
view_item_export(_) | view_item_use(*) =>
Expand All @@ -3575,13 +3590,18 @@ impl parser {
assert items_allowed;
items.push(item)
}
iovi_foreign_item(foreign_item) => {
assert foreign_items_allowed;
foreign_items.push(foreign_item);
}
}
attrs = self.parse_outer_attributes();
}

{attrs_remaining: attrs,
view_items: dvec::unwrap(move view_items),
items: dvec::unwrap(move items)}
items: dvec::unwrap(move items),
foreign_items: dvec::unwrap(move foreign_items)}
}

// Parses a source module as a crate
Expand Down
4 changes: 4 additions & 0 deletions src/test/compile-fail/duplicate-visibility.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// error-pattern:unmatched visibility `pub`
extern {
pub pub fn foo();
}