Skip to content

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

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 3 commits 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
2 changes: 1 addition & 1 deletion src/libcore/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1906,7 +1906,7 @@ pub mod raw {
}

/// Converts a vector of bytes to a string.
pub pub unsafe fn from_bytes(v: &[const u8]) -> ~str {
pub unsafe fn from_bytes(v: &[const u8]) -> ~str {
do vec::as_const_buf(v) |buf, len| {
from_buf_len(buf, len)
}
Expand Down
86 changes: 60 additions & 26 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,13 @@ 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,
VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED,
IMPORTS_AND_ITEMS_ALLOWED
}

Expand Down Expand Up @@ -2185,7 +2186,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 +2196,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,7 +2264,7 @@ 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);

Expand Down Expand Up @@ -2884,7 +2888,7 @@ 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);
let mut items: ~[@item] = move starting_items;
Expand All @@ -2898,7 +2902,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 +3002,11 @@ 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);
VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED);

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 @@ -3539,28 +3561,35 @@ impl parser {
mode: view_item_parse_mode)
-> {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 items_allowed = match mode {
VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => true,
VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => false
};

let (view_items, items) = (DVec(), DVec());
let restricted_to_imports = match mode {
IMPORTS_AND_ITEMS_ALLOWED => true,
VIEW_ITEMS_AND_ITEMS_ALLOWED |
VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => false
};

let foreign_items_allowed = match mode {
VIEW_ITEMS_AND_FOREIGN_ITEMS_ALLOWED => true,
VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => false
};

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 +3604,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();
}