From f48b9d9be737339be988042ca88d31330738618c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 8 Sep 2018 10:55:09 +0300 Subject: Fix block structure in enums --- crates/libsyntax2/src/grammar/items/mod.rs | 8 +- crates/libsyntax2/src/grammar/items/nominal.rs | 150 +++++++++++++++ crates/libsyntax2/src/grammar/items/structs.rs | 141 -------------- .../tests/data/parser/err/0013_invalid_type.txt | 44 +++-- .../libsyntax2/tests/data/parser/err/0025_nope.rs | 31 ++++ .../libsyntax2/tests/data/parser/err/0025_nope.txt | 203 +++++++++++++++++++++ 6 files changed, 413 insertions(+), 164 deletions(-) create mode 100644 crates/libsyntax2/src/grammar/items/nominal.rs delete mode 100644 crates/libsyntax2/src/grammar/items/structs.rs create mode 100644 crates/libsyntax2/tests/data/parser/err/0025_nope.rs create mode 100644 crates/libsyntax2/tests/data/parser/err/0025_nope.txt diff --git a/crates/libsyntax2/src/grammar/items/mod.rs b/crates/libsyntax2/src/grammar/items/mod.rs index 57742ecb9..85d7fe770 100644 --- a/crates/libsyntax2/src/grammar/items/mod.rs +++ b/crates/libsyntax2/src/grammar/items/mod.rs @@ -1,11 +1,11 @@ mod consts; -mod structs; +mod nominal; mod traits; mod use_item; use super::*; -pub(crate) use self::structs::named_field_def_list; +pub(crate) use self::nominal::named_field_def_list; // test mod_contents // fn foo() {} @@ -176,7 +176,7 @@ fn items_without_modifiers(p: &mut Parser) -> Option { MODULE } STRUCT_KW => { - structs::struct_def(p); + nominal::struct_def(p); if p.at(SEMI) { p.err_and_bump( "expected item, found `;`\n\ @@ -186,7 +186,7 @@ fn items_without_modifiers(p: &mut Parser) -> Option { STRUCT_DEF } ENUM_KW => { - structs::enum_def(p); + nominal::enum_def(p); ENUM_DEF } USE_KW => { diff --git a/crates/libsyntax2/src/grammar/items/nominal.rs b/crates/libsyntax2/src/grammar/items/nominal.rs new file mode 100644 index 000000000..3db5b24af --- /dev/null +++ b/crates/libsyntax2/src/grammar/items/nominal.rs @@ -0,0 +1,150 @@ +use super::*; + +pub(super) fn struct_def(p: &mut Parser) { + assert!(p.at(STRUCT_KW)); + p.bump(); + + name_r(p, ITEM_RECOVERY_SET); + type_params::opt_type_param_list(p); + match p.current() { + WHERE_KW => { + type_params::opt_where_clause(p); + match p.current() { + SEMI => { + p.bump(); + return; + } + L_CURLY => named_field_def_list(p), + _ => { + //TODO: special case `(` error message + p.error("expected `;` or `{`"); + return; + } + } + } + SEMI => { + p.bump(); + return; + } + L_CURLY => named_field_def_list(p), + L_PAREN => { + pos_field_list(p); + p.expect(SEMI); + } + _ => { + p.error("expected `;`, `{`, or `(`"); + return; + } + } +} + +pub(super) fn enum_def(p: &mut Parser) { + assert!(p.at(ENUM_KW)); + p.bump(); + name_r(p, ITEM_RECOVERY_SET); + type_params::opt_type_param_list(p); + type_params::opt_where_clause(p); + if p.at(L_CURLY) { + enum_variant_list(p); + } else { + p.error("expected `{`") + } +} + +fn enum_variant_list(p: &mut Parser) { + assert!(p.at(L_CURLY)); + let m = p.start(); + p.bump(); + while !p.at(EOF) && !p.at(R_CURLY) { + if p.at(L_CURLY) { + error_block(p, "expected enum variant"); + continue; + } + let var = p.start(); + attributes::outer_attributes(p); + if p.at(IDENT) { + name(p); + match p.current() { + L_CURLY => named_field_def_list(p), + L_PAREN => pos_field_list(p), + EQ => { + p.bump(); + expressions::expr(p); + } + _ => (), + } + var.complete(p, ENUM_VARIANT); + } else { + var.abandon(p); + p.err_and_bump("expected enum variant"); + } + if !p.at(R_CURLY) { + p.expect(COMMA); + } + } + p.expect(R_CURLY); + m.complete(p, ENUM_VARIANT_LIST); +} + +pub(crate) fn named_field_def_list(p: &mut Parser) { + assert!(p.at(L_CURLY)); + let m = p.start(); + p.bump(); + while !p.at(R_CURLY) && !p.at(EOF) { + if p.at(L_CURLY) { + error_block(p, "expected field"); + continue; + } + named_field_def(p); + if !p.at(R_CURLY) { + p.expect(COMMA); + } + } + p.expect(R_CURLY); + m.complete(p, NAMED_FIELD_DEF_LIST); + + fn named_field_def(p: &mut Parser) { + let m = p.start(); + // test field_attrs + // struct S { + // #[serde(with = "url_serde")] + // pub uri: Uri, + // } + attributes::outer_attributes(p); + opt_visibility(p); + if p.at(IDENT) { + name(p); + p.expect(COLON); + types::type_(p); + m.complete(p, NAMED_FIELD_DEF); + } else { + m.abandon(p); + p.err_and_bump("expected field declaration"); + } + } +} + +fn pos_field_list(p: &mut Parser) { + assert!(p.at(L_PAREN)); + let m = p.start(); + if !p.expect(L_PAREN) { + return; + } + while !p.at(R_PAREN) && !p.at(EOF) { + let m = p.start(); + opt_visibility(p); + if !p.at_ts(types::TYPE_FIRST) { + p.error("expected a type"); + m.complete(p, ERROR); + break; + } + types::type_(p); + m.complete(p, POS_FIELD); + + if !p.at(R_PAREN) { + p.expect(COMMA); + } + } + p.expect(R_PAREN); + m.complete(p, POS_FIELD_LIST); +} diff --git a/crates/libsyntax2/src/grammar/items/structs.rs b/crates/libsyntax2/src/grammar/items/structs.rs deleted file mode 100644 index f1e78865c..000000000 --- a/crates/libsyntax2/src/grammar/items/structs.rs +++ /dev/null @@ -1,141 +0,0 @@ -use super::*; - -pub(super) fn struct_def(p: &mut Parser) { - assert!(p.at(STRUCT_KW)); - p.bump(); - - name_r(p, ITEM_RECOVERY_SET); - type_params::opt_type_param_list(p); - match p.current() { - WHERE_KW => { - type_params::opt_where_clause(p); - match p.current() { - SEMI => { - p.bump(); - return; - } - L_CURLY => named_field_def_list(p), - _ => { - //TODO: special case `(` error message - p.error("expected `;` or `{`"); - return; - } - } - } - SEMI => { - p.bump(); - return; - } - L_CURLY => named_field_def_list(p), - L_PAREN => { - pos_field_list(p); - p.expect(SEMI); - } - _ => { - p.error("expected `;`, `{`, or `(`"); - return; - } - } -} - -pub(super) fn enum_def(p: &mut Parser) { - assert!(p.at(ENUM_KW)); - p.bump(); - name_r(p, ITEM_RECOVERY_SET); - type_params::opt_type_param_list(p); - type_params::opt_where_clause(p); - if p.at(L_CURLY) { - enum_variant_list(p); - } else { - p.error("expected `{`") - } -} - -fn enum_variant_list(p: &mut Parser) { - assert!(p.at(L_CURLY)); - let m = p.start(); - p.bump(); - while !p.at(EOF) && !p.at(R_CURLY) { - if p.at(L_CURLY) { - error_block(p, "expected enum variant"); - continue; - } - let var = p.start(); - attributes::outer_attributes(p); - if p.at(IDENT) { - name(p); - match p.current() { - L_CURLY => named_field_def_list(p), - L_PAREN => pos_field_list(p), - EQ => { - p.bump(); - expressions::expr(p); - } - _ => (), - } - var.complete(p, ENUM_VARIANT); - } else { - var.abandon(p); - p.err_and_bump("expected enum variant"); - } - if !p.at(R_CURLY) { - p.expect(COMMA); - } - } - p.expect(R_CURLY); - m.complete(p, ENUM_VARIANT_LIST); -} - -pub(crate) fn named_field_def_list(p: &mut Parser) { - assert!(p.at(L_CURLY)); - let m = p.start(); - p.bump(); - while !p.at(R_CURLY) && !p.at(EOF) { - named_field_def(p); - if !p.at(R_CURLY) { - p.expect(COMMA); - } - } - p.expect(R_CURLY); - m.complete(p, NAMED_FIELD_DEF_LIST); - - fn named_field_def(p: &mut Parser) { - let m = p.start(); - // test field_attrs - // struct S { - // #[serde(with = "url_serde")] - // pub uri: Uri, - // } - attributes::outer_attributes(p); - opt_visibility(p); - if p.at(IDENT) { - name(p); - p.expect(COLON); - types::type_(p); - m.complete(p, NAMED_FIELD_DEF); - } else { - m.abandon(p); - p.err_and_bump("expected field declaration"); - } - } -} - -fn pos_field_list(p: &mut Parser) { - assert!(p.at(L_PAREN)); - let m = p.start(); - if !p.expect(L_PAREN) { - return; - } - while !p.at(R_PAREN) && !p.at(EOF) { - let pos_field = p.start(); - opt_visibility(p); - types::type_(p); - pos_field.complete(p, POS_FIELD); - - if !p.at(R_PAREN) { - p.expect(COMMA); - } - } - p.expect(R_PAREN); - m.complete(p, POS_FIELD_LIST); -} diff --git a/crates/libsyntax2/tests/data/parser/err/0013_invalid_type.txt b/crates/libsyntax2/tests/data/parser/err/0013_invalid_type.txt index f7f6c6bce..e1a6b6432 100644 --- a/crates/libsyntax2/tests/data/parser/err/0013_invalid_type.txt +++ b/crates/libsyntax2/tests/data/parser/err/0013_invalid_type.txt @@ -1,5 +1,5 @@ ROOT@[0; 86) - STRUCT_DEF@[0; 84) + STRUCT_DEF@[0; 72) VISIBILITY@[0; 3) PUB_KW@[0; 3) WHITESPACE@[3; 4) @@ -7,7 +7,7 @@ ROOT@[0; 86) WHITESPACE@[10; 11) NAME@[11; 16) IDENT@[11; 16) "Cache" - POS_FIELD_LIST@[16; 83) + POS_FIELD_LIST@[16; 72) L_PAREN@[16; 17) WHITESPACE@[17; 22) POS_FIELD@[22; 68) @@ -62,22 +62,28 @@ ROOT@[0; 86) NAME_REF@[69; 72) IDENT@[69; 72) "Any" err: `expected COMMA` - err: `expected type` - POS_FIELD@[72; 73) - ERROR@[72; 73) - R_ANGLE@[72; 73) - COMMA@[73; 74) - WHITESPACE@[74; 79) - err: `expected type` - POS_FIELD@[79; 80) - ERROR@[79; 80) - R_ANGLE@[79; 80) - err: `expected COMMA` - err: `expected type` - POS_FIELD@[80; 81) - ERROR@[80; 81) - R_ANGLE@[80; 81) - WHITESPACE@[81; 82) - R_PAREN@[82; 83) + err: `expected a type` + err: `expected R_PAREN` + err: `expected SEMI` + err: `expected an item` + ERROR@[72; 72) + ERROR@[72; 73) + R_ANGLE@[72; 73) + err: `expected an item` + ERROR@[73; 74) + COMMA@[73; 74) + WHITESPACE@[74; 79) + err: `expected an item` + ERROR@[79; 80) + R_ANGLE@[79; 80) + err: `expected an item` + ERROR@[80; 81) + R_ANGLE@[80; 81) + WHITESPACE@[81; 82) + err: `expected an item` + ERROR@[82; 83) + R_PAREN@[82; 83) + err: `expected an item` + ERROR@[83; 84) SEMI@[83; 84) WHITESPACE@[84; 86) diff --git a/crates/libsyntax2/tests/data/parser/err/0025_nope.rs b/crates/libsyntax2/tests/data/parser/err/0025_nope.rs new file mode 100644 index 000000000..28726ed51 --- /dev/null +++ b/crates/libsyntax2/tests/data/parser/err/0025_nope.rs @@ -0,0 +1,31 @@ +fn main() { + enum Test { + Var1, + Var2(String), + Var3 { + abc: {}, //~ ERROR: expected type, found `{` + }, + } + + // recover... + let a = 1; + enum Test2 { + Fine, + } + + enum Test3 { + StillFine { + def: i32, + }, + } + + { + // fail again + enum Test4 { + Nope(i32 {}) //~ ERROR: found `{` + //~^ ERROR: found `{` + } + } + // still recover later + let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_` +} diff --git a/crates/libsyntax2/tests/data/parser/err/0025_nope.txt b/crates/libsyntax2/tests/data/parser/err/0025_nope.txt new file mode 100644 index 000000000..c30b8585f --- /dev/null +++ b/crates/libsyntax2/tests/data/parser/err/0025_nope.txt @@ -0,0 +1,203 @@ +ROOT@[0; 575) + FN_DEF@[0; 574) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 7) + IDENT@[3; 7) "main" + PARAM_LIST@[7; 9) + L_PAREN@[7; 8) + R_PAREN@[8; 9) + WHITESPACE@[9; 10) + BLOCK@[10; 574) + L_CURLY@[10; 11) + WHITESPACE@[11; 16) + ENUM_DEF@[16; 152) + ENUM_KW@[16; 20) + WHITESPACE@[20; 21) + NAME@[21; 25) + IDENT@[21; 25) "Test" + WHITESPACE@[25; 26) + ENUM_VARIANT_LIST@[26; 152) + L_CURLY@[26; 27) + WHITESPACE@[27; 36) + ENUM_VARIANT@[36; 40) + NAME@[36; 40) + IDENT@[36; 40) "Var1" + COMMA@[40; 41) + WHITESPACE@[41; 50) + ENUM_VARIANT@[50; 62) + NAME@[50; 54) + IDENT@[50; 54) "Var2" + POS_FIELD_LIST@[54; 62) + L_PAREN@[54; 55) + POS_FIELD@[55; 61) + PATH_TYPE@[55; 61) + PATH@[55; 61) + PATH_SEGMENT@[55; 61) + NAME_REF@[55; 61) + IDENT@[55; 61) "String" + R_PAREN@[61; 62) + COMMA@[62; 63) + WHITESPACE@[63; 72) + ENUM_VARIANT@[72; 145) + NAME@[72; 76) + IDENT@[72; 76) "Var3" + WHITESPACE@[76; 77) + NAMED_FIELD_DEF_LIST@[77; 145) + L_CURLY@[77; 78) + WHITESPACE@[78; 91) + NAMED_FIELD_DEF@[91; 95) + NAME@[91; 94) + IDENT@[91; 94) "abc" + COLON@[94; 95) + err: `expected type` + err: `expected COMMA` + WHITESPACE@[95; 96) + err: `expected field` + ERROR@[96; 98) + L_CURLY@[96; 97) + R_CURLY@[97; 98) + err: `expected field declaration` + ERROR@[98; 99) + COMMA@[98; 99) + WHITESPACE@[99; 100) + COMMENT@[100; 135) + WHITESPACE@[135; 144) + R_CURLY@[144; 145) + COMMA@[145; 146) + WHITESPACE@[146; 151) + R_CURLY@[151; 152) + WHITESPACE@[152; 158) + COMMENT@[158; 171) + WHITESPACE@[171; 176) + LET_STMT@[176; 186) + LET_KW@[176; 179) + WHITESPACE@[179; 180) + BIND_PAT@[180; 181) + NAME@[180; 181) + IDENT@[180; 181) "a" + WHITESPACE@[181; 182) + EQ@[182; 183) + WHITESPACE@[183; 184) + LITERAL@[184; 185) + INT_NUMBER@[184; 185) "1" + SEMI@[185; 186) + WHITESPACE@[186; 191) + ENUM_DEF@[191; 223) + ENUM_KW@[191; 195) + WHITESPACE@[195; 196) + NAME@[196; 201) + IDENT@[196; 201) "Test2" + WHITESPACE@[201; 202) + ENUM_VARIANT_LIST@[202; 223) + L_CURLY@[202; 203) + WHITESPACE@[203; 212) + ENUM_VARIANT@[212; 216) + NAME@[212; 216) + IDENT@[212; 216) "Fine" + COMMA@[216; 217) + WHITESPACE@[217; 222) + R_CURLY@[222; 223) + WHITESPACE@[223; 229) + ENUM_DEF@[229; 300) + ENUM_KW@[229; 233) + WHITESPACE@[233; 234) + NAME@[234; 239) + IDENT@[234; 239) "Test3" + WHITESPACE@[239; 240) + ENUM_VARIANT_LIST@[240; 300) + L_CURLY@[240; 241) + WHITESPACE@[241; 250) + ENUM_VARIANT@[250; 293) + NAME@[250; 259) + IDENT@[250; 259) "StillFine" + WHITESPACE@[259; 260) + NAMED_FIELD_DEF_LIST@[260; 293) + L_CURLY@[260; 261) + WHITESPACE@[261; 274) + NAMED_FIELD_DEF@[274; 282) + NAME@[274; 277) + IDENT@[274; 277) "def" + COLON@[277; 278) + WHITESPACE@[278; 279) + PATH_TYPE@[279; 282) + PATH@[279; 282) + PATH_SEGMENT@[279; 282) + NAME_REF@[279; 282) + IDENT@[279; 282) "i32" + COMMA@[282; 283) + WHITESPACE@[283; 292) + R_CURLY@[292; 293) + COMMA@[293; 294) + WHITESPACE@[294; 299) + R_CURLY@[299; 300) + WHITESPACE@[300; 306) + EXPR_STMT@[306; 459) + BLOCK_EXPR@[306; 459) + BLOCK@[306; 459) + L_CURLY@[306; 307) + WHITESPACE@[307; 316) + COMMENT@[316; 329) + WHITESPACE@[329; 338) + ENUM_DEF@[338; 453) + ENUM_KW@[338; 342) + WHITESPACE@[342; 343) + NAME@[343; 348) + IDENT@[343; 348) "Test4" + WHITESPACE@[348; 349) + ENUM_VARIANT_LIST@[349; 453) + L_CURLY@[349; 350) + WHITESPACE@[350; 363) + ENUM_VARIANT@[363; 372) + NAME@[363; 367) + IDENT@[363; 367) "Nope" + POS_FIELD_LIST@[367; 372) + L_PAREN@[367; 368) + POS_FIELD@[368; 371) + PATH_TYPE@[368; 371) + PATH@[368; 371) + PATH_SEGMENT@[368; 371) + NAME_REF@[368; 371) + IDENT@[368; 371) "i32" + err: `expected COMMA` + WHITESPACE@[371; 372) + err: `expected a type` + err: `expected R_PAREN` + err: `expected COMMA` + err: `expected enum variant` + ERROR@[372; 372) + ERROR@[372; 374) + L_CURLY@[372; 373) + R_CURLY@[373; 374) + err: `expected enum variant` + ERROR@[374; 375) + R_PAREN@[374; 375) + WHITESPACE@[375; 376) + COMMENT@[376; 396) + WHITESPACE@[396; 422) + COMMENT@[422; 443) + WHITESPACE@[443; 452) + R_CURLY@[452; 453) + WHITESPACE@[453; 458) + R_CURLY@[458; 459) + WHITESPACE@[459; 464) + COMMENT@[464; 486) + WHITESPACE@[486; 491) + LET_STMT@[491; 510) + LET_KW@[491; 494) + WHITESPACE@[494; 495) + BIND_PAT@[495; 505) + NAME@[495; 505) + IDENT@[495; 505) "bad_syntax" + WHITESPACE@[505; 506) + EQ@[506; 507) + WHITESPACE@[507; 508) + err: `expected expression` + ERROR@[508; 509) + UNDERSCORE@[508; 509) + SEMI@[509; 510) + WHITESPACE@[510; 511) + COMMENT@[511; 572) + WHITESPACE@[572; 573) + R_CURLY@[573; 574) + WHITESPACE@[574; 575) -- cgit v1.2.3