about summary refs log tree commit diff
path: root/src/libsyntax/parse/parser.rs
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-08-15 17:10:23 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-08-15 17:11:13 -0700
commita78030fbaa8d4196f7a60851aacfd9f7ed57d7db (patch)
treed0cdc1b8f696aa131b669159e83f958a9cf0b791 /src/libsyntax/parse/parser.rs
parent913f7bdae744f88110eaca73fb28e4b8e987456c (diff)
downloadrust-a78030fbaa8d4196f7a60851aacfd9f7ed57d7db.tar.gz
rust-a78030fbaa8d4196f7a60851aacfd9f7ed57d7db.zip
libsyntax: Parse tuple and unit structs
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
-rw-r--r--src/libsyntax/parse/parser.rs116
1 files changed, 72 insertions, 44 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 0f1387069ca..9407f904bf7 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -53,10 +53,11 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
              ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_param_bound,
              ty_path, ty_ptr, ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq,
              ty_vec, ty_fixed_length, tuple_variant_kind, unchecked_blk, uniq,
-             unsafe_blk, unsafe_fn, variant, view_item, view_item_,
-             view_item_export, view_item_import, view_item_use, view_path,
-             view_path_glob, view_path_list, view_path_simple, visibility,
-             vstore, vstore_box, vstore_fixed, vstore_slice, vstore_uniq};
+             unnamed_field, unsafe_blk, unsafe_fn, variant, view_item,
+             view_item_, view_item_export, view_item_import, view_item_use,
+             view_path, view_path_glob, view_path_list, view_path_simple,
+             visibility, vstore, vstore_box, vstore_fixed, vstore_slice,
+             vstore_uniq};
 
 export file_type;
 export parser;
@@ -2563,53 +2564,81 @@ class parser {
         let traits : ~[@trait_ref] = if self.eat(token::COLON)
             { self.parse_trait_ref_list(token::LBRACE) }
         else { ~[] };
-        self.expect(token::LBRACE);
-        let mut fields: ~[@struct_field] = ~[];
+
+        let mut fields: ~[@struct_field];
         let mut methods: ~[@method] = ~[];
+        let mut the_ctor: option<(fn_decl, ~[attribute], blk, codemap::span)>
+            = none;
+        let mut the_dtor: option<(blk, ~[attribute], codemap::span)> = none;
         let ctor_id = self.get_id();
-        let mut the_ctor : option<(fn_decl, ~[attribute], blk,
-                                   codemap::span)> = none;
-        let mut the_dtor : option<(blk, ~[attribute], codemap::span)> = none;
-        while self.token != token::RBRACE {
-            match self.parse_class_item(class_path) {
-              ctor_decl(a_fn_decl, attrs, blk, s) => {
-                  match the_ctor {
-                    some((_, _, _, s_first)) => {
-                      self.span_note(s, #fmt("Duplicate constructor \
-                                   declaration for class %s", *class_name));
-                       self.span_fatal(copy s_first, ~"First constructor \
-                                                      declared here");
-                    }
-                    none    => {
-                      the_ctor = some((a_fn_decl, attrs, blk, s));
-                    }
+
+        if self.eat(token::LBRACE) {
+            // It's a record-like struct.
+            fields = ~[];
+            while self.token != token::RBRACE {
+                match self.parse_class_item(class_path) {
+                  ctor_decl(a_fn_decl, attrs, blk, s) => {
+                      match the_ctor {
+                        some((_, _, _, s_first)) => {
+                          self.span_note(s, #fmt("Duplicate constructor \
+                                       declaration for class %s", *class_name));
+                           self.span_fatal(copy s_first, ~"First constructor \
+                                                          declared here");
+                        }
+                        none    => {
+                          the_ctor = some((a_fn_decl, attrs, blk, s));
+                        }
+                      }
                   }
-              }
-              dtor_decl(blk, attrs, s) => {
-                  match the_dtor {
-                    some((_, _, s_first)) => {
-                      self.span_note(s, #fmt("Duplicate destructor \
-                                    declaration for class %s", *class_name));
-                      self.span_fatal(copy s_first, ~"First destructor \
-                                                      declared here");
-                    }
-                    none => {
-                      the_dtor = some((blk, attrs, s));
-                    }
+                  dtor_decl(blk, attrs, s) => {
+                      match the_dtor {
+                        some((_, _, s_first)) => {
+                          self.span_note(s, #fmt("Duplicate destructor \
+                                        declaration for class %s", *class_name));
+                          self.span_fatal(copy s_first, ~"First destructor \
+                                                          declared here");
+                        }
+                        none => {
+                          the_dtor = some((blk, attrs, s));
+                        }
+                      }
                   }
-              }
-              members(mms) => {
-                for mms.each |mm| {
-                    match mm {
-                        @field_member(struct_field) =>
-                            vec::push(fields, struct_field),
-                        @method_member(the_method_member) =>
-                            vec::push(methods, the_method_member)
+                  members(mms) => {
+                    for mms.each |mm| {
+                        match mm {
+                            @field_member(struct_field) =>
+                                vec::push(fields, struct_field),
+                            @method_member(the_method_member) =>
+                                vec::push(methods, the_method_member)
+                        }
                     }
+                  }
                 }
-              }
             }
+            self.bump();
+        } else if self.token == token::LPAREN {
+            // It's a tuple-like struct.
+            fields = do self.parse_unspanned_seq(token::LPAREN, token::RPAREN,
+                                                 seq_sep_trailing_allowed
+                                                    (token::COMMA)) |p| {
+                let lo = p.span.lo;
+                let struct_field_ = {
+                    kind: unnamed_field,
+                    id: self.get_id(),
+                    ty: p.parse_ty(false)
+                };
+                @spanned(lo, p.span.hi, struct_field_)
+            };
+            self.expect(token::SEMI);
+        } else if self.eat(token::SEMI) {
+            // It's a unit-like struct.
+            fields = ~[];
+        } else {
+            self.fatal(fmt!("expected `{`, `(`, or `;` after struct name \
+                             but found `%s`",
+                            token_to_str(self.reader, self.token)));
         }
+
         let actual_dtor = do option::map(the_dtor) |dtor| {
             let (d_body, d_attrs, d_s) = dtor;
             {node: {id: self.get_id(),
@@ -2617,7 +2646,6 @@ class parser {
                     self_id: self.get_id(),
                     body: d_body},
              span: d_s}};
-        self.bump();
         match the_ctor {
           some((ct_d, ct_attrs, ct_b, ct_s)) => {
             (class_name,