use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
-use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField};
+use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField};
use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
use syntax::print::pprust;
use syntax::ptr::P;
let id = self.parse_ident()?;
let mut generics = self.parse_generics()?;
generics.where_clause = self.parse_where_clause()?;
- self.expect(&token::OpenDelim(token::Brace))?;
- let enum_definition = self.parse_enum_def(&generics).map_err(|e| {
+ let (variants, _) = self.parse_delim_comma_seq(
+ token::Brace,
+ |p| p.parse_enum_item(),
+ ).map_err(|e| {
self.recover_stmt();
- self.eat(&token::CloseDelim(token::Brace));
e
})?;
+
+ let enum_definition = EnumDef {
+ variants: variants.into_iter().filter_map(|v| v).collect(),
+ };
Ok((id, ItemKind::Enum(enum_definition, generics), None))
}
- /// Parses the part of an enum declaration following the `{`.
- fn parse_enum_def(&mut self, _generics: &Generics) -> PResult<'a, EnumDef> {
- let mut variants = Vec::new();
- // FIXME: Consider using `parse_delim_comma_seq`.
- // We could then remove eating comma in `recover_nested_adt_item`.
- while self.token != token::CloseDelim(token::Brace) {
- let variant_attrs = self.parse_outer_attributes()?;
- let vlo = self.token.span;
-
- let vis = self.parse_visibility(FollowedByType::No)?;
- if !self.recover_nested_adt_item(kw::Enum)? {
- // Item already parsed, we need to skip this variant.
- continue
- }
- let ident = self.parse_ident()?;
+ fn parse_enum_item(&mut self) -> PResult<'a, Option<Variant>> {
+ let variant_attrs = self.parse_outer_attributes()?;
+ let vlo = self.token.span;
- let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
- // Parse a struct variant.
- let (fields, recovered) = self.parse_record_struct_body()?;
- VariantData::Struct(fields, recovered)
- } else if self.check(&token::OpenDelim(token::Paren)) {
- VariantData::Tuple(
- self.parse_tuple_struct_body()?,
- DUMMY_NODE_ID,
- )
- } else {
- VariantData::Unit(DUMMY_NODE_ID)
- };
+ let vis = self.parse_visibility(FollowedByType::No)?;
+ if !self.recover_nested_adt_item(kw::Enum)? {
+ return Ok(None)
+ }
+ let ident = self.parse_ident()?;
- let disr_expr = if self.eat(&token::Eq) {
- Some(AnonConst {
- id: DUMMY_NODE_ID,
- value: self.parse_expr()?,
- })
- } else {
- None
- };
+ let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
+ // Parse a struct variant.
+ let (fields, recovered) = self.parse_record_struct_body()?;
+ VariantData::Struct(fields, recovered)
+ } else if self.check(&token::OpenDelim(token::Paren)) {
+ VariantData::Tuple(
+ self.parse_tuple_struct_body()?,
+ DUMMY_NODE_ID,
+ )
+ } else {
+ VariantData::Unit(DUMMY_NODE_ID)
+ };
- let vr = ast::Variant {
- ident,
- vis,
+ let disr_expr = if self.eat(&token::Eq) {
+ Some(AnonConst {
id: DUMMY_NODE_ID,
- attrs: variant_attrs,
- data: struct_def,
- disr_expr,
- span: vlo.to(self.prev_span),
- is_placeholder: false,
- };
- variants.push(vr);
+ value: self.parse_expr()?,
+ })
+ } else {
+ None
+ };
- if !self.eat(&token::Comma) {
- if self.token.is_ident() && !self.token.is_reserved_ident() {
- let sp = self.sess.source_map().next_point(self.prev_span);
- self.struct_span_err(sp, "missing comma")
- .span_suggestion_short(
- sp,
- "missing comma",
- ",".to_owned(),
- Applicability::MaybeIncorrect,
- )
- .emit();
- } else {
- break;
- }
- }
- }
- self.expect(&token::CloseDelim(token::Brace))?;
+ let vr = ast::Variant {
+ ident,
+ vis,
+ id: DUMMY_NODE_ID,
+ attrs: variant_attrs,
+ data: struct_def,
+ disr_expr,
+ span: vlo.to(self.prev_span),
+ is_placeholder: false,
+ };
- Ok(ast::EnumDef { variants })
+ Ok(Some(vr))
}
/// Parses `struct Foo { ... }`.
let kw_token = self.token.clone();
let kw_str = pprust::token_to_string(&kw_token);
let item = self.parse_item()?;
- self.eat(&token::Comma);
self.struct_span_err(
kw_token.span,
-error: missing comma
- --> $DIR/recover-enum.rs:3:13
+error: expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad`
+ --> $DIR/recover-enum.rs:4:9
|
LL | Very
- | ^ help: missing comma
+ | -
+ | |
+ | expected one of `(`, `,`, `=`, `{`, or `}`
+ | help: missing `,`
+LL | Bad(usize)
+ | ^^^ unexpected token
-error: missing comma
- --> $DIR/recover-enum.rs:5:19
+error: expected one of `,`, `=`, or `}`, found `Stuff`
+ --> $DIR/recover-enum.rs:6:9
|
LL | Bad(usize)
- | ^ help: missing comma
+ | -
+ | |
+ | expected one of `,`, `=`, or `}`
+ | help: missing `,`
+LL |
+LL | Stuff { a: usize }
+ | ^^^^^ unexpected token
-error: missing comma
- --> $DIR/recover-enum.rs:7:27
+error: expected one of `,`, `=`, or `}`, found `Here`
+ --> $DIR/recover-enum.rs:8:9
|
LL | Stuff { a: usize }
- | ^ help: missing comma
+ | -
+ | |
+ | expected one of `,`, `=`, or `}`
+ | help: missing `,`
+LL |
+LL | Here
+ | ^^^^ unexpected token
error: aborting due to 3 previous errors