syntax: Merge parsing code for structures and variants
This commit is contained in:
@@ -4686,18 +4686,21 @@ impl<'a> Parser<'a> {
|
|||||||
VariantData::Unit(ast::DUMMY_NODE_ID)
|
VariantData::Unit(ast::DUMMY_NODE_ID)
|
||||||
} else {
|
} else {
|
||||||
// If we see: `struct Foo<T> where T: Copy { ... }`
|
// 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>;`
|
// No `where` so: `struct Foo<T>;`
|
||||||
} else if try!(self.eat(&token::Semi) ){
|
} else if try!(self.eat(&token::Semi) ){
|
||||||
VariantData::Unit(ast::DUMMY_NODE_ID)
|
VariantData::Unit(ast::DUMMY_NODE_ID)
|
||||||
// Record-style struct definition
|
// Record-style struct definition
|
||||||
} else if self.token == token::OpenDelim(token::Brace) {
|
} 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.
|
// Tuple-style struct definition with optional where-clause.
|
||||||
} else if self.token == token::OpenDelim(token::Paren) {
|
} else if self.token == token::OpenDelim(token::Paren) {
|
||||||
VariantData::Tuple(try!(self.parse_tuple_struct_body(&mut generics)),
|
let body = VariantData::Tuple(try!(self.parse_tuple_struct_body(true)),
|
||||||
ast::DUMMY_NODE_ID)
|
ast::DUMMY_NODE_ID);
|
||||||
|
generics.where_clause = try!(self.parse_where_clause());
|
||||||
|
try!(self.expect(&token::Semi));
|
||||||
|
body
|
||||||
} else {
|
} else {
|
||||||
let token_str = self.this_token_to_string();
|
let token_str = self.this_token_to_string();
|
||||||
return Err(self.fatal(&format!("expected `where`, `{{`, `(`, or `;` after struct \
|
return Err(self.fatal(&format!("expected `where`, `{{`, `(`, or `;` after struct \
|
||||||
@@ -4707,11 +4710,11 @@ impl<'a> Parser<'a> {
|
|||||||
Ok((class_name, ItemStruct(vdata, generics), None))
|
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();
|
let mut fields = Vec::new();
|
||||||
if try!(self.eat(&token::OpenDelim(token::Brace)) ){
|
if try!(self.eat(&token::OpenDelim(token::Brace)) ){
|
||||||
while self.token != token::CloseDelim(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());
|
try!(self.bump());
|
||||||
@@ -4725,9 +4728,7 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(fields)
|
Ok(fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_tuple_struct_body(&mut self,
|
pub fn parse_tuple_struct_body(&mut self, allow_pub: bool) -> PResult<Vec<StructField>> {
|
||||||
generics: &mut ast::Generics)
|
|
||||||
-> PResult<Vec<StructField>> {
|
|
||||||
// This is the case where we find `struct Foo<T>(T) where T: Copy;`
|
// This is the case where we find `struct Foo<T>(T) where T: Copy;`
|
||||||
// Unit like structs are handled in parse_item_struct function
|
// Unit like structs are handled in parse_item_struct function
|
||||||
let fields = try!(self.parse_unspanned_seq(
|
let fields = try!(self.parse_unspanned_seq(
|
||||||
@@ -4738,7 +4739,9 @@ impl<'a> Parser<'a> {
|
|||||||
let attrs = try!(p.parse_outer_attributes());
|
let attrs = try!(p.parse_outer_attributes());
|
||||||
let lo = p.span.lo;
|
let lo = p.span.lo;
|
||||||
let struct_field_ = ast::StructField_ {
|
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,
|
id: ast::DUMMY_NODE_ID,
|
||||||
ty: try!(p.parse_ty_sum()),
|
ty: try!(p.parse_ty_sum()),
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
@@ -4746,8 +4749,6 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(spanned(lo, p.span.hi, struct_field_))
|
Ok(spanned(lo, p.span.hi, struct_field_))
|
||||||
}));
|
}));
|
||||||
|
|
||||||
generics.where_clause = try!(self.parse_where_clause());
|
|
||||||
try!(self.expect(&token::Semi));
|
|
||||||
Ok(fields)
|
Ok(fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5133,18 +5134,6 @@ impl<'a> Parser<'a> {
|
|||||||
Ok((ident, ItemTy(ty, tps), None))
|
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 '{'
|
/// Parse the part of an "enum" decl following the '{'
|
||||||
fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<EnumDef> {
|
fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<EnumDef> {
|
||||||
let mut variants = Vec::new();
|
let mut variants = Vec::new();
|
||||||
@@ -5157,34 +5146,21 @@ impl<'a> Parser<'a> {
|
|||||||
let struct_def;
|
let struct_def;
|
||||||
let mut disr_expr = None;
|
let mut disr_expr = None;
|
||||||
let ident = try!(self.parse_ident());
|
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.
|
// Parse a struct variant.
|
||||||
all_nullary = false;
|
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)) {
|
} else if self.check(&token::OpenDelim(token::Paren)) {
|
||||||
all_nullary = false;
|
all_nullary = false;
|
||||||
let arg_tys = try!(self.parse_enum_variant_seq(
|
struct_def = VariantData::Tuple(try!(self.parse_tuple_struct_body(false)),
|
||||||
&token::OpenDelim(token::Paren),
|
ast::DUMMY_NODE_ID);
|
||||||
&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);
|
|
||||||
} else if try!(self.eat(&token::Eq) ){
|
} else if try!(self.eat(&token::Eq) ){
|
||||||
disr_expr = Some(try!(self.parse_expr_nopanic()));
|
disr_expr = Some(try!(self.parse_expr_nopanic()));
|
||||||
any_disr = disr_expr.as_ref().map(|expr| expr.span);
|
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 {
|
} else {
|
||||||
struct_def = ast::VariantData::Unit(ast::DUMMY_NODE_ID);
|
struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
let vr = ast::Variant_ {
|
let vr = ast::Variant_ {
|
||||||
|
|||||||
@@ -8,15 +8,13 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// compile-flags: -Z parse-only
|
|
||||||
|
|
||||||
// For style and consistency reasons, non-parametrized enum variants must
|
// For style and consistency reasons, non-parametrized enum variants must
|
||||||
// be used simply as `ident` instead of `ident ()`.
|
// be used simply as `ident` instead of `ident ()`.
|
||||||
// This test-case covers enum declaration.
|
// This test-case covers enum declaration.
|
||||||
|
|
||||||
enum Foo {
|
enum Foo {
|
||||||
Bar(), //~ ERROR nullary enum variants are written with no trailing `( )`
|
Bar(), //~ ERROR empty tuple structs and enum variants are not allowed
|
||||||
Baz(), //~ ERROR nullary enum variants are written with no trailing `( )`
|
Baz(), //~ ERROR empty tuple structs and enum variants are not allowed
|
||||||
Bazar
|
Bazar
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10,9 +10,17 @@
|
|||||||
|
|
||||||
struct TS ( //~ ERROR empty tuple structs and enum variants are not allowed
|
struct TS ( //~ ERROR empty tuple structs and enum variants are not allowed
|
||||||
#[cfg(untrue)]
|
#[cfg(untrue)]
|
||||||
int,
|
i32,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn main() {
|
enum E {
|
||||||
let s = S;
|
TV ( //~ ERROR empty tuple structs and enum variants are not allowed
|
||||||
|
#[cfg(untrue)]
|
||||||
|
i32,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let s = TS;
|
||||||
|
let tv = E::TV;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user