Skip to content

Commit 5c34a11

Browse files
committed
Refactor 'parse_enum_item' to use 'parse_delim_comma_seq'
1 parent 7d761fe commit 5c34a11

File tree

11 files changed

+124
-92
lines changed

11 files changed

+124
-92
lines changed

src/librustc_parse/parser/item.rs

+47-68
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, An
77
use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
88
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
99
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
10-
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField};
10+
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField};
1111
use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
1212
use syntax::print::pprust;
1313
use syntax::ptr::P;
@@ -1324,85 +1324,65 @@ impl<'a> Parser<'a> {
13241324
let id = self.parse_ident()?;
13251325
let mut generics = self.parse_generics()?;
13261326
generics.where_clause = self.parse_where_clause()?;
1327-
self.expect(&token::OpenDelim(token::Brace))?;
13281327

1329-
let enum_definition = self.parse_enum_def(&generics).map_err(|e| {
1328+
let (variants, _) = self.parse_delim_comma_seq(
1329+
token::Brace,
1330+
|p| p.parse_enum_item(),
1331+
).map_err(|e| {
13301332
self.recover_stmt();
1331-
self.eat(&token::CloseDelim(token::Brace));
13321333
e
13331334
})?;
1335+
1336+
let enum_definition = EnumDef {
1337+
variants: variants.into_iter().filter_map(|v| v).collect(),
1338+
};
13341339
Ok((id, ItemKind::Enum(enum_definition, generics), None))
13351340
}
13361341

1337-
/// Parses the part of an enum declaration following the `{`.
1338-
fn parse_enum_def(&mut self, _generics: &Generics) -> PResult<'a, EnumDef> {
1339-
let mut variants = Vec::new();
1340-
// FIXME: Consider using `parse_delim_comma_seq`.
1341-
// We could then remove eating comma in `recover_nested_adt_item`.
1342-
while self.token != token::CloseDelim(token::Brace) {
1343-
let variant_attrs = self.parse_outer_attributes()?;
1344-
let vlo = self.token.span;
1345-
1346-
let vis = self.parse_visibility(FollowedByType::No)?;
1347-
if !self.recover_nested_adt_item(kw::Enum)? {
1348-
// Item already parsed, we need to skip this variant.
1349-
continue
1350-
}
1351-
let ident = self.parse_ident()?;
1342+
fn parse_enum_item(&mut self) -> PResult<'a, Option<Variant>> {
1343+
let variant_attrs = self.parse_outer_attributes()?;
1344+
let vlo = self.token.span;
13521345

1353-
let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
1354-
// Parse a struct variant.
1355-
let (fields, recovered) = self.parse_record_struct_body()?;
1356-
VariantData::Struct(fields, recovered)
1357-
} else if self.check(&token::OpenDelim(token::Paren)) {
1358-
VariantData::Tuple(
1359-
self.parse_tuple_struct_body()?,
1360-
DUMMY_NODE_ID,
1361-
)
1362-
} else {
1363-
VariantData::Unit(DUMMY_NODE_ID)
1364-
};
1346+
let vis = self.parse_visibility(FollowedByType::No)?;
1347+
if !self.recover_nested_adt_item(kw::Enum)? {
1348+
return Ok(None)
1349+
}
1350+
let ident = self.parse_ident()?;
13651351

1366-
let disr_expr = if self.eat(&token::Eq) {
1367-
Some(AnonConst {
1368-
id: DUMMY_NODE_ID,
1369-
value: self.parse_expr()?,
1370-
})
1371-
} else {
1372-
None
1373-
};
1352+
let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
1353+
// Parse a struct variant.
1354+
let (fields, recovered) = self.parse_record_struct_body()?;
1355+
VariantData::Struct(fields, recovered)
1356+
} else if self.check(&token::OpenDelim(token::Paren)) {
1357+
VariantData::Tuple(
1358+
self.parse_tuple_struct_body()?,
1359+
DUMMY_NODE_ID,
1360+
)
1361+
} else {
1362+
VariantData::Unit(DUMMY_NODE_ID)
1363+
};
13741364

1375-
let vr = ast::Variant {
1376-
ident,
1377-
vis,
1365+
let disr_expr = if self.eat(&token::Eq) {
1366+
Some(AnonConst {
13781367
id: DUMMY_NODE_ID,
1379-
attrs: variant_attrs,
1380-
data: struct_def,
1381-
disr_expr,
1382-
span: vlo.to(self.prev_span),
1383-
is_placeholder: false,
1384-
};
1385-
variants.push(vr);
1368+
value: self.parse_expr()?,
1369+
})
1370+
} else {
1371+
None
1372+
};
13861373

1387-
if !self.eat(&token::Comma) {
1388-
if self.token.is_ident() && !self.token.is_reserved_ident() {
1389-
let sp = self.sess.source_map().next_point(self.prev_span);
1390-
self.struct_span_err(sp, "missing comma")
1391-
.span_suggestion_short(
1392-
sp,
1393-
"missing comma",
1394-
",".to_owned(),
1395-
Applicability::MaybeIncorrect,
1396-
)
1397-
.emit();
1398-
} else {
1399-
break;
1400-
}
1401-
}
1402-
}
1403-
self.expect(&token::CloseDelim(token::Brace))?;
1374+
let vr = ast::Variant {
1375+
ident,
1376+
vis,
1377+
id: DUMMY_NODE_ID,
1378+
attrs: variant_attrs,
1379+
data: struct_def,
1380+
disr_expr,
1381+
span: vlo.to(self.prev_span),
1382+
is_placeholder: false,
1383+
};
14041384

