mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-13 23:42:56 +00:00
Refactor 'parse_enum_item' to use 'parse_delim_comma_seq'
This commit is contained in:
parent
7d761fe046
commit
5c34a11324
@ -7,7 +7,7 @@ use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, An
|
|||||||
use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
|
use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
|
||||||
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
|
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
|
||||||
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
|
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::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
|
||||||
use syntax::print::pprust;
|
use syntax::print::pprust;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
@ -1324,85 +1324,65 @@ impl<'a> Parser<'a> {
|
|||||||
let id = self.parse_ident()?;
|
let id = self.parse_ident()?;
|
||||||
let mut generics = self.parse_generics()?;
|
let mut generics = self.parse_generics()?;
|
||||||
generics.where_clause = self.parse_where_clause()?;
|
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.recover_stmt();
|
||||||
self.eat(&token::CloseDelim(token::Brace));
|
|
||||||
e
|
e
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
let enum_definition = EnumDef {
|
||||||
|
variants: variants.into_iter().filter_map(|v| v).collect(),
|
||||||
|
};
|
||||||
Ok((id, ItemKind::Enum(enum_definition, generics), None))
|
Ok((id, ItemKind::Enum(enum_definition, generics), None))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the part of an enum declaration following the `{`.
|
fn parse_enum_item(&mut self) -> PResult<'a, Option<Variant>> {
|
||||||
fn parse_enum_def(&mut self, _generics: &Generics) -> PResult<'a, EnumDef> {
|
let variant_attrs = self.parse_outer_attributes()?;
|
||||||
let mut variants = Vec::new();
|
let vlo = self.token.span;
|
||||||
// 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)?;
|
let vis = self.parse_visibility(FollowedByType::No)?;
|
||||||
if !self.recover_nested_adt_item(kw::Enum)? {
|
if !self.recover_nested_adt_item(kw::Enum)? {
|
||||||
// Item already parsed, we need to skip this variant.
|
return Ok(None)
|
||||||
continue
|
|
||||||
}
|
|
||||||
let ident = self.parse_ident()?;
|
|
||||||
|
|
||||||
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 disr_expr = if self.eat(&token::Eq) {
|
|
||||||
Some(AnonConst {
|
|
||||||
id: DUMMY_NODE_ID,
|
|
||||||
value: self.parse_expr()?,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
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,
|
|
||||||
};
|
|
||||||
variants.push(vr);
|
|
||||||
|
|
||||||
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 ident = self.parse_ident()?;
|
||||||
|
|
||||||
Ok(ast::EnumDef { variants })
|
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 disr_expr = if self.eat(&token::Eq) {
|
||||||
|
Some(AnonConst {
|
||||||
|
id: DUMMY_NODE_ID,
|
||||||
|
value: self.parse_expr()?,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
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(Some(vr))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses `struct Foo { ... }`.
|
/// Parses `struct Foo { ... }`.
|
||||||
@ -1759,7 +1739,6 @@ impl<'a> Parser<'a> {
|
|||||||
let kw_token = self.token.clone();
|
let kw_token = self.token.clone();
|
||||||
let kw_str = pprust::token_to_string(&kw_token);
|
let kw_str = pprust::token_to_string(&kw_token);
|
||||||
let item = self.parse_item()?;
|
let item = self.parse_item()?;
|
||||||
self.eat(&token::Comma);
|
|
||||||
|
|
||||||
self.struct_span_err(
|
self.struct_span_err(
|
||||||
kw_token.span,
|
kw_token.span,
|
||||||
|
@ -805,21 +805,39 @@ impl<'a> Parser<'a> {
|
|||||||
recovered = true;
|
recovered = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Err(mut e) => {
|
Err(mut expect_err) => {
|
||||||
|
let sp = self.sess.source_map().next_point(self.prev_span);
|
||||||
|
let token_str = pprust::token_kind_to_string(t);
|
||||||
|
|
||||||
// Attempt to keep parsing if it was a similar separator.
|
// Attempt to keep parsing if it was a similar separator.
|
||||||
if let Some(ref tokens) = t.similar_tokens() {
|
if let Some(ref tokens) = t.similar_tokens() {
|
||||||
if tokens.contains(&self.token.kind) {
|
if tokens.contains(&self.token.kind) {
|
||||||
self.bump();
|
self.bump();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e.emit();
|
|
||||||
// Attempt to keep parsing if it was an omitted separator.
|
// Attempt to keep parsing if it was an omitted separator.
|
||||||
match f(self) {
|
match f(self) {
|
||||||
Ok(t) => {
|
Ok(t) => {
|
||||||
|
// Parsed successfully, therefore most probably the code only
|
||||||
|
// misses a separator.
|
||||||
|
expect_err
|
||||||
|
.span_suggestion_short(
|
||||||
|
sp,
|
||||||
|
&format!("missing `{}`", token_str),
|
||||||
|
token_str,
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
|
||||||
v.push(t);
|
v.push(t);
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
Err(mut e) => {
|
Err(mut e) => {
|
||||||
|
// Parsing failed, therefore it must be something more serious
|
||||||
|
// than just a missing separator.
|
||||||
|
expect_err.emit();
|
||||||
|
|
||||||
e.cancel();
|
e.cancel();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,10 @@ error: expected one of `)` or `,`, found `label`
|
|||||||
--> $DIR/expected-comma-found-token.rs:9:5
|
--> $DIR/expected-comma-found-token.rs:9:5
|
||||||
|
|
|
|
||||||
LL | message="the message"
|
LL | message="the message"
|
||||||
| - expected one of `)` or `,`
|
| -
|
||||||
|
| |
|
||||||
|
| expected one of `)` or `,`
|
||||||
|
| help: missing `,`
|
||||||
LL | label="the label"
|
LL | label="the label"
|
||||||
| ^^^^^ unexpected token
|
| ^^^^^ unexpected token
|
||||||
|
|
||||||
|
@ -2,7 +2,10 @@ error: expected one of `)`, `,`, `@`, or `|`, found `[`
|
|||||||
--> $DIR/pat-lt-bracket-6.rs:5:19
|
--> $DIR/pat-lt-bracket-6.rs:5:19
|
||||||
|
|
|
|
||||||
LL | let Test(&desc[..]) = x;
|
LL | let Test(&desc[..]) = x;
|
||||||
| ^ expected one of `)`, `,`, `@`, or `|`
|
| ^
|
||||||
|
| |
|
||||||
|
| expected one of `)`, `,`, `@`, or `|`
|
||||||
|
| help: missing `,`
|
||||||
|
|
||||||
error[E0658]: subslice patterns are unstable
|
error[E0658]: subslice patterns are unstable
|
||||||
--> $DIR/pat-lt-bracket-6.rs:5:20
|
--> $DIR/pat-lt-bracket-6.rs:5:20
|
||||||
|
@ -2,7 +2,10 @@ error: expected one of `)`, `,`, `@`, or `|`, found `[`
|
|||||||
--> $DIR/pat-lt-bracket-7.rs:5:16
|
--> $DIR/pat-lt-bracket-7.rs:5:16
|
||||||
|
|
|
|
||||||
LL | for Thing(x[]) in foo {}
|
LL | for Thing(x[]) in foo {}
|
||||||
| ^ expected one of `)`, `,`, `@`, or `|`
|
| ^
|
||||||
|
| |
|
||||||
|
| expected one of `)`, `,`, `@`, or `|`
|
||||||
|
| help: missing `,`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/pat-lt-bracket-7.rs:9:30
|
--> $DIR/pat-lt-bracket-7.rs:9:30
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
enum Test {
|
enum Test {
|
||||||
Very
|
Very //~ HELP missing `,`
|
||||||
//~^ ERROR missing comma
|
Bad(usize) //~ HELP missing `,`
|
||||||
Bad(usize)
|
//~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad`
|
||||||
//~^ ERROR missing comma
|
Stuff { a: usize } //~ HELP missing `,`
|
||||||
Stuff { a: usize }
|
//~^ ERROR expected one of `,`, `=`, or `}`, found `Stuff`
|
||||||
//~^ ERROR missing comma
|
|
||||||
Here
|
Here
|
||||||
|
//~^ ERROR expected one of `,`, `=`, or `}`, found `Here`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,37 @@
|
|||||||
error: missing comma
|
error: expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad`
|
||||||
--> $DIR/recover-enum.rs:3:13
|
--> $DIR/recover-enum.rs:4:9
|
||||||
|
|
|
|
||||||
LL | Very
|
LL | Very
|
||||||
| ^ help: missing comma
|
| -
|
||||||
|
| |
|
||||||
|
| expected one of `(`, `,`, `=`, `{`, or `}`
|
||||||
|
| help: missing `,`
|
||||||
|
LL | Bad(usize)
|
||||||
|
| ^^^ unexpected token
|
||||||
|
|
||||||
error: missing comma
|
error: expected one of `,`, `=`, or `}`, found `Stuff`
|
||||||
--> $DIR/recover-enum.rs:5:19
|
--> $DIR/recover-enum.rs:6:9
|
||||||
|
|
|
|
||||||
LL | Bad(usize)
|
LL | Bad(usize)
|
||||||
| ^ help: missing comma
|
| -
|
||||||
|
| |
|
||||||
|
| expected one of `,`, `=`, or `}`
|
||||||
|
| help: missing `,`
|
||||||
|
LL |
|
||||||
|
LL | Stuff { a: usize }
|
||||||
|
| ^^^^^ unexpected token
|
||||||
|
|
||||||
error: missing comma
|
error: expected one of `,`, `=`, or `}`, found `Here`
|
||||||
--> $DIR/recover-enum.rs:7:27
|
--> $DIR/recover-enum.rs:8:9
|
||||||
|
|
|
|
||||||
LL | Stuff { a: usize }
|
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
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
@ -2,7 +2,10 @@ error: expected one of `,`, `::`, `as`, or `}`, found `.`
|
|||||||
--> $DIR/similar-tokens.rs:7:10
|
--> $DIR/similar-tokens.rs:7:10
|
||||||
|
|
|
|
||||||
LL | use x::{A. B};
|
LL | use x::{A. B};
|
||||||
| ^ expected one of `,`, `::`, `as`, or `}`
|
| ^
|
||||||
|
| |
|
||||||
|
| expected one of `,`, `::`, `as`, or `}`
|
||||||
|
| help: missing `,`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -2,7 +2,9 @@ error: expected one of `)` or `,`, found `(`
|
|||||||
--> $DIR/test.rs:4:26
|
--> $DIR/test.rs:4:26
|
||||||
|
|
|
|
||||||
LL | struct S2(pub((foo)) ());
|
LL | struct S2(pub((foo)) ());
|
||||||
| ^ expected one of `)` or `,`
|
| -^ expected one of `)` or `,`
|
||||||
|
| |
|
||||||
|
| help: missing `,`
|
||||||
|
|
||||||
error[E0412]: cannot find type `foo` in this scope
|
error[E0412]: cannot find type `foo` in this scope
|
||||||
--> $DIR/test.rs:4:20
|
--> $DIR/test.rs:4:20
|
||||||
|
@ -2,7 +2,9 @@ error: expected one of `)` or `,`, found `(`
|
|||||||
--> $DIR/test2.rs:5:26
|
--> $DIR/test2.rs:5:26
|
||||||
|
|
|
|
||||||
LL | struct S3(pub $t ());
|
LL | struct S3(pub $t ());
|
||||||
| ^ expected one of `)` or `,`
|
| -^ expected one of `)` or `,`
|
||||||
|
| |
|
||||||
|
| help: missing `,`
|
||||||
...
|
...
|
||||||
LL | define_struct! { (foo) }
|
LL | define_struct! { (foo) }
|
||||||
| ------------------------ in this macro invocation
|
| ------------------------ in this macro invocation
|
||||||
|
@ -2,7 +2,9 @@ error: expected one of `)` or `,`, found `(`
|
|||||||
--> $DIR/test3.rs:5:27
|
--> $DIR/test3.rs:5:27
|
||||||
|
|
|
|
||||||
LL | struct S3(pub($t) ());
|
LL | struct S3(pub($t) ());
|
||||||
| ^ expected one of `)` or `,`
|
| -^ expected one of `)` or `,`
|
||||||
|
| |
|
||||||
|
| help: missing `,`
|
||||||
...
|
...
|
||||||
LL | define_struct! { foo }
|
LL | define_struct! { foo }
|
||||||
| ---------------------- in this macro invocation
|
| ---------------------- in this macro invocation
|
||||||
|
Loading…
Reference in New Issue
Block a user