diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0686bad2532..de772b0ff1c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2089,51 +2089,86 @@ class parser { (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 /& of to_str for ~[T] { ... } // impl name/& of to_str for ~[T] { ... } // impl name/& for ~[T] { ... } + // impl ~[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) {