diff --git a/src/parser/event_parser/grammar/items.rs b/src/parser/event_parser/grammar/items.rs index 309e4f4def4a..56e3208ac445 100644 --- a/src/parser/event_parser/grammar/items.rs +++ b/src/parser/event_parser/grammar/items.rs @@ -36,6 +36,11 @@ fn item(p: &mut Parser) { fn_item(p); FN_ITEM } + L_CURLY => { + item.abandon(p); + error_block(p, "expected item"); + return; + } err_token => { item.abandon(p); let message = if err_token == SEMI { diff --git a/src/parser/event_parser/grammar/mod.rs b/src/parser/event_parser/grammar/mod.rs index 92125acd1c60..e7f1915d260f 100644 --- a/src/parser/event_parser/grammar/mod.rs +++ b/src/parser/event_parser/grammar/mod.rs @@ -49,6 +49,23 @@ fn alias(p: &mut Parser) -> bool { true //FIXME: return false if three are errors } +fn error_block(p: &mut Parser, message: &str) { + assert!(p.at(L_CURLY)); + let err = p.start(); + p.error().message(message).emit(); + p.bump(); + let mut level: u32 = 1; + while level > 0 && !p.at(EOF) { + match p.current() { + L_CURLY => level += 1, + R_CURLY => level -= 1, + _ => (), + } + p.bump(); + } + err.complete(p, ERROR); +} + impl<'p> Parser<'p> { fn at(&self, l: L) -> bool { l.is_ahead(self) diff --git a/tests/data/parser/err/0008_item_block_recovery.rs b/tests/data/parser/err/0008_item_block_recovery.rs new file mode 100644 index 000000000000..9fcac19b5ce0 --- /dev/null +++ b/tests/data/parser/err/0008_item_block_recovery.rs @@ -0,0 +1,13 @@ +fn foo() { +} + +bar() { + if true { + 1 + } else { + 2 + 3 + } +} + +fn baz() { +} diff --git a/tests/data/parser/err/0008_item_block_recovery.txt b/tests/data/parser/err/0008_item_block_recovery.txt new file mode 100644 index 000000000000..4bb66f56a127 --- /dev/null +++ b/tests/data/parser/err/0008_item_block_recovery.txt @@ -0,0 +1,61 @@ +FILE@[0; 95) + FN_ITEM@[0; 14) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + IDENT@[3; 6) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + L_CURLY@[9; 10) + WHITESPACE@[10; 11) + R_CURLY@[11; 12) + WHITESPACE@[12; 14) + ERROR@[14; 17) + err: `expected item` + IDENT@[14; 17) + ERROR@[17; 18) + err: `expected item` + L_PAREN@[17; 18) + ERROR@[18; 20) + err: `expected item` + R_PAREN@[18; 19) + WHITESPACE@[19; 20) + ERROR@[20; 82) + err: `expected item` + L_CURLY@[20; 21) + WHITESPACE@[21; 26) + IDENT@[26; 28) + WHITESPACE@[28; 29) + TRUE_KW@[29; 33) + WHITESPACE@[33; 34) + L_CURLY@[34; 35) + WHITESPACE@[35; 44) + INT_NUMBER@[44; 45) + WHITESPACE@[45; 50) + R_CURLY@[50; 51) + WHITESPACE@[51; 52) + IDENT@[52; 56) + WHITESPACE@[56; 57) + L_CURLY@[57; 58) + WHITESPACE@[58; 67) + INT_NUMBER@[67; 68) + WHITESPACE@[68; 69) + PLUS@[69; 70) + WHITESPACE@[70; 71) + INT_NUMBER@[71; 72) + WHITESPACE@[72; 77) + R_CURLY@[77; 78) + WHITESPACE@[78; 79) + R_CURLY@[79; 80) + WHITESPACE@[80; 82) + FN_ITEM@[82; 95) + FN_KW@[82; 84) + WHITESPACE@[84; 85) + IDENT@[85; 88) + L_PAREN@[88; 89) + R_PAREN@[89; 90) + WHITESPACE@[90; 91) + L_CURLY@[91; 92) + WHITESPACE@[92; 93) + R_CURLY@[93; 94) + WHITESPACE@[94; 95)