hokein created this revision. hokein added a reviewer: sammccall. Herald added a project: All. hokein requested review of this revision. Herald added a subscriber: alextsao1999. Herald added a project: clang-tools-extra.
Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D132470 Files: clang-tools-extra/pseudo/lib/GLR.cpp clang-tools-extra/pseudo/unittests/GLRTest.cpp Index: clang-tools-extra/pseudo/unittests/GLRTest.cpp =================================================================== --- clang-tools-extra/pseudo/unittests/GLRTest.cpp +++ clang-tools-extra/pseudo/unittests/GLRTest.cpp @@ -708,6 +708,57 @@ "[ 1, end) └─body := <opaque>\n"); } +TEST_F(GLRTest, SpuriousRecoveryLeftAndUpwardsCase) { + build(R"bnf( + _ := compound-stmt EOF + + compound-stmt := { stmt-seq [recover=Braces] } + + stmt-seq := stmt + stmt-seq := stmt-seq stmt + + stmt := compound-stmt + stmt := IF ( expr [recover=Parentheses] ) IDENTIFIER + stmt := ; + )bnf"); + + TestLang.Table = LRTable::buildSLR(TestLang.G); + TestLang.RecoveryStrategies.try_emplace(extensionID("Braces"), recoverBraces); + TestLang.RecoveryStrategies.try_emplace( + extensionID("Parentheses"), + [](Token::Index Start, const TokenStream &Code) { + assert(Start > 0); + const Token &Left = Code.tokens()[Start - 1]; + assert(Left.Kind == tok::l_paren); + if (const auto *Right = Left.pair()) + return Code.index(*Right); + return Token::Invalid; + }); + clang::LangOptions LOptions; + TokenStream Tokens = cook(lex(R"cpp( + { ; + { if (id) ? } + } + )cpp", LOptions), LOptions); + pairBrackets(Tokens); + + const ForestNode &Parsed = + glrParse({Tokens, Arena, GSStack}, id("compound-stmt"), TestLang); + EXPECT_EQ(Parsed.dumpRecursive(TestLang.G), + "[ 0, end) compound-stmt := { stmt-seq [recover=Braces] }\n" + "[ 0, 1) ├─{ := tok[0]\n" + "[ 1, 9) ├─stmt-seq := stmt-seq stmt\n" + "[ 1, 2) │ ├─stmt-seq := stmt\n" + "[ 1, 2) │ │ └─stmt := ;\n" + "[ 1, 2) │ │ └─; := tok[1]\n" + "[ 2, 9) │ └─stmt := compound-stmt\n" + "[ 2, 9) │ └─compound-stmt := { stmt-seq [recover=Braces] }\n" + "[ 2, 3) │ ├─{ := tok[2]\n" + "[ 3, 8) │ ├─stmt-seq := <opaque>\n" + "[ 8, 9) │ └─} := tok[8]\n" + "[ 9, end) └─} := tok[9]\n"); +} + TEST_F(GLRTest, NoExplicitAccept) { build(R"bnf( _ := test EOF Index: clang-tools-extra/pseudo/lib/GLR.cpp =================================================================== --- clang-tools-extra/pseudo/lib/GLR.cpp +++ clang-tools-extra/pseudo/lib/GLR.cpp @@ -88,7 +88,6 @@ // For now, we have to take this into account when defining recovery rules. // (e.g. in the expr recovery above, stay inside the parentheses). // FIXME: find a more satisfying way to avoid such false recovery. - // FIXME: Add a test for spurious recovery once tests can define strategies. std::vector<const ForestNode *> Path; llvm::DenseSet<const GSS::Node *> Seen; auto WalkUp = [&](const GSS::Node *N, Token::Index NextTok, auto &WalkUp) {
Index: clang-tools-extra/pseudo/unittests/GLRTest.cpp =================================================================== --- clang-tools-extra/pseudo/unittests/GLRTest.cpp +++ clang-tools-extra/pseudo/unittests/GLRTest.cpp @@ -708,6 +708,57 @@ "[ 1, end) ââbody := <opaque>\n"); } +TEST_F(GLRTest, SpuriousRecoveryLeftAndUpwardsCase) { + build(R"bnf( + _ := compound-stmt EOF + + compound-stmt := { stmt-seq [recover=Braces] } + + stmt-seq := stmt + stmt-seq := stmt-seq stmt + + stmt := compound-stmt + stmt := IF ( expr [recover=Parentheses] ) IDENTIFIER + stmt := ; + )bnf"); + + TestLang.Table = LRTable::buildSLR(TestLang.G); + TestLang.RecoveryStrategies.try_emplace(extensionID("Braces"), recoverBraces); + TestLang.RecoveryStrategies.try_emplace( + extensionID("Parentheses"), + [](Token::Index Start, const TokenStream &Code) { + assert(Start > 0); + const Token &Left = Code.tokens()[Start - 1]; + assert(Left.Kind == tok::l_paren); + if (const auto *Right = Left.pair()) + return Code.index(*Right); + return Token::Invalid; + }); + clang::LangOptions LOptions; + TokenStream Tokens = cook(lex(R"cpp( + { ; + { if (id) ? } + } + )cpp", LOptions), LOptions); + pairBrackets(Tokens); + + const ForestNode &Parsed = + glrParse({Tokens, Arena, GSStack}, id("compound-stmt"), TestLang); + EXPECT_EQ(Parsed.dumpRecursive(TestLang.G), + "[ 0, end) compound-stmt := { stmt-seq [recover=Braces] }\n" + "[ 0, 1) ââ{ := tok[0]\n" + "[ 1, 9) ââstmt-seq := stmt-seq stmt\n" + "[ 1, 2) â ââstmt-seq := stmt\n" + "[ 1, 2) â â ââstmt := ;\n" + "[ 1, 2) â â ââ; := tok[1]\n" + "[ 2, 9) â ââstmt := compound-stmt\n" + "[ 2, 9) â ââcompound-stmt := { stmt-seq [recover=Braces] }\n" + "[ 2, 3) â ââ{ := tok[2]\n" + "[ 3, 8) â ââstmt-seq := <opaque>\n" + "[ 8, 9) â ââ} := tok[8]\n" + "[ 9, end) ââ} := tok[9]\n"); +} + TEST_F(GLRTest, NoExplicitAccept) { build(R"bnf( _ := test EOF Index: clang-tools-extra/pseudo/lib/GLR.cpp =================================================================== --- clang-tools-extra/pseudo/lib/GLR.cpp +++ clang-tools-extra/pseudo/lib/GLR.cpp @@ -88,7 +88,6 @@ // For now, we have to take this into account when defining recovery rules. // (e.g. in the expr recovery above, stay inside the parentheses). // FIXME: find a more satisfying way to avoid such false recovery. - // FIXME: Add a test for spurious recovery once tests can define strategies. std::vector<const ForestNode *> Path; llvm::DenseSet<const GSS::Node *> Seen; auto WalkUp = [&](const GSS::Node *N, Token::Index NextTok, auto &WalkUp) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits