Refactor 'parse_enum_item' to use 'parse_delim_comma_seq'

This commit is contained in:
Janusz Marcinkiewicz 2019-11-24 22:33:00 +01:00
parent 7d761fe046
commit 5c34a11324
11 changed files with 127 additions and 95 deletions

View File

@ -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::{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;
@ -1324,85 +1324,65 @@ impl<'a> Parser<'a> {
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;
fn parse_enum_item(&mut self) -> PResult<'a, Option<Variant>> {
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()?;
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;
}
}
let vis = self.parse_visibility(FollowedByType::No)?;
if !self.recover_nested_adt_item(kw::Enum)? {
return Ok(None)
}
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 { ... }`.
@ -1759,7 +1739,6 @@ impl<'a> Parser<'a> {
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,

View File

@ -805,21 +805,39 @@ impl<'a> Parser<'a> {
recovered = true;
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.
if let Some(ref tokens) = t.similar_tokens() {
if tokens.contains(&self.token.kind) {
self.bump();
}
}
e.emit();
// Attempt to keep parsing if it was an omitted separator.
match f(self) {
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);
continue;
},
Err(mut e) => {
// Parsing failed, therefore it must be something more serious
// than just a missing separator.
expect_err.emit();
e.cancel();
break;
}

View File

@ -2,7 +2,10 @@ error: expected one of `)` or `,`, found `label`
--> $DIR/expected-comma-found-token.rs:9:5
|
LL | message="the message"
| - expected one of `)` or `,`
| -
| |
| expected one of `)` or `,`
| help: missing `,`
LL | label="the label"
| ^^^^^ unexpected token

View File

@ -2,7 +2,10 @@ error: expected one of `)`, `,`, `@`, or `|`, found `[`
--> $DIR/pat-lt-bracket-6.rs:5:19
|
LL | let Test(&desc[..]) = x;
| ^ expected one of `)`, `,`, `@`, or `|`
| ^
| |
| expected one of `)`, `,`, `@`, or `|`
| help: missing `,`
error[E0658]: subslice patterns are unstable
--> $DIR/pat-lt-bracket-6.rs:5:20

View File

@ -2,7 +2,10 @@ error: expected one of `)`, `,`, `@`, or `|`, found `[`
--> $DIR/pat-lt-bracket-7.rs:5:16
|
LL | for Thing(x[]) in foo {}
| ^ expected one of `)`, `,`, `@`, or `|`
| ^
| |
| expected one of `)`, `,`, `@`, or `|`
| help: missing `,`
error[E0308]: mismatched types
--> $DIR/pat-lt-bracket-7.rs:9:30

View File

@ -1,11 +1,11 @@
fn main() {
enum Test {
Very
//~^ ERROR missing comma
Bad(usize)
//~^ ERROR missing comma
Stuff { a: usize }
//~^ ERROR missing comma
Very //~ HELP missing `,`
Bad(usize) //~ HELP missing `,`
//~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad`
Stuff { a: usize } //~ HELP missing `,`
//~^ ERROR expected one of `,`, `=`, or `}`, found `Stuff`
Here
//~^ ERROR expected one of `,`, `=`, or `}`, found `Here`
}
}

View File

@ -1,20 +1,37 @@
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

View File

@ -2,7 +2,10 @@ error: expected one of `,`, `::`, `as`, or `}`, found `.`
--> $DIR/similar-tokens.rs:7:10
|
LL | use x::{A. B};
| ^ expected one of `,`, `::`, `as`, or `}`
| ^
| |
| expected one of `,`, `::`, `as`, or `}`
| help: missing `,`
error: aborting due to previous error

View File

@ -2,7 +2,9 @@ error: expected one of `)` or `,`, found `(`
--> $DIR/test.rs:4:26
|
LL | struct S2(pub((foo)) ());
| ^ expected one of `)` or `,`
| -^ expected one of `)` or `,`
| |
| help: missing `,`
error[E0412]: cannot find type `foo` in this scope
--> $DIR/test.rs:4:20

View File

@ -2,7 +2,9 @@ error: expected one of `)` or `,`, found `(`
--> $DIR/test2.rs:5:26
|
LL | struct S3(pub $t ());
| ^ expected one of `)` or `,`
| -^ expected one of `)` or `,`
| |
| help: missing `,`
...
LL | define_struct! { (foo) }
| ------------------------ in this macro invocation

View File

@ -2,7 +2,9 @@ error: expected one of `)` or `,`, found `(`
--> $DIR/test3.rs:5:27
|
LL | struct S3(pub($t) ());
| ^ expected one of `)` or `,`
| -^ expected one of `)` or `,`
| |
| help: missing `,`
...
LL | define_struct! { foo }
| ---------------------- in this macro invocation