From 5c34a11324b060b0492eb390c7e9b2abc9eb61a4 Mon Sep 17 00:00:00 2001 From: Janusz Marcinkiewicz Date: Sun, 24 Nov 2019 22:33:00 +0100 Subject: [PATCH] Refactor 'parse_enum_item' to use 'parse_delim_comma_seq' --- src/librustc_parse/parser/item.rs | 115 +++++++----------- src/librustc_parse/parser/mod.rs | 22 +++- .../expected-comma-found-token.stderr | 5 +- src/test/ui/parser/pat-lt-bracket-6.stderr | 5 +- src/test/ui/parser/pat-lt-bracket-7.stderr | 5 +- src/test/ui/parser/recover-enum.rs | 12 +- src/test/ui/parser/recover-enum.stderr | 35 ++++-- src/test/ui/similar-tokens.stderr | 5 +- .../ui/tuple/tuple-struct-fields/test.stderr | 4 +- .../ui/tuple/tuple-struct-fields/test2.stderr | 4 +- .../ui/tuple/tuple-struct-fields/test3.stderr | 4 +- 11 files changed, 124 insertions(+), 92 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 2c9d4004226..7569269921a 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -7,7 +7,7 @@ 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 @@ fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> { 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> { + 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 { ... }`. @@ -1759,7 +1739,6 @@ fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> { 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, diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index d810117662c..ea7673767d0 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -805,21 +805,39 @@ fn parse_seq_to_before_tokens( 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; } diff --git a/src/test/ui/on-unimplemented/expected-comma-found-token.stderr b/src/test/ui/on-unimplemented/expected-comma-found-token.stderr index 738bf7c6c6b..2e1d484e05a 100644 --- a/src/test/ui/on-unimplemented/expected-comma-found-token.stderr +++ b/src/test/ui/on-unimplemented/expected-comma-found-token.stderr @@ -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 diff --git a/src/test/ui/parser/pat-lt-bracket-6.stderr b/src/test/ui/parser/pat-lt-bracket-6.stderr index cb8bf62a8fe..fe9603cb57f 100644 --- a/src/test/ui/parser/pat-lt-bracket-6.stderr +++ b/src/test/ui/parser/pat-lt-bracket-6.stderr @@ -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 diff --git a/src/test/ui/parser/pat-lt-bracket-7.stderr b/src/test/ui/parser/pat-lt-bracket-7.stderr index aa115659d47..004dcfb2a7b 100644 --- a/src/test/ui/parser/pat-lt-bracket-7.stderr +++ b/src/test/ui/parser/pat-lt-bracket-7.stderr @@ -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 diff --git a/src/test/ui/parser/recover-enum.rs b/src/test/ui/parser/recover-enum.rs index 331bfff84f1..08dd939e2c0 100644 --- a/src/test/ui/parser/recover-enum.rs +++ b/src/test/ui/parser/recover-enum.rs @@ -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` } } diff --git a/src/test/ui/parser/recover-enum.stderr b/src/test/ui/parser/recover-enum.stderr index 81c7ae337db..a2b650e4f4e 100644 --- a/src/test/ui/parser/recover-enum.stderr +++ b/src/test/ui/parser/recover-enum.stderr @@ -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 diff --git a/src/test/ui/similar-tokens.stderr b/src/test/ui/similar-tokens.stderr index d3d5b4a6d1e..35a2fe79d5e 100644 --- a/src/test/ui/similar-tokens.stderr +++ b/src/test/ui/similar-tokens.stderr @@ -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 diff --git a/src/test/ui/tuple/tuple-struct-fields/test.stderr b/src/test/ui/tuple/tuple-struct-fields/test.stderr index 94f39f3b9f1..bfa0b32fd45 100644 --- a/src/test/ui/tuple/tuple-struct-fields/test.stderr +++ b/src/test/ui/tuple/tuple-struct-fields/test.stderr @@ -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 diff --git a/src/test/ui/tuple/tuple-struct-fields/test2.stderr b/src/test/ui/tuple/tuple-struct-fields/test2.stderr index 9a64ed97ae1..d924c351439 100644 --- a/src/test/ui/tuple/tuple-struct-fields/test2.stderr +++ b/src/test/ui/tuple/tuple-struct-fields/test2.stderr @@ -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 diff --git a/src/test/ui/tuple/tuple-struct-fields/test3.stderr b/src/test/ui/tuple/tuple-struct-fields/test3.stderr index 89ae784882d..50cac6c179e 100644 --- a/src/test/ui/tuple/tuple-struct-fields/test3.stderr +++ b/src/test/ui/tuple/tuple-struct-fields/test3.stderr @@ -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 -- 2.44.0