diff --git a/clang-tools-extra/pseudo/include/clang-pseudo/GLR.h b/clang-tools-extra/pseudo/include/clang-pseudo/GLR.h --- a/clang-tools-extra/pseudo/include/clang-pseudo/GLR.h +++ b/clang-tools-extra/pseudo/include/clang-pseudo/GLR.h @@ -122,6 +122,9 @@ // Arena for data structure used by the GLR algorithm. ForestArena &Forest; // Storage for the output forest. GSS &GSStack; // Storage for parsing stacks. + + // If not null, store the token indices that trigger the error-recovery. + std::vector *FailingPoints = nullptr; }; // Parses the given token stream as the start symbol with the GLR algorithm, diff --git a/clang-tools-extra/pseudo/lib/GLR.cpp b/clang-tools-extra/pseudo/lib/GLR.cpp --- a/clang-tools-extra/pseudo/lib/GLR.cpp +++ b/clang-tools-extra/pseudo/lib/GLR.cpp @@ -646,7 +646,8 @@ "Re-reducing without lookahead.\n"); Heads.resize(HeadsPartition); Reduce(Heads, /*allow all reductions*/ tokenSymbol(tok::unknown)); - + if (Params.FailingPoints) + Params.FailingPoints->push_back(I); glrRecover(Heads, I, Params, Lang, NextHeads); assert(!NextHeads.empty() && "no fallback recovery strategy!" ); } else diff --git a/clang-tools-extra/pseudo/tool/ClangPseudo.cpp b/clang-tools-extra/pseudo/tool/ClangPseudo.cpp --- a/clang-tools-extra/pseudo/tool/ClangPseudo.cpp +++ b/clang-tools-extra/pseudo/tool/ClangPseudo.cpp @@ -153,12 +153,26 @@ "The start symbol {0} doesn't exit in the grammar!\n", StartSymbol); return 2; } - auto &Root = - glrParse(clang::pseudo::ParseParams{*ParseableStream, Arena, GSS}, - *StartSymID, Lang); + std::vector FailingPoints; + auto &Root = glrParse(clang::pseudo::ParseParams{*ParseableStream, Arena, + GSS, &FailingPoints}, + *StartSymID, Lang); if (PrintForest) llvm::outs() << Root.dumpRecursive(Lang.G, /*Abbreviated=*/ForestAbbrev); - + if (!FailingPoints.empty()) { + llvm::for_each(FailingPoints, [&](Token::Index Pos) { + if (Pos >= ParseableStream->tokens().size()) + return; + const auto &T = ParseableStream->tokens()[Pos]; + std::string LineCode; + llvm::for_each(ParseableStream->tokens(), [&](const Token &E) { + if (E.Line == T.Line) + LineCode += (" " + E.text().str()); + }); + llvm::outs() << llvm::formatv("Error on parsing Line {0}: {1}\n", + T.Line + 1, LineCode); + }); + } if (HTMLForest.getNumOccurrences()) { std::error_code EC; llvm::raw_fd_ostream HTMLOut(HTMLForest, EC);