about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-07-24 16:38:24 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-07-24 16:38:24 -0700
commit728d16cfca4d1d12fdabbcc666071810c4d94dc9 (patch)
tree613fe2fb692e2d72adf91a641aae1e42bfd67c33 /src/libsyntax/parse
parent587b0edbbf6c3ac587be98679c4262049aa2a305 (diff)
downloadrust-728d16cfca4d1d12fdabbcc666071810c4d94dc9.tar.gz
rust-728d16cfca4d1d12fdabbcc666071810c4d94dc9.zip
rustc: Parse new-style impl declarations
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser.rs103
1 files changed, 69 insertions, 34 deletions
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 /&<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())
+
+        // 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 {
+                traits = ~[];
             }
-            else if self.is_keyword(~"of") {
-                (none, ~[])
+        } else {
+            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 {
-                let id = self.parse_ident();
+                ident_old = some(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");
+                tps = self.parse_ty_params();
             }
-            if traits.len() > 1 {
-                self.fatal(~"BUG: multiple 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);
+
+            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) {