Author: Sam McCall Date: 2022-07-26T13:56:26+02:00 New Revision: 07b7ff983837dbc20749682673d09992f71b0c59
URL: https://github.com/llvm/llvm-project/commit/07b7ff983837dbc20749682673d09992f71b0c59 DIFF: https://github.com/llvm/llvm-project/commit/07b7ff983837dbc20749682673d09992f71b0c59.diff LOG: [pseudo] Allow opaque nodes to represent terminals This allows incomplete code such as `namespace foo {` to be modeled as a normal sequence with the missing } represented by an empty opaque node. Differential Revision: https://reviews.llvm.org/D130551 Added: Modified: clang-tools-extra/pseudo/lib/GLR.cpp clang-tools-extra/pseudo/unittests/GLRTest.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/pseudo/lib/GLR.cpp b/clang-tools-extra/pseudo/lib/GLR.cpp index ab230accdf8f8..10a94860ffc98 100644 --- a/clang-tools-extra/pseudo/lib/GLR.cpp +++ b/clang-tools-extra/pseudo/lib/GLR.cpp @@ -182,9 +182,13 @@ void glrRecover(llvm::ArrayRef<const GSS::Node *> OldHeads, for (const PlaceholderRecovery *Option : BestOptions) { const ForestNode &Placeholder = Params.Forest.createOpaque(Option->Symbol, RecoveryRange->Begin); - const GSS::Node *NewHead = Params.GSStack.addNode( - *Lang.Table.getGoToState(Option->RecoveryNode->State, Option->Symbol), - &Placeholder, {Option->RecoveryNode}); + LRTable::StateID OldState = Option->RecoveryNode->State; + LRTable::StateID NewState = + isToken(Option->Symbol) + ? *Lang.Table.getShiftState(OldState, Option->Symbol) + : *Lang.Table.getGoToState(OldState, Option->Symbol); + const GSS::Node *NewHead = + Params.GSStack.addNode(NewState, &Placeholder, {Option->RecoveryNode}); NewHeads.push_back(NewHead); } TokenIndex = RecoveryRange->End; diff --git a/clang-tools-extra/pseudo/unittests/GLRTest.cpp b/clang-tools-extra/pseudo/unittests/GLRTest.cpp index 5f87efec67044..7abf9295d1570 100644 --- a/clang-tools-extra/pseudo/unittests/GLRTest.cpp +++ b/clang-tools-extra/pseudo/unittests/GLRTest.cpp @@ -604,6 +604,28 @@ TEST_F(GLRTest, RecoveryEndToEnd) { "[ 5, end) └─} := tok[5]\n"); } +TEST_F(GLRTest, RecoverTerminal) { + build(R"bnf( + _ := stmt + + stmt := IDENTIFIER ; [recover=Skip] + )bnf"); + TestLang.Table = LRTable::buildSLR(TestLang.G); + TestLang.RecoveryStrategies.try_emplace( + extensionID("Skip"), + [](Token::Index Start, const TokenStream &) { return Start + 1; }); + clang::LangOptions LOptions; + TokenStream Tokens = cook(lex("foo", LOptions), LOptions); + + const ForestNode &Parsed = + glrParse({Tokens, Arena, GSStack}, id("stmt"), TestLang); + EXPECT_EQ(Parsed.dumpRecursive(TestLang.G), + "[ 0, end) stmt := IDENTIFIER ; [recover=Skip]\n" + "[ 0, 1) ├─IDENTIFIER := tok[0]\n" + "[ 1, end) └─; := <opaque>\n"); +} + + TEST_F(GLRTest, NoExplicitAccept) { build(R"bnf( _ := test _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits