rustc: Parse new-style impl declarations

This commit is contained in:
Patrick Walton 2012-07-24 16:38:24 -07:00
parent 587b0edbbf
commit 728d16cfca

View File

@ -2089,51 +2089,86 @@ fn parse_item_trait() -> item_info {
(ident, item_trait(tps, meths), none)
}
// Parses three variants (with the region/type params always optional):
// Parses four variants (with the region/type params always optional):
// impl /&<T: copy> of to_str for ~[T] { ... }
// impl name/&<T> of to_str for ~[T] { ... }
// impl name/&<T> for ~[T] { ... }
// impl<T> ~[T] : to_str { ... }
fn parse_item_impl() -> item_info {
fn wrap_path(p: parser, pt: @path) -> @ty {
@{id: p.get_id(), node: ty_path(pt, p.get_id()), span: pt.span}
}
let mut (ident, tps) = {
if self.token == token::LT {
(none, self.parse_ty_params())
} else if self.token == token::BINOP(token::SLASH) {
self.parse_region_param();
(none, self.parse_ty_params())
}
else if self.is_keyword(~"of") {
(none, ~[])
// We do two separate paths here: old-style impls and new-style impls.
// First, parse type parameters if necessary.
let mut tps;
if self.token == token::LT {
tps = self.parse_ty_params();
} else {
tps = ~[];
}
let mut ident;
let ty, traits;
if !self.is_keyword(~"of") &&
!self.token_is_keyword(~"of", self.look_ahead(1)) &&
!self.token_is_keyword(~"for", self.look_ahead(1)) &&
self.look_ahead(1) != token::BINOP(token::SLASH) &&
self.look_ahead(1) != token::LT {
// This is a new-style impl declaration.
ident = @~"__extensions__"; // XXX: clownshoes
// Parse the type.
ty = self.parse_ty(false);
// Parse traits, if necessary.
if self.token == token::COLON {
self.bump();
traits = self.parse_trait_ref_list(token::LBRACE);
} else {
let id = self.parse_ident();
self.parse_region_param();
(some(id), self.parse_ty_params())
}
};
let traits;
if self.eat_keyword(~"of") {
let for_atom = interner::intern(*self.reader.interner(), @~"for");
traits = self.parse_trait_ref_list(token::IDENT(for_atom, false));
if traits.len() >= 1 && option::is_none(ident) {
ident = some(vec::last(traits[0].path.idents));
}
if traits.len() == 0 {
self.fatal(~"BUG: 'of' but no trait");
}
if traits.len() > 1 {
self.fatal(~"BUG: multiple traits");
traits = ~[];
}
} else {
traits = ~[];
};
let ident = alt ident {
some(name) { name }
none { self.expect_keyword(~"of"); fail; }
};
self.expect_keyword(~"for");
let ty = self.parse_ty(false);
let mut ident_old;
if self.token == token::BINOP(token::SLASH) {
self.parse_region_param();
ident_old = none;
tps = self.parse_ty_params();
} else if self.is_keyword(~"of") {
ident_old = none;
} else {
ident_old = some(self.parse_ident());
self.parse_region_param();
tps = self.parse_ty_params();
}
if self.eat_keyword(~"of") {
let for_atom = interner::intern(*self.reader.interner(),
@~"for");
traits = self.parse_trait_ref_list
(token::IDENT(for_atom, false));
if traits.len() >= 1 && option::is_none(ident_old) {
ident_old = some(vec::last(traits[0].path.idents));
}
if traits.len() == 0 {
self.fatal(~"BUG: 'of' but no trait");
}
if traits.len() > 1 {
self.fatal(~"BUG: multiple traits");
}
} else {
traits = ~[];
};
ident = alt ident_old {
some(name) { name }
none { self.expect_keyword(~"of"); fail; }
};
self.expect_keyword(~"for");
ty = self.parse_ty(false);
}
let mut meths = ~[];
self.expect(token::LBRACE);
while !self.eat(token::RBRACE) {