1405-
Ok(ast::EnumDef { variants })
1385+
Ok(Some(vr))
14061386
}
14071387

14081388
/// Parses `struct Foo { ... }`.
@@ -1759,7 +1739,6 @@ impl<'a> Parser<'a> {
17591739
let kw_token = self.token.clone();
17601740
let kw_str = pprust::token_to_string(&kw_token);
17611741
let item = self.parse_item()?;
1762-
self.eat(&token::Comma);
17631742

17641743
self.struct_span_err(
17651744
kw_token.span,

src/librustc_parse/parser/mod.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -805,21 +805,39 @@ impl<'a> Parser<'a> {
805805
recovered = true;
806806
break;
807807
}
808-
Err(mut e) => {
808+
Err(mut expect_err) => {
809+
let sp = self.sess.source_map().next_point(self.prev_span);
810+
let token_str = pprust::token_kind_to_string(t);
811+
809812
// Attempt to keep parsing if it was a similar separator.
810813
if let Some(ref tokens) = t.similar_tokens() {
811814
if tokens.contains(&self.token.kind) {
812815
self.bump();
813816
}
814817
}
815-
e.emit();
818+
816819
// Attempt to keep parsing if it was an omitted separator.
817820
match f(self) {
818821
Ok(t) => {
822+
// Parsed successfully, therefore most probably the code only
823+
// misses a separator.
824+
expect_err
825+
.span_suggestion_short(
826+
sp,
827+
&format!("missing `{}`", token_str),
828+
token_str,
829+
Applicability::MaybeIncorrect,
830+
)
831+
.emit();
832+
819833
v.push(t);
820834
continue;
821835
},
822836
Err(mut e) => {
837+
// Parsing failed, therefore it must be something more serious
838+
// than just a missing separator.
839+
expect_err.emit();
840+
823841
e.cancel();
824842
break;
825843
}

src/test/ui/on-unimplemented/expected-comma-found-token.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error: expected one of `)` or `,`, found `label`
22
--> $DIR/expected-comma-found-token.rs:9:5
33
|
44
LL | message="the message"
5-
| - expected one of `)` or `,`
5+
| -
6+
| |
7+
| expected one of `)` or `,`
8+
| help: missing `,`
69
LL | label="the label"
710
| ^^^^^ unexpected token
811

src/test/ui/parser/pat-lt-bracket-6.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error: expected one of `)`, `,`, `@`, or `|`, found `[`
22
--> $DIR/pat-lt-bracket-6.rs:5:19
33
|
44
LL | let Test(&desc[..]) = x;
5-
| ^ expected one of `)`, `,`, `@`, or `|`
5+
| ^
6+
| |
7+
| expected one of `)`, `,`, `@`, or `|`
8+
| help: missing `,`
69

710
error[E0658]: subslice patterns are unstable
811
--> $DIR/pat-lt-bracket-6.rs:5:20

src/test/ui/parser/pat-lt-bracket-7.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error: expected one of `)`, `,`, `@`, or `|`, found `[`
22
--> $DIR/pat-lt-bracket-7.rs:5:16
33
|
44
LL | for Thing(x[]) in foo {}
5-
| ^ expected one of `)`, `,`, `@`, or `|`
5+
| ^
6+
| |
7+
| expected one of `)`, `,`, `@`, or `|`
8+
| help: missing `,`
69

710
error[E0308]: mismatched types
811
--> $DIR/pat-lt-bracket-7.rs:9:30

src/test/ui/parser/recover-enum.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
fn main() {
22
enum Test {
3-
Very
4-
//~^ ERROR missing comma
5-
Bad(usize)
6-
//~^ ERROR missing comma
7-
Stuff { a: usize }
8-
//~^ ERROR missing comma
3+
Very //~ HELP missing `,`
4+
Bad(usize) //~ HELP missing `,`
5+
//~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad`
6+
Stuff { a: usize } //~ HELP missing `,`
7+
//~^ ERROR expected one of `,`, `=`, or `}`, found `Stuff`
98
Here
9+
//~^ ERROR expected one of `,`, `=`, or `}`, found `Here`
1010
}
1111
}
+26-9
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,37 @@
1-
error: missing comma
2-
--> $DIR/recover-enum.rs:3:13
1+
error: expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad`
2+
--> $DIR/recover-enum.rs:4:9
33
|
44
LL | Very
5-
| ^ help: missing comma
5+
| -
6+
| |
7+
| expected one of `(`, `,`, `=`, `{`, or `}`
8+
| help: missing `,`
9+
LL | Bad(usize)
10+
| ^^^ unexpected token
611

7-
error: missing comma
8-
--> $DIR/recover-enum.rs:5:19
12+
error: expected one of `,`, `=`, or `}`, found `Stuff`
13+
--> $DIR/recover-enum.rs:6:9
914
|
1015
LL | Bad(usize)
11-
| ^ help: missing comma
16+
| -
17+
| |
18+
| expected one of `,`, `=`, or `}`
19+
| help: missing `,`
20+
LL |
21+
LL | Stuff { a: usize }
22+
| ^^^^^ unexpected token
1223

13-
error: missing comma
14-
--> $DIR/recover-enum.rs:7:27
24+
error: expected one of `,`, `=`, or `}`, found `Here`
25+
--> $DIR/recover-enum.rs:8:9
1526
|
1627
LL | Stuff { a: usize }
17-
| ^ help: missing comma
28+
| -
29+
| |
30+
| expected one of `,`, `=`, or `}`
31+
| help: missing `,`
32+
LL |
33+
LL | Here
34+
| ^^^^ unexpected token
1835

1936
error: aborting due to 3 previous errors
2037

src/test/ui/similar-tokens.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error: expected one of `,`, `::`, `as`, or `}`, found `.`
22
--> $DIR/similar-tokens.rs:7:10
33
|
44
LL | use x::{A. B};
5-
| ^ expected one of `,`, `::`, `as`, or `}`
5+
| ^
6+
| |
7+
| expected one of `,`, `::`, `as`, or `}`
8+
| help: missing `,`
69

710
error: aborting due to previous error
811

src/test/ui/tuple/tuple-struct-fields/test.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error: expected one of `)` or `,`, found `(`
22
--> $DIR/test.rs:4:26
33
|
44
LL | struct S2(pub((foo)) ());
5-
| ^ expected one of `)` or `,`
5+
| -^ expected one of `)` or `,`
6+
| |
7+
| help: missing `,`
68

79
error[E0412]: cannot find type `foo` in this scope
810
--> $DIR/test.rs:4:20

src/test/ui/tuple/tuple-struct-fields/test2.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error: expected one of `)` or `,`, found `(`
22
--> $DIR/test2.rs:5:26
33
|
44
LL | struct S3(pub $t ());
5-
| ^ expected one of `)` or `,`
5+
| -^ expected one of `)` or `,`
6+
| |
7+
| help: missing `,`
68
...
79
LL | define_struct! { (foo) }
810
| ------------------------ in this macro invocation

src/test/ui/tuple/tuple-struct-fields/test3.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error: expected one of `)` or `,`, found `(`
22
--> $DIR/test3.rs:5:27
33
|
44
LL | struct S3(pub($t) ());
5-
| ^ expected one of `)` or `,`
5+
| -^ expected one of `)` or `,`
6+
| |
7+
| help: missing `,`
68
...
79
LL | define_struct! { foo }
810
| ---------------------- in this macro invocation

0 commit comments

Comments
 (0)