From 8fc7f438c4347e027deda5cda4bcd5e560610bb7 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 31 Aug 2018 13:35:48 +0300 Subject: start item recovery --- crates/libsyntax2/src/grammar/items/mod.rs | 6 +++++- crates/libsyntax2/src/grammar/items/structs.rs | 4 ++-- crates/libsyntax2/src/grammar/items/traits.rs | 2 +- crates/libsyntax2/src/grammar/mod.rs | 8 ++++++-- crates/libsyntax2/src/parser_api.rs | 6 +++--- .../tests/data/parser/err/0020_fn_recover.rs | 3 +++ .../tests/data/parser/err/0020_fn_recover.txt | 20 ++++++++++++++++++++ 7 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 crates/libsyntax2/tests/data/parser/err/0020_fn_recover.rs create mode 100644 crates/libsyntax2/tests/data/parser/err/0020_fn_recover.txt (limited to 'crates/libsyntax2') diff --git a/crates/libsyntax2/src/grammar/items/mod.rs b/crates/libsyntax2/src/grammar/items/mod.rs index 7c6f7b63e..e672aa419 100644 --- a/crates/libsyntax2/src/grammar/items/mod.rs +++ b/crates/libsyntax2/src/grammar/items/mod.rs @@ -24,6 +24,10 @@ pub(super) enum ItemFlavor { Mod, Trait } +const ITEM_RECOVERY_SET: TokenSet = + token_set![FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, + MOD_KW, PUB_KW, CRATE_KW]; + pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { let m = p.start(); match maybe_item(p, flavor) { @@ -231,7 +235,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) { assert!(p.at(FN_KW)); p.bump(); - name(p); + name_r(p, ITEM_RECOVERY_SET); // test function_type_params // fn foo(){} type_params::opt_type_param_list(p); diff --git a/crates/libsyntax2/src/grammar/items/structs.rs b/crates/libsyntax2/src/grammar/items/structs.rs index 180205393..f1e78865c 100644 --- a/crates/libsyntax2/src/grammar/items/structs.rs +++ b/crates/libsyntax2/src/grammar/items/structs.rs @@ -4,7 +4,7 @@ pub(super) fn struct_def(p: &mut Parser) { assert!(p.at(STRUCT_KW)); p.bump(); - name(p); + name_r(p, ITEM_RECOVERY_SET); type_params::opt_type_param_list(p); match p.current() { WHERE_KW => { @@ -41,7 +41,7 @@ pub(super) fn struct_def(p: &mut Parser) { pub(super) fn enum_def(p: &mut Parser) { assert!(p.at(ENUM_KW)); p.bump(); - name(p); + name_r(p, ITEM_RECOVERY_SET); type_params::opt_type_param_list(p); type_params::opt_where_clause(p); if p.at(L_CURLY) { diff --git a/crates/libsyntax2/src/grammar/items/traits.rs b/crates/libsyntax2/src/grammar/items/traits.rs index 01b79e3c9..9d21d4d36 100644 --- a/crates/libsyntax2/src/grammar/items/traits.rs +++ b/crates/libsyntax2/src/grammar/items/traits.rs @@ -5,7 +5,7 @@ use super::*; pub(super) fn trait_def(p: &mut Parser) { assert!(p.at(TRAIT_KW)); p.bump(); - name(p); + name_r(p, ITEM_RECOVERY_SET); type_params::opt_type_param_list(p); if p.at(COLON) { type_params::bounds(p); diff --git a/crates/libsyntax2/src/grammar/mod.rs b/crates/libsyntax2/src/grammar/mod.rs index 1acecac41..339664af3 100644 --- a/crates/libsyntax2/src/grammar/mod.rs +++ b/crates/libsyntax2/src/grammar/mod.rs @@ -129,16 +129,20 @@ fn opt_fn_ret_type(p: &mut Parser) -> bool { } } -fn name(p: &mut Parser) { +fn name_r(p: &mut Parser, recovery: TokenSet) { if p.at(IDENT) { let m = p.start(); p.bump(); m.complete(p, NAME); } else { - p.err_and_bump("expected a name"); + p.err_recover("expected a name", recovery); } } +fn name(p: &mut Parser) { + name_r(p, TokenSet::EMPTY) +} + fn name_ref(p: &mut Parser) { if p.at(IDENT) { let m = p.start(); diff --git a/crates/libsyntax2/src/parser_api.rs b/crates/libsyntax2/src/parser_api.rs index 70af474ae..9bc58e7f7 100644 --- a/crates/libsyntax2/src/parser_api.rs +++ b/crates/libsyntax2/src/parser_api.rs @@ -12,7 +12,7 @@ fn mask(kind: SyntaxKind) -> u128 { } impl TokenSet { - const EMPTY: TokenSet = TokenSet(0); + pub const EMPTY: TokenSet = TokenSet(0); pub fn contains(&self, kind: SyntaxKind) -> bool { self.0 & mask(kind) != 0 @@ -145,10 +145,10 @@ impl<'t> Parser<'t> { } /// Create an error node and consume the next token. - pub(crate) fn err_recover(&mut self, message: &str, recovery_set: TokenSet) { + pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) { if self.at(SyntaxKind::L_CURLY) || self.at(SyntaxKind::R_CURLY) - || recovery_set.contains(self.current()) { + || recovery.contains(self.current()) { self.error(message); } else { let m = self.start(); diff --git a/crates/libsyntax2/tests/data/parser/err/0020_fn_recover.rs b/crates/libsyntax2/tests/data/parser/err/0020_fn_recover.rs new file mode 100644 index 000000000..3393b668b --- /dev/null +++ b/crates/libsyntax2/tests/data/parser/err/0020_fn_recover.rs @@ -0,0 +1,3 @@ +fn + +fn foo() {} diff --git a/crates/libsyntax2/tests/data/parser/err/0020_fn_recover.txt b/crates/libsyntax2/tests/data/parser/err/0020_fn_recover.txt new file mode 100644 index 000000000..b5218b0fa --- /dev/null +++ b/crates/libsyntax2/tests/data/parser/err/0020_fn_recover.txt @@ -0,0 +1,20 @@ +ROOT@[0; 16) + FN_DEF@[0; 2) + FN_KW@[0; 2) + err: `expected a name` + err: `expected function arguments` + err: `expected a block` + WHITESPACE@[2; 4) + FN_DEF@[4; 15) + FN_KW@[4; 6) + WHITESPACE@[6; 7) + NAME@[7; 10) + IDENT@[7; 10) "foo" + PARAM_LIST@[10; 12) + L_PAREN@[10; 11) + R_PAREN@[11; 12) + WHITESPACE@[12; 13) + BLOCK@[13; 15) + L_CURLY@[13; 14) + R_CURLY@[14; 15) + WHITESPACE@[15; 16) -- cgit v1.2.3