diff --git a/C/SyntaxTree.cpp b/C/SyntaxTree.cpp index 4db503d4..2314bd46 100644 --- a/C/SyntaxTree.cpp +++ b/C/SyntaxTree.cpp @@ -251,18 +251,18 @@ void SyntaxTree::buildFor(SyntaxCategory syntaxCategory) return; auto disambiguationStrategy = Reparser::DisambiguationStrategy::UNSPECIFIED; - auto permitHeuristic = false; + auto allowHeuristics = false; switch (P->parseOptions_.treatmentOfAmbiguities()) { case ParseOptions::TreatmentOfAmbiguities::None: + for (const auto& diag : parser.releaseRetainedAmbiguityDiags()) + newDiagnostic(std::get<0>(diag), std::get<1>(diag)); return; - case ParseOptions::TreatmentOfAmbiguities::Diagnose: - for (const auto& diag : parser.releaseRetainedAmbiguityDiags()) - newDiagnostic(diag.first, diag.second); + case ParseOptions::TreatmentOfAmbiguities::Ignore: return; case ParseOptions::TreatmentOfAmbiguities::DisambiguateAlgorithmicallyOrHeuristically: - permitHeuristic = true; + allowHeuristics = true; [[fallthrough]]; case ParseOptions::TreatmentOfAmbiguities::DisambiguateAlgorithmically: { @@ -274,7 +274,7 @@ void SyntaxTree::buildFor(SyntaxCategory syntaxCategory) case ParseOptions::TreatmentOfAmbiguities::DisambiguateHeuristically: disambiguationStrategy = Reparser::DisambiguationStrategy::GuidelineImposition; - permitHeuristic = true; + allowHeuristics = true; break; default: @@ -286,8 +286,14 @@ void SyntaxTree::buildFor(SyntaxCategory syntaxCategory) Reparser reparser; reparser.setDisambiguationStrategy(disambiguationStrategy); - reparser.setPermitHeuristic(permitHeuristic); + reparser.setAllowHeuristics(allowHeuristics); reparser.reparse(this); + if (!reparser.eliminatedAllAmbiguities()) { + for (const auto& diag : parser.releaseRetainedAmbiguityDiags()) { + if (reparser.ambiguityPersists(std::get<2>(diag))) + newDiagnostic(std::get<0>(diag), std::get<1>(diag)); + } + } } const ParseOptions& SyntaxTree::parseOptions() const diff --git a/C/parser/DiagnosticsReporter_Parser.cpp b/C/parser/DiagnosticsReporter_Parser.cpp index ab3c0369..2a43edbc 100644 --- a/C/parser/DiagnosticsReporter_Parser.cpp +++ b/C/parser/DiagnosticsReporter_Parser.cpp @@ -20,6 +20,8 @@ #include "Parser.h" +#include "syntax/SyntaxNodes.h" + using namespace psy; using namespace C; @@ -101,7 +103,7 @@ std::string Parser::DiagnosticsReporter::joinTokenNames(const std::vectormightBacktrack()) + if (parser_->willBacktrack()) return; if (IDsForDelay_.find(desc.id()) != IDsForDelay_.end()) @@ -116,12 +118,14 @@ void Parser::DiagnosticsReporter::diagnoseDelayed() parser_->tree_->newDiagnostic(p.first, p.second); } -void Parser::DiagnosticsReporter::diagnoseAmbiguityButRetainIt(DiagnosticDescriptor&& desc) +void Parser::DiagnosticsReporter::diagnoseAmbiguityButRetainIt( + DiagnosticDescriptor&& desc, + const SyntaxNode* node) { - retainedAmbiguityDiags_.push_back(std::make_pair(desc, parser_->curTkIdx_ - 1)); + retainedAmbiguityDiags_.push_back(std::make_tuple(desc, parser_->curTkIdx_ - 1, node)); } -/* Generic */ +/* General */ void Parser::DiagnosticsReporter::ExpectedFeature(const std::string& name) { @@ -476,7 +480,8 @@ void Parser::DiagnosticsReporter::UnexpectedGNUExtensionFlag() /* Ambiguities */ -void Parser::DiagnosticsReporter::AmbiguousTypeNameOrExpressionAsTypeReference() +void Parser::DiagnosticsReporter::AmbiguousTypeNameOrExpressionAsTypeReference( + const AmbiguousTypeNameOrExpressionAsTypeReferenceSyntax* node) { std::string s = "ambiguous type name or expression `" + parser_->peek().valueText() @@ -487,10 +492,12 @@ void Parser::DiagnosticsReporter::AmbiguousTypeNameOrExpressionAsTypeReference() "[[ambiguous type name or expression]]", s, DiagnosticSeverity::Error, - DiagnosticCategory::Syntax)); + DiagnosticCategory::Syntax), + node); } -void Parser::DiagnosticsReporter::AmbiguousCastOrBinaryExpression() +void Parser::DiagnosticsReporter::AmbiguousCastOrBinaryExpression( + const AmbiguousCastOrBinaryExpressionSyntax* node) { std::string s = "ambiguous cast or binary expression `" + parser_->peek().valueText() @@ -501,10 +508,12 @@ void Parser::DiagnosticsReporter::AmbiguousCastOrBinaryExpression() "[[ambiguous cast or binary expression]]", s, DiagnosticSeverity::Error, - DiagnosticCategory::Syntax)); + DiagnosticCategory::Syntax), + node); } -void Parser::DiagnosticsReporter::AmbiguousExpressionOrDeclarationStatement() +void Parser::DiagnosticsReporter::AmbiguousExpressionOrDeclarationStatement( + const AmbiguousExpressionOrDeclarationStatementSyntax* node) { std::string s = "ambiguous expression- or declaration-statement `" + parser_->peek().valueText() @@ -515,5 +524,6 @@ void Parser::DiagnosticsReporter::AmbiguousExpressionOrDeclarationStatement() "[[ambiguous expression- or declaration-statement]]", s, DiagnosticSeverity::Error, - DiagnosticCategory::Syntax)); + DiagnosticCategory::Syntax), + node); } diff --git a/C/parser/ParseOptions.h b/C/parser/ParseOptions.h index 861eae0d..3a82dbd1 100644 --- a/C/parser/ParseOptions.h +++ b/C/parser/ParseOptions.h @@ -100,8 +100,8 @@ class PSY_C_API ParseOptions */ enum class TreatmentOfAmbiguities : std::uint8_t { - None, /**< No special treatment (ambiguities are preserved). */ - Diagnose, /**< Diagnose ambiguities. */ + None, /**< No special treatment: ambiguities are diagnosed (and preserved). */ + Ignore, /**< Ignore ambiguities. */ DisambiguateAlgorithmically, /**< Disambiguate ambiguities algorithmically. */ DisambiguateAlgorithmicallyOrHeuristically, /**< Disambiguate ambiguities algorithmically/heristically. */ DisambiguateHeuristically, /**< Disambiguate ambiguities heuristically. */ diff --git a/C/parser/Parser.cpp b/C/parser/Parser.cpp index 63d89358..b2bb2942 100644 --- a/C/parser/Parser.cpp +++ b/C/parser/Parser.cpp @@ -177,7 +177,7 @@ void Parser::skipTo(SyntaxKind tkK) /** * Whether the parser is in backtracking mode. */ -bool Parser::mightBacktrack() const +bool Parser::willBacktrack() const { return static_cast(backtracker_); } @@ -200,8 +200,9 @@ bool Parser::detectedAnyAmbiguity() const } std::vector< - std::pair> Parser::releaseRetainedAmbiguityDiags() const + std::tuple> Parser::releaseRetainedAmbiguityDiags() const { return std::move(diagReporter_.retainedAmbiguityDiags_); } diff --git a/C/parser/Parser.h b/C/parser/Parser.h index f4937c96..aecad62f 100644 --- a/C/parser/Parser.h +++ b/C/parser/Parser.h @@ -92,7 +92,7 @@ class PSY_C_NON_API Parser }; friend struct Backtracker; const Backtracker* backtracker_; - bool mightBacktrack() const; + bool willBacktrack() const; struct DiagnosticsReporter { @@ -106,11 +106,14 @@ class PSY_C_NON_API Parser std::unordered_set IDsForDelay_; std::vector> delayedDiags_; - std::vector> retainedAmbiguityDiags_; + std::vector> retainedAmbiguityDiags_; void diagnose(DiagnosticDescriptor&& desc); void diagnoseDelayed(); - void diagnoseAmbiguityButRetainIt(DiagnosticDescriptor&& desc); + void diagnoseAmbiguityButRetainIt(DiagnosticDescriptor&& desc, const SyntaxNode* node); /* General */ void ExpectedFeature(const std::string& name); @@ -187,9 +190,12 @@ class PSY_C_NON_API Parser static const std::string ID_of_UnexpectedGNUExtensionFlag; /* Ambiguities */ - void AmbiguousTypeNameOrExpressionAsTypeReference(); - void AmbiguousCastOrBinaryExpression(); - void AmbiguousExpressionOrDeclarationStatement(); + void AmbiguousTypeNameOrExpressionAsTypeReference( + const AmbiguousTypeNameOrExpressionAsTypeReferenceSyntax*); + void AmbiguousCastOrBinaryExpression( + const AmbiguousCastOrBinaryExpressionSyntax*); + void AmbiguousExpressionOrDeclarationStatement( + const AmbiguousExpressionOrDeclarationStatementSyntax*); static const std::string ID_of_AmbiguousTypeNameOrExpressionAsTypeReference; static const std::string ID_of_AmbiguousCastOrBinaryExpression; @@ -200,8 +206,9 @@ class PSY_C_NON_API Parser DiagnosticsReporter diagReporter_; std::vector< - std::pair> releaseRetainedAmbiguityDiags() const; + std::tuple> releaseRetainedAmbiguityDiags() const; struct DiagnosticsReporterDelayer { diff --git a/C/parser/Parser_Common.cpp b/C/parser/Parser_Common.cpp index 8aab7788..9cd72855 100644 --- a/C/parser/Parser_Common.cpp +++ b/C/parser/Parser_Common.cpp @@ -113,10 +113,10 @@ void Parser::maybeAmbiguateTypeReference(TypeReferenceSyntax*& tyRef) tyNameAsTyRef->typeName_ = tyName; tyNameAsTyRef->closeParenTkIdx_ = parenExpr->closeParenTkIdx_; - auto ambiTyRef = makeNode(); - tyRef = ambiTyRef; - ambiTyRef->exprAsTyRef_ = exprAsTyRef; - ambiTyRef->tyNameAsTyRef_ = tyNameAsTyRef; + auto ambigTyRef = makeNode(); + tyRef = ambigTyRef; + ambigTyRef->exprAsTyRef_ = exprAsTyRef; + ambigTyRef->tyNameAsTyRef_ = tyNameAsTyRef; - diagReporter_.AmbiguousTypeNameOrExpressionAsTypeReference(); + diagReporter_.AmbiguousTypeNameOrExpressionAsTypeReference(ambigTyRef); } diff --git a/C/parser/Parser_Expressions.cpp b/C/parser/Parser_Expressions.cpp index 5d9c1c86..20510776 100644 --- a/C/parser/Parser_Expressions.cpp +++ b/C/parser/Parser_Expressions.cpp @@ -1221,12 +1221,12 @@ void Parser::maybeAmbiguateCastExpression(ExpressionSyntax*& expr) binExpr->oprtrTkIdx_ = prefixExpr->oprtrTkIdx_; binExpr->rightExpr_ = prefixExpr->expr_; - auto ambiExpr = makeNode(AmbiguousCastOrBinaryExpression); - expr = ambiExpr; - ambiExpr->castExpr_ = castExpr; - ambiExpr->binExpr_ = binExpr; + auto ambigExpr = makeNode(AmbiguousCastOrBinaryExpression); + expr = ambigExpr; + ambigExpr->castExpr_ = castExpr; + ambigExpr->binExpr_ = binExpr; - diagReporter_.AmbiguousCastOrBinaryExpression(); + diagReporter_.AmbiguousCastOrBinaryExpression(ambigExpr); } /* N-ary */ diff --git a/C/parser/Parser_Statements.cpp b/C/parser/Parser_Statements.cpp index 7cd53cdc..29fa8766 100644 --- a/C/parser/Parser_Statements.cpp +++ b/C/parser/Parser_Statements.cpp @@ -270,14 +270,14 @@ void Parser::maybeAmbiguateStatement(StatementSyntax*& stmt) varDecl->semicolonTkIdx_ = exprStmt->semicolonTkIdx_; varDecl->decltors_ = makeNode(decltor); - auto ambiStmt = makeNode(stmtK); - stmt = ambiStmt; - ambiStmt->exprStmt_ = exprStmt; + auto ambigStmt = makeNode(stmtK); + stmt = ambigStmt; + ambigStmt->exprStmt_ = exprStmt; auto declStmt = makeNode(); declStmt->decl_ = varDecl; - ambiStmt->declStmt_ = declStmt; + ambigStmt->declStmt_ = declStmt; - diagReporter_.AmbiguousExpressionOrDeclarationStatement(); + diagReporter_.AmbiguousExpressionOrDeclarationStatement(ambigStmt); } /** diff --git a/C/reparser/Disambiguator.cpp b/C/reparser/Disambiguator.cpp index a9ca1aa6..7738d294 100644 --- a/C/reparser/Disambiguator.cpp +++ b/C/reparser/Disambiguator.cpp @@ -33,14 +33,18 @@ Disambiguator::~Disambiguator() Disambiguator::Disambiguator(SyntaxTree* tree) : SyntaxVisitor(tree) - , pendingAmbigs_(0) {} -unsigned int Disambiguator::disambiguate() +bool Disambiguator::disambiguate() { visit(tree_->root()); - return pendingAmbigs_; + return inconclusiveDisambigs_.empty(); +} + +std::vector Disambiguator::persistentAmbiguities() const +{ + return inconclusiveDisambigs_; } template @@ -63,7 +67,7 @@ SyntaxVisitor::Action Disambiguator::visitMaybeAmbiguousExpression(ExprT* const& break; case Disambiguation::Inconclusive: - ++pendingAmbigs_; + inconclusiveDisambigs_.push_back(node); break; default: @@ -101,7 +105,7 @@ SyntaxVisitor::Action Disambiguator::visitMaybeAmbiguousStatement(StmtT* const& break; case Disambiguation::Inconclusive: - ++pendingAmbigs_; + inconclusiveDisambigs_.push_back(node); break; default: @@ -138,7 +142,7 @@ SyntaxVisitor::Action Disambiguator::visitMaybeAmbiguousTypeReference(TypeRefT* break; case Disambiguation::Inconclusive: - ++pendingAmbigs_; + inconclusiveDisambigs_.push_back(node); break; default: diff --git a/C/reparser/Disambiguator.h b/C/reparser/Disambiguator.h index 3e9c68fc..cffc3b96 100644 --- a/C/reparser/Disambiguator.h +++ b/C/reparser/Disambiguator.h @@ -29,6 +29,7 @@ #include #include +#include namespace psy { namespace C { @@ -41,7 +42,9 @@ class PSY_C_NON_API Disambiguator : public SyntaxVisitor PSY_INTERNAL_AND_RESTRICTED: PSY_GRANT_ACCESS(Reparser); - unsigned int disambiguate(); + bool disambiguate(); + + std::vector persistentAmbiguities() const; PSY_INTERNAL_AND_EXTENSIBLE: Disambiguator(SyntaxTree* tree); @@ -66,7 +69,7 @@ class PSY_C_NON_API Disambiguator : public SyntaxVisitor template Action visitMaybeAmbiguousStatement(StmtT* const&); template Action visitMaybeAmbiguousTypeReference(TypeRefT* const&); - unsigned int pendingAmbigs_; + std::vector inconclusiveDisambigs_; protected: //--------------// diff --git a/C/reparser/Disambiguator_SyntaxCorrelation.cpp b/C/reparser/Disambiguator_SyntaxCorrelation.cpp index b32504b3..a03a7647 100644 --- a/C/reparser/Disambiguator_SyntaxCorrelation.cpp +++ b/C/reparser/Disambiguator_SyntaxCorrelation.cpp @@ -30,11 +30,10 @@ using namespace psy; using namespace C; -SyntaxCorrelationDisambiguator::SyntaxCorrelationDisambiguator(SyntaxTree* tree) +SyntaxCorrelationDisambiguator::SyntaxCorrelationDisambiguator( + SyntaxTree* tree, + std::unique_ptr catalog) : Disambiguator(tree) -{} - -void SyntaxCorrelationDisambiguator::acquireCatalog(std::unique_ptr catalog) { catalog_ = std::move(catalog); } diff --git a/C/reparser/Disambiguator_SyntaxCorrelation.h b/C/reparser/Disambiguator_SyntaxCorrelation.h index 1844cdb3..d37da607 100644 --- a/C/reparser/Disambiguator_SyntaxCorrelation.h +++ b/C/reparser/Disambiguator_SyntaxCorrelation.h @@ -38,9 +38,7 @@ class PSY_C_NON_API SyntaxCorrelationDisambiguator final : public Disambiguator PSY_INTERNAL_AND_RESTRICTED: PSY_GRANT_ACCESS(Reparser); - SyntaxCorrelationDisambiguator(SyntaxTree* tree); - - void acquireCatalog(std::unique_ptr catalog); + SyntaxCorrelationDisambiguator(SyntaxTree* tree, std::unique_ptr catalog); private: std::unique_ptr catalog_; diff --git a/C/reparser/Reparser.cpp b/C/reparser/Reparser.cpp index e52aa717..dbf286a7 100644 --- a/C/reparser/Reparser.cpp +++ b/C/reparser/Reparser.cpp @@ -35,7 +35,7 @@ using namespace C; Reparser::Reparser() : disambigStrategy_(DisambiguationStrategy::SyntaxCorrelation) - , permitHeuristic_(false) + , allowHeuristics_(false) {} void Reparser::setDisambiguationStrategy(DisambiguationStrategy strategy) @@ -43,9 +43,23 @@ void Reparser::setDisambiguationStrategy(DisambiguationStrategy strategy) disambigStrategy_ = strategy; } -void Reparser::setPermitHeuristic(bool heuristic) +void Reparser::setAllowHeuristics(bool allow) { - permitHeuristic_ = heuristic; + allowHeuristics_ = allow; +} + +bool Reparser::eliminatedAllAmbiguities() const +{ + return persistentAmbigs_.empty(); +} + +bool Reparser::ambiguityPersists(const SyntaxNode* node) const +{ + for (auto ambig : persistentAmbigs_) { + if (node == ambig) + return true; + } + return false; } void Reparser::reparse(SyntaxTree* tree) @@ -57,12 +71,11 @@ void Reparser::reparse(SyntaxTree* tree) NameCataloger cataloger(tree); auto catalog = cataloger.catalogNamesWithinNode(tree->root()); - + std::unique_ptr disambiguator_; switch (disambigStrategy_) { case Reparser::DisambiguationStrategy::SyntaxCorrelation: { - SyntaxCorrelationDisambiguator disambiguator(tree); - disambiguator.acquireCatalog(std::move(catalog)); - disambiguator.disambiguate(); + disambiguator_.reset( + new SyntaxCorrelationDisambiguator(tree, std::move(catalog))); break; } @@ -71,6 +84,13 @@ void Reparser::reparse(SyntaxTree* tree) break; default: - PSY_ESCAPE(); + PSY_ESCAPE_VIA_RETURN(); + } + + auto ok = disambiguator_->disambiguate(); + if (!ok) { + const auto& persistentAmbigs = disambiguator_->persistentAmbiguities(); + for (const auto& ambig : persistentAmbigs) + persistentAmbigs_.insert(ambig); } } diff --git a/C/reparser/Reparser.h b/C/reparser/Reparser.h index 668a085b..023945fc 100644 --- a/C/reparser/Reparser.h +++ b/C/reparser/Reparser.h @@ -28,6 +28,7 @@ #include "../common/infra/InternalAccess.h" +#include #include namespace psy { @@ -51,14 +52,17 @@ class PSY_C_NON_API Reparser }; void setDisambiguationStrategy(DisambiguationStrategy strategy); - - void setPermitHeuristic(bool heuristic); + void setAllowHeuristics(bool allow); void reparse(SyntaxTree* tree); + bool eliminatedAllAmbiguities() const; + bool ambiguityPersists(const SyntaxNode* node) const; + private: DisambiguationStrategy disambigStrategy_; - bool permitHeuristic_; + bool allowHeuristics_; + std::unordered_set persistentAmbigs_; }; } // C diff --git a/C/tests/TestSuite_Internals.cpp b/C/tests/TestSuite_Internals.cpp index e11a3531..fc6403cd 100644 --- a/C/tests/TestSuite_Internals.cpp +++ b/C/tests/TestSuite_Internals.cpp @@ -196,7 +196,7 @@ void InternalsTestSuite::parse(std::string source, ParseOptions parseOpts; if (X.containsAmbiguity_) - parseOpts.setTreatmentOfAmbiguities(ParseOptions::TreatmentOfAmbiguities::None); + parseOpts.setTreatmentOfAmbiguities(ParseOptions::TreatmentOfAmbiguities::Ignore); tree_ = SyntaxTree::parseText(text, TextPreprocessingState::Unknown, diff --git a/cnippet/CompilerFrontend_C.cpp b/cnippet/CompilerFrontend_C.cpp index 6ff6a49b..c30494ad 100644 --- a/cnippet/CompilerFrontend_C.cpp +++ b/cnippet/CompilerFrontend_C.cpp @@ -137,8 +137,6 @@ int CCompilerFrontend::constructSyntaxTree(const std::string& srcText, if (!config_->ParseOptions_TreatmentOfAmbiguities.empty()) { if (config_->ParseOptions_TreatmentOfAmbiguities == "None") parseOpts.setTreatmentOfAmbiguities(ParseOptions::TreatmentOfAmbiguities::None); - else if (config_->ParseOptions_TreatmentOfAmbiguities == "Diagnose") - parseOpts.setTreatmentOfAmbiguities(ParseOptions::TreatmentOfAmbiguities::Diagnose); else if (config_->ParseOptions_TreatmentOfAmbiguities == "DisambiguateAlgorithmically") parseOpts.setTreatmentOfAmbiguities(ParseOptions::TreatmentOfAmbiguities::DisambiguateAlgorithmically); else if (config_->ParseOptions_TreatmentOfAmbiguities == "DisambiguateAlgorithmicallyOrHeuristically") diff --git a/cnippet/Configuration_C.cpp b/cnippet/Configuration_C.cpp index e4918743..7e37fba3 100644 --- a/cnippet/Configuration_C.cpp +++ b/cnippet/Configuration_C.cpp @@ -71,7 +71,7 @@ void ConfigurationForC::extend(cxxopts::Options& cmdLineOpts) "Treatment of ambiguities.", cxxopts::value() ->default_value("DisambiguateAlgorithmicallyOrHeuristically"), - "") + "") /* Type inference */ ("C-infer", "Infer the definition of missing types.")