From d07b448932ca8c714eff744d8582b7b0de1163fd Mon Sep 17 00:00:00 2001 From: Peefy Date: Fri, 31 May 2024 18:03:39 +0800 Subject: [PATCH] fix: list and config if expr error recovery in the parser (#1384) Signed-off-by: peefy --- kclvm/parser/src/parser/expr.rs | 6 + kclvm/parser/src/tests/error_recovery.rs | 30 ++++ ...sts__error_recovery__list_recovery_13.snap | 90 +++++++++++ ...sts__error_recovery__list_recovery_14.snap | 87 +++++++++++ ...sts__error_recovery__list_recovery_15.snap | 89 +++++++++++ ...sts__error_recovery__list_recovery_16.snap | 140 ++++++++++++++++++ ...sts__error_recovery__list_recovery_17.snap | 137 +++++++++++++++++ ...sts__error_recovery__list_recovery_18.snap | 126 ++++++++++++++++ 8 files changed, 705 insertions(+) create mode 100644 kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_13.snap create mode 100644 kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_14.snap create mode 100644 kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_15.snap create mode 100644 kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_16.snap create mode 100644 kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_17.snap create mode 100644 kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_18.snap diff --git a/kclvm/parser/src/parser/expr.rs b/kclvm/parser/src/parser/expr.rs index 9283f2d28..b1e0067a4 100644 --- a/kclvm/parser/src/parser/expr.rs +++ b/kclvm/parser/src/parser/expr.rs @@ -1163,6 +1163,7 @@ impl<'a> Parser<'a> { // elif ... let mut elif_list = Vec::new(); loop { + let marker = self.mark(); if !self.token.is_keyword(kw::Elif) { break; } @@ -1188,6 +1189,7 @@ impl<'a> Parser<'a> { x, self.sess.struct_token_loc(token, self.prev_token), ))); + self.drop(marker); } if let TokenKind::Newline = self.token.kind { @@ -1259,6 +1261,7 @@ impl<'a> Parser<'a> { let mut body = Vec::new(); loop { + let marker = self.mark(); self.validate_dedent(); if matches!(self.token.kind, TokenKind::Dedent(VALID_SPACES_LENGTH)) { break; @@ -1270,6 +1273,7 @@ impl<'a> Parser<'a> { self.bump(); } self.skip_newlines(); + self.drop(marker); } self.validate_dedent(); self.bump_token(TokenKind::Dedent(VALID_SPACES_LENGTH)); @@ -1581,6 +1585,7 @@ impl<'a> Parser<'a> { let mut elif_list = Vec::new(); let mut last_token = self.token; loop { + let marker = self.mark(); if !self.token.is_keyword(kw::Elif) { break; } @@ -1607,6 +1612,7 @@ impl<'a> Parser<'a> { self.sess.struct_token_loc(token, self.prev_token), ))); last_token = self.prev_token; + self.drop(marker); } if let TokenKind::Newline = self.token.kind { diff --git a/kclvm/parser/src/tests/error_recovery.rs b/kclvm/parser/src/tests/error_recovery.rs index 00bf54555..cff059570 100644 --- a/kclvm/parser/src/tests/error_recovery.rs +++ b/kclvm/parser/src/tests/error_recovery.rs @@ -52,6 +52,21 @@ parse_expr_snapshot! { list_recovery_9, "[*a, **b]" } parse_expr_snapshot! { list_recovery_10, "[**a, *b" } parse_expr_snapshot! { list_recovery_11, "[if True: a, b]" } parse_expr_snapshot! { list_recovery_12, "[if True: **a, b]" } +parse_expr_snapshot! { list_recovery_13, r#"[ + if True: + b = [] +] +"# } +parse_expr_snapshot! { list_recovery_14, r#"[ + if True: + b = +] +"# } +parse_expr_snapshot! { list_recovery_15, r#"[ + if True: + b - +] +"# } parse_expr_snapshot! { config_recovery_0, "{" } parse_expr_snapshot! { config_recovery_1, "{a = 1" } parse_expr_snapshot! { config_recovery_2, "{a = 1, b = 2" } @@ -71,6 +86,21 @@ parse_expr_snapshot! { config_recovery_12, "{if True: *a, b = 2}" } parse_expr_snapshot! { config_recovery_13, "{if True: key: {}}" } parse_expr_snapshot! { config_recovery_14, "{if True: key: []}" } parse_expr_snapshot! { config_recovery_15, "{你好" } +parse_expr_snapshot! { list_recovery_16, r#"{ + if True: + b = [] = [] +} +"# } +parse_expr_snapshot! { list_recovery_17, r#"{ + if True: + b = [] = +} +"# } +parse_expr_snapshot! { list_recovery_18, r#"{ + if True: + b = [] - +} +"# } parse_expr_snapshot! { comp_clause_recovery_0, "[i for i in [1,2,3]]" } parse_expr_snapshot! { comp_clause_recovery_1, "[i, j for i in [1,2,3]]" } parse_expr_snapshot! { comp_clause_recovery_2, "[for i in [1,2,3]]" } diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_13.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_13.snap new file mode 100644 index 000000000..90b45fd76 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_13.snap @@ -0,0 +1,90 @@ +--- +source: parser/src/tests/error_recovery.rs +expression: "crate::tests::parsing_expr_string(r#\"[\n if True:\n b = []\n]\n\"#)" +--- +Node { + node: List( + ListExpr { + elts: [ + Node { + node: ListIfItem( + ListIfItemExpr { + if_cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 11, + }, + exprs: [ + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 3, + column: 10, + end_line: 3, + end_column: 11, + }, + Node { + node: List( + ListExpr { + elts: [], + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 12, + end_line: 3, + end_column: 14, + }, + ], + orelse: None, + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 0, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 4, + end_column: 1, +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_14.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_14.snap new file mode 100644 index 000000000..fe6b45e6d --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_14.snap @@ -0,0 +1,87 @@ +--- +source: parser/src/tests/error_recovery.rs +expression: "crate::tests::parsing_expr_string(r#\"[\n if True:\n b = \n]\n\"#)" +--- +Node { + node: List( + ListExpr { + elts: [ + Node { + node: ListIfItem( + ListIfItemExpr { + if_cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 11, + }, + exprs: [ + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 3, + column: 10, + end_line: 3, + end_column: 11, + }, + Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 3, + column: 12, + end_line: 4, + end_column: 0, + }, + ], + orelse: None, + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 0, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 4, + end_column: 1, +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_15.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_15.snap new file mode 100644 index 000000000..4d35ef38b --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_15.snap @@ -0,0 +1,89 @@ +--- +source: parser/src/tests/error_recovery.rs +expression: "crate::tests::parsing_expr_string(r#\"[\n if True:\n b -\n]\n\"#)" +--- +Node { + node: List( + ListExpr { + elts: [ + Node { + node: ListIfItem( + ListIfItemExpr { + if_cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 11, + }, + exprs: [ + Node { + node: Binary( + BinaryExpr { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + op: Sub, + right: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 3, + column: 11, + end_line: 4, + end_column: 0, + }, + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 11, + }, + ], + orelse: None, + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 0, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 4, + end_column: 1, +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_16.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_16.snap new file mode 100644 index 000000000..28dc6c75d --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_16.snap @@ -0,0 +1,140 @@ +--- +source: parser/src/tests/error_recovery.rs +expression: "crate::tests::parsing_expr_string(r#\"{\n if True:\n b = [] = []\n}\n\"#)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: None, + value: Node { + node: ConfigIfEntry( + ConfigIfEntryExpr { + if_cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 11, + }, + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ), + value: Node { + node: List( + ListExpr { + elts: [], + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 12, + end_line: 3, + end_column: 14, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 14, + }, + Node { + node: ConfigEntry { + key: Some( + Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 3, + column: 15, + end_line: 3, + end_column: 16, + }, + ), + value: Node { + node: List( + ListExpr { + elts: [], + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 17, + end_line: 3, + end_column: 19, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 3, + column: 15, + end_line: 3, + end_column: 19, + }, + ], + orelse: None, + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 0, + }, + operation: Union, + insert_index: -1, + }, + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 0, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 4, + end_column: 1, +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_17.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_17.snap new file mode 100644 index 000000000..592f00612 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_17.snap @@ -0,0 +1,137 @@ +--- +source: parser/src/tests/error_recovery.rs +expression: "crate::tests::parsing_expr_string(r#\"{\n if True:\n b = [] = \n}\n\"#)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: None, + value: Node { + node: ConfigIfEntry( + ConfigIfEntryExpr { + if_cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 11, + }, + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ), + value: Node { + node: List( + ListExpr { + elts: [], + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 12, + end_line: 3, + end_column: 14, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 14, + }, + Node { + node: ConfigEntry { + key: Some( + Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 3, + column: 15, + end_line: 3, + end_column: 16, + }, + ), + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 3, + column: 17, + end_line: 4, + end_column: 0, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 3, + column: 15, + end_line: 4, + end_column: 0, + }, + ], + orelse: None, + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 0, + }, + operation: Union, + insert_index: -1, + }, + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 0, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 4, + end_column: 1, +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_18.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_18.snap new file mode 100644 index 000000000..514a63e75 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_18.snap @@ -0,0 +1,126 @@ +--- +source: parser/src/tests/error_recovery.rs +expression: "crate::tests::parsing_expr_string(r#\"{\n if True:\n b = [] -\n}\n\"#)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: None, + value: Node { + node: ConfigIfEntry( + ConfigIfEntryExpr { + if_cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 11, + }, + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ), + value: Node { + node: Binary( + BinaryExpr { + left: Node { + node: List( + ListExpr { + elts: [], + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 12, + end_line: 3, + end_column: 14, + }, + op: Sub, + right: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 3, + column: 16, + end_line: 4, + end_column: 0, + }, + }, + ), + filename: "", + line: 3, + column: 12, + end_line: 3, + end_column: 16, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 16, + }, + ], + orelse: None, + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 0, + }, + operation: Union, + insert_index: -1, + }, + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 0, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 4, + end_column: 1, +}