From a78030fbaa8d4196f7a60851aacfd9f7ed57d7db Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 15 Aug 2012 17:10:23 -0700 Subject: [PATCH] libsyntax: Parse tuple and unit structs --- src/libsyntax/parse/parser.rs | 118 +++++++++++++--------- src/test/run-pass/tuple-struct-trivial.rs | 5 + 2 files changed, 78 insertions(+), 45 deletions(-) create mode 100644 src/test/run-pass/tuple-struct-trivial.rs 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)); + } + } + } + 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) + } } } - } - 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) - } } - } } + 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, diff --git a/src/test/run-pass/tuple-struct-trivial.rs b/src/test/run-pass/tuple-struct-trivial.rs new file mode 100644 index 00000000000..e054f441a12 --- /dev/null +++ b/src/test/run-pass/tuple-struct-trivial.rs @@ -0,0 +1,5 @@ +struct Foo(int, int, int); + +fn main() { +} +