Skip to content

Commit

Permalink
syntax: Merge parsing code for structures and variants
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Nov 9, 2015
1 parent 5b4986f commit e6b14aa
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 50 deletions.
64 changes: 20 additions & 44 deletions src/libsyntax/parse/parser.rs
Expand Up @@ -4686,18 +4686,21 @@ impl<'a> Parser<'a> {
VariantData::Unit(ast::DUMMY_NODE_ID)
} else {
// If we see: `struct Foo<T> where T: Copy { ... }`
VariantData::Struct(try!(self.parse_record_struct_body()), ast::DUMMY_NODE_ID)
VariantData::Struct(try!(self.parse_record_struct_body(true)), ast::DUMMY_NODE_ID)
}
// No `where` so: `struct Foo<T>;`
} else if try!(self.eat(&token::Semi) ){
VariantData::Unit(ast::DUMMY_NODE_ID)
// Record-style struct definition
} else if self.token == token::OpenDelim(token::Brace) {
VariantData::Struct(try!(self.parse_record_struct_body()), ast::DUMMY_NODE_ID)
VariantData::Struct(try!(self.parse_record_struct_body(true)), ast::DUMMY_NODE_ID)
// Tuple-style struct definition with optional where-clause.
} else if self.token == token::OpenDelim(token::Paren) {
VariantData::Tuple(try!(self.parse_tuple_struct_body(&mut generics)),
ast::DUMMY_NODE_ID)
let body = VariantData::Tuple(try!(self.parse_tuple_struct_body(true)),
ast::DUMMY_NODE_ID);
generics.where_clause = try!(self.parse_where_clause());
try!(self.expect(&token::Semi));
body
} else {
let token_str = self.this_token_to_string();
return Err(self.fatal(&format!("expected `where`, `{{`, `(`, or `;` after struct \
Expand All @@ -4707,11 +4710,11 @@ impl<'a> Parser<'a> {
Ok((class_name, ItemStruct(vdata, generics), None))
}

pub fn parse_record_struct_body(&mut self) -> PResult<Vec<StructField>> {
pub fn parse_record_struct_body(&mut self, allow_pub: bool) -> PResult<Vec<StructField>> {
let mut fields = Vec::new();
if try!(self.eat(&token::OpenDelim(token::Brace)) ){
while self.token != token::CloseDelim(token::Brace) {
fields.push(try!(self.parse_struct_decl_field(true)));
fields.push(try!(self.parse_struct_decl_field(allow_pub)));
}

try!(self.bump());
Expand All @@ -4725,9 +4728,7 @@ impl<'a> Parser<'a> {
Ok(fields)
}

pub fn parse_tuple_struct_body(&mut self,
generics: &mut ast::Generics)
-> PResult<Vec<StructField>> {
pub fn parse_tuple_struct_body(&mut self, allow_pub: bool) -> PResult<Vec<StructField>> {
// This is the case where we find `struct Foo<T>(T) where T: Copy;`
// Unit like structs are handled in parse_item_struct function
let fields = try!(self.parse_unspanned_seq(
Expand All @@ -4738,16 +4739,16 @@ impl<'a> Parser<'a> {
let attrs = try!(p.parse_outer_attributes());
let lo = p.span.lo;
let struct_field_ = ast::StructField_ {
kind: UnnamedField(try!(p.parse_visibility())),
kind: UnnamedField (
if allow_pub { try!(p.parse_visibility()) } else { Inherited }
),
id: ast::DUMMY_NODE_ID,
ty: try!(p.parse_ty_sum()),
attrs: attrs,
};
Ok(spanned(lo, p.span.hi, struct_field_))
}));

generics.where_clause = try!(self.parse_where_clause());
try!(self.expect(&token::Semi));
Ok(fields)
}

Expand Down Expand Up @@ -5133,18 +5134,6 @@ impl<'a> Parser<'a> {
Ok((ident, ItemTy(ty, tps), None))
}

/// Parse a structure-like enum variant definition
/// this should probably be renamed or refactored...
fn parse_struct_def(&mut self) -> PResult<VariantData> {
let mut fields: Vec<StructField> = Vec::new();
while self.token != token::CloseDelim(token::Brace) {
fields.push(try!(self.parse_struct_decl_field(false)));
}
try!(self.bump());

Ok(VariantData::Struct(fields, ast::DUMMY_NODE_ID))
}

/// Parse the part of an "enum" decl following the '{'
fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<EnumDef> {
let mut variants = Vec::new();
Expand All @@ -5157,34 +5146,21 @@ impl<'a> Parser<'a> {
let struct_def;
let mut disr_expr = None;
let ident = try!(self.parse_ident());
if try!(self.eat(&token::OpenDelim(token::Brace)) ){
if self.check(&token::OpenDelim(token::Brace)) {
// Parse a struct variant.
all_nullary = false;
struct_def = try!(self.parse_struct_def());
struct_def = VariantData::Struct(try!(self.parse_record_struct_body(false)),
ast::DUMMY_NODE_ID);
} else if self.check(&token::OpenDelim(token::Paren)) {
all_nullary = false;
let arg_tys = try!(self.parse_enum_variant_seq(
&token::OpenDelim(token::Paren),
&token::CloseDelim(token::Paren),
seq_sep_trailing_allowed(token::Comma),
|p| p.parse_ty_sum()
));
let mut fields = Vec::new();
for ty in arg_tys {
fields.push(Spanned { span: ty.span, node: ast::StructField_ {
ty: ty,
kind: ast::UnnamedField(ast::Inherited),
attrs: Vec::new(),
id: ast::DUMMY_NODE_ID,
}});
}
struct_def = ast::VariantData::Tuple(fields, ast::DUMMY_NODE_ID);
struct_def = VariantData::Tuple(try!(self.parse_tuple_struct_body(false)),
ast::DUMMY_NODE_ID);
} else if try!(self.eat(&token::Eq) ){
disr_expr = Some(try!(self.parse_expr_nopanic()));
any_disr = disr_expr.as_ref().map(|expr| expr.span);
struct_def = ast::VariantData::Unit(ast::DUMMY_NODE_ID);
struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
} else {
struct_def = ast::VariantData::Unit(ast::DUMMY_NODE_ID);
struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
}

let vr = ast::Variant_ {
Expand Down
Expand Up @@ -8,15 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags: -Z parse-only

// For style and consistency reasons, non-parametrized enum variants must
// be used simply as `ident` instead of `ident ()`.
// This test-case covers enum declaration.

enum Foo {
Bar(), //~ ERROR nullary enum variants are written with no trailing `( )`
Baz(), //~ ERROR nullary enum variants are written with no trailing `( )`
Bar(), //~ ERROR empty tuple structs and enum variants are not allowed
Baz(), //~ ERROR empty tuple structs and enum variants are not allowed
Bazar
}

Expand Down
12 changes: 10 additions & 2 deletions src/test/compile-fail/issue-16819.rs
Expand Up @@ -10,9 +10,17 @@

struct TS ( //~ ERROR empty tuple structs and enum variants are not allowed
#[cfg(untrue)]
int,
i32,
);

enum E {
TV ( //~ ERROR empty tuple structs and enum variants are not allowed
#[cfg(untrue)]
i32,
)
}

fn main() {
let s = S;
let s = TS;
let tv = E::TV;
}

0 comments on commit e6b14aa

Please sign in to comment.