From e790003e6b50b4ecf4b17f37a6c972e8f9d46374 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Thu, 11 Jul 2024 13:05:56 +0200 Subject: [PATCH] fix: Naively recover the Pratt matches when recovering --- .../parser_support/sequence_helper.rs | 13 ++++- .../parser_support/sequence_helper.rs | 13 ++++- .../generated/0.4.11-failure.yml | 57 +++++++++++++++++++ .../parser_support/sequence_helper.rs | 13 ++++- 4 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 crates/solidity/testing/snapshots/cst_output/SourceUnit/pratt_precedence_recovery/generated/0.4.11-failure.yml diff --git a/crates/codegen/runtime/cargo/src/runtime/language/parser_support/sequence_helper.rs b/crates/codegen/runtime/cargo/src/runtime/language/parser_support/sequence_helper.rs index 3eac27101b..50fa3ea4d8 100644 --- a/crates/codegen/runtime/cargo/src/runtime/language/parser_support/sequence_helper.rs +++ b/crates/codegen/runtime/cargo/src/runtime/language/parser_support/sequence_helper.rs @@ -116,8 +116,17 @@ impl SequenceHelper { })); } - (ParserResult::PrattOperatorMatch(_), ParserResult::SkippedUntil(_)) => - unreachable!("Error recovery happens outside precedence parsing"), + (ParserResult::PrattOperatorMatch(running), ParserResult::SkippedUntil(skipped)) => { + let nodes: Vec<_> = std::mem::take(&mut running.elements) + .into_iter() + .flat_map(PrattElement::into_nodes) + .collect(); + + self.result = State::Running(ParserResult::SkippedUntil(SkippedUntil { + nodes, + ..skipped + })); + } // Try to recover until we hit an expected boundary terminal. // If the sequence is unwinding, then a subsequent non-empty match must mean that diff --git a/crates/solidity/outputs/cargo/slang_solidity/src/generated/language/parser_support/sequence_helper.rs b/crates/solidity/outputs/cargo/slang_solidity/src/generated/language/parser_support/sequence_helper.rs index 4d46325e81..d2819a363f 100644 --- a/crates/solidity/outputs/cargo/slang_solidity/src/generated/language/parser_support/sequence_helper.rs +++ b/crates/solidity/outputs/cargo/slang_solidity/src/generated/language/parser_support/sequence_helper.rs @@ -118,8 +118,17 @@ impl SequenceHelper { })); } - (ParserResult::PrattOperatorMatch(_), ParserResult::SkippedUntil(_)) => - unreachable!("Error recovery happens outside precedence parsing"), + (ParserResult::PrattOperatorMatch(running), ParserResult::SkippedUntil(skipped)) => { + let nodes: Vec<_> = std::mem::take(&mut running.elements) + .into_iter() + .flat_map(PrattElement::into_nodes) + .collect(); + + self.result = State::Running(ParserResult::SkippedUntil(SkippedUntil { + nodes, + ..skipped + })); + } // Try to recover until we hit an expected boundary terminal. // If the sequence is unwinding, then a subsequent non-empty match must mean that diff --git a/crates/solidity/testing/snapshots/cst_output/SourceUnit/pratt_precedence_recovery/generated/0.4.11-failure.yml b/crates/solidity/testing/snapshots/cst_output/SourceUnit/pratt_precedence_recovery/generated/0.4.11-failure.yml new file mode 100644 index 0000000000..4220407a95 --- /dev/null +++ b/crates/solidity/testing/snapshots/cst_output/SourceUnit/pratt_precedence_recovery/generated/0.4.11-failure.yml @@ -0,0 +1,57 @@ +# This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +Source: > + 1 │ contract A { │ 0..12 + 2 │ function a() { │ 13..28 + 3 │ 2 + ( │ 29..36 + 4 │ } │ 37..39 + 5 │ } │ 40..41 + +Errors: # 1 total + - > + Error: Expected CloseParen or Comma. + ╭─[crates/solidity/testing/snapshots/cst_output/SourceUnit/pratt_precedence_recovery/input.sol:4:2] + │ + 4 │ } + │ │ + │ ╰─ Error occurred here. + ───╯ + +Tree: + - (SourceUnit) ► (members꞉ SourceUnitMembers): # "contract A {\n\tfunction a() {\n\t\t2 + (\n\t" (0..38) + - (item꞉ SourceUnitMember) ► (variant꞉ ContractDefinition): # "contract A {\n\tfunction a() {\n\t\t2 + (\n\t" (0..38) + - (contract_keyword꞉ ContractKeyword): "contract" # (0..8) + - (leading_trivia꞉ Whitespace): " " # (8..9) + - (name꞉ Identifier): "A" # (9..10) + - (leading_trivia꞉ Whitespace): " " # (10..11) + - (open_brace꞉ OpenBrace): "{" # (11..12) + - (trailing_trivia꞉ EndOfLine): "\n" # (12..13) + - (members꞉ ContractMembers): # "\tfunction a() {\n\t\t2 + (" (13..36) + - (item꞉ ContractMember) ► (variant꞉ FunctionDefinition): # "\tfunction a() {\n\t\t2 + (" (13..36) + - (leading_trivia꞉ Whitespace): "\t" # (13..14) + - (function_keyword꞉ FunctionKeyword): "function" # (14..22) + - (name꞉ FunctionName): # " a" (22..24) + - (leading_trivia꞉ Whitespace): " " # (22..23) + - (variant꞉ Identifier): "a" # (23..24) + - (parameters꞉ ParametersDeclaration): # "()" (24..26) + - (open_paren꞉ OpenParen): "(" # (24..25) + - (parameters꞉ Parameters): [] # (25..25) + - (close_paren꞉ CloseParen): ")" # (25..26) + - (attributes꞉ FunctionAttributes): [] # (26..26) + - (body꞉ FunctionBody) ► (variant꞉ Block): # " {\n\t\t2 + (" (26..36) + - (leading_trivia꞉ Whitespace): " " # (26..27) + - (open_brace꞉ OpenBrace): "{" # (27..28) + - (trailing_trivia꞉ EndOfLine): "\n" # (28..29) + - (statements꞉ Statements): # "\t\t2 +" (29..34) + - (item꞉ Statement) ► (variant꞉ ExpressionStatement) ► (expression꞉ Expression): # "\t\t2 +" (29..34) + - (variant꞉ DecimalNumberExpression): # "\t\t2" (29..32) + - (leading_trivia꞉ Whitespace): "\t\t" # (29..31) + - (literal꞉ DecimalLiteral): "2" # (31..32) + - (AdditiveExpression): # " +" (32..34) + - (leading_trivia꞉ Whitespace): " " # (32..33) + - (operator꞉ Plus): "+" # (33..34) + - (MISSING): "" # (34..34) + - (close_brace꞉ CloseBrace): " " # (34..35) + - (trailing_trivia꞉ EndOfLine): "(" # (35..36) + - (close_brace꞉ CloseBrace): "\n" # (36..37) + - (trailing_trivia꞉ EndOfLine): "\t" # (37..38) diff --git a/crates/testlang/outputs/cargo/slang_testlang/src/generated/language/parser_support/sequence_helper.rs b/crates/testlang/outputs/cargo/slang_testlang/src/generated/language/parser_support/sequence_helper.rs index 4d46325e81..d2819a363f 100644 --- a/crates/testlang/outputs/cargo/slang_testlang/src/generated/language/parser_support/sequence_helper.rs +++ b/crates/testlang/outputs/cargo/slang_testlang/src/generated/language/parser_support/sequence_helper.rs @@ -118,8 +118,17 @@ impl SequenceHelper { })); } - (ParserResult::PrattOperatorMatch(_), ParserResult::SkippedUntil(_)) => - unreachable!("Error recovery happens outside precedence parsing"), + (ParserResult::PrattOperatorMatch(running), ParserResult::SkippedUntil(skipped)) => { + let nodes: Vec<_> = std::mem::take(&mut running.elements) + .into_iter() + .flat_map(PrattElement::into_nodes) + .collect(); + + self.result = State::Running(ParserResult::SkippedUntil(SkippedUntil { + nodes, + ..skipped + })); + } // Try to recover until we hit an expected boundary terminal. // If the sequence is unwinding, then a subsequent non-empty match must mean that