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::{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,29 +1324,28 @@ 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 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 variant_attrs = self.parse_outer_attributes()?;
let vlo = self.token.span; 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 ident = self.parse_ident()?;
@ -1382,27 +1381,8 @@ impl<'a> Parser<'a> {
span: vlo.to(self.prev_span), span: vlo.to(self.prev_span),
is_placeholder: false, is_placeholder: false,
}; };
variants.push(vr);
if !self.eat(&token::Comma) { Ok(Some(vr))
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))?;
Ok(ast::EnumDef { variants })
} }
/// 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,

View File

@ -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;
} }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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`
} }
} }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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