Skip to content

Commit

Permalink
be aware of ambiguities that persist after reparse
Browse files Browse the repository at this point in the history
  • Loading branch information
ltcmelo committed Jan 2, 2024
1 parent af9bcf7 commit d9f6769
Show file tree
Hide file tree
Showing 17 changed files with 125 additions and 75 deletions.
20 changes: 13 additions & 7 deletions C/SyntaxTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -274,7 +274,7 @@ void SyntaxTree::buildFor(SyntaxCategory syntaxCategory)

case ParseOptions::TreatmentOfAmbiguities::DisambiguateHeuristically:
disambiguationStrategy = Reparser::DisambiguationStrategy::GuidelineImposition;
permitHeuristic = true;
allowHeuristics = true;
break;

default:
Expand All @@ -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
Expand Down
30 changes: 20 additions & 10 deletions C/parser/DiagnosticsReporter_Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

#include "Parser.h"

#include "syntax/SyntaxNodes.h"

using namespace psy;
using namespace C;

Expand Down Expand Up @@ -101,7 +103,7 @@ std::string Parser::DiagnosticsReporter::joinTokenNames(const std::vector<Syntax

void Parser::DiagnosticsReporter::diagnose(DiagnosticDescriptor&& desc)
{
if (parser_->mightBacktrack())
if (parser_->willBacktrack())
return;

if (IDsForDelay_.find(desc.id()) != IDsForDelay_.end())
Expand All @@ -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)
{
Expand Down Expand Up @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -515,5 +524,6 @@ void Parser::DiagnosticsReporter::AmbiguousExpressionOrDeclarationStatement()
"[[ambiguous expression- or declaration-statement]]",
s,
DiagnosticSeverity::Error,
DiagnosticCategory::Syntax));
DiagnosticCategory::Syntax),
node);
}
4 changes: 2 additions & 2 deletions C/parser/ParseOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
7 changes: 4 additions & 3 deletions C/parser/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool>(backtracker_);
}
Expand All @@ -200,8 +200,9 @@ bool Parser::detectedAnyAmbiguity() const
}

std::vector<
std::pair<DiagnosticDescriptor,
LexedTokens::IndexType>> Parser::releaseRetainedAmbiguityDiags() const
std::tuple<DiagnosticDescriptor,
LexedTokens::IndexType,
const SyntaxNode*>> Parser::releaseRetainedAmbiguityDiags() const
{
return std::move(diagReporter_.retainedAmbiguityDiags_);
}
Expand Down
23 changes: 15 additions & 8 deletions C/parser/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class PSY_C_NON_API Parser
};
friend struct Backtracker;
const Backtracker* backtracker_;
bool mightBacktrack() const;
bool willBacktrack() const;

struct DiagnosticsReporter
{
Expand All @@ -106,11 +106,14 @@ class PSY_C_NON_API Parser

std::unordered_set<std::string> IDsForDelay_;
std::vector<std::pair<DiagnosticDescriptor, LexedTokens::IndexType>> delayedDiags_;
std::vector<std::pair<DiagnosticDescriptor, LexedTokens::IndexType>> retainedAmbiguityDiags_;
std::vector<std::tuple<
DiagnosticDescriptor,
LexedTokens::IndexType,
const SyntaxNode*>> 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);
Expand Down Expand Up @@ -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;
Expand All @@ -200,8 +206,9 @@ class PSY_C_NON_API Parser
DiagnosticsReporter diagReporter_;

std::vector<
std::pair<DiagnosticDescriptor,
LexedTokens::IndexType>> releaseRetainedAmbiguityDiags() const;
std::tuple<DiagnosticDescriptor,
LexedTokens::IndexType,
const SyntaxNode*>> releaseRetainedAmbiguityDiags() const;

struct DiagnosticsReporterDelayer
{
Expand Down
10 changes: 5 additions & 5 deletions C/parser/Parser_Common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,10 @@ void Parser::maybeAmbiguateTypeReference(TypeReferenceSyntax*& tyRef)
tyNameAsTyRef->typeName_ = tyName;
tyNameAsTyRef->closeParenTkIdx_ = parenExpr->closeParenTkIdx_;

auto ambiTyRef = makeNode<AmbiguousTypeNameOrExpressionAsTypeReferenceSyntax>();
tyRef = ambiTyRef;
ambiTyRef->exprAsTyRef_ = exprAsTyRef;
ambiTyRef->tyNameAsTyRef_ = tyNameAsTyRef;
auto ambigTyRef = makeNode<AmbiguousTypeNameOrExpressionAsTypeReferenceSyntax>();
tyRef = ambigTyRef;
ambigTyRef->exprAsTyRef_ = exprAsTyRef;
ambigTyRef->tyNameAsTyRef_ = tyNameAsTyRef;

diagReporter_.AmbiguousTypeNameOrExpressionAsTypeReference();
diagReporter_.AmbiguousTypeNameOrExpressionAsTypeReference(ambigTyRef);
}
10 changes: 5 additions & 5 deletions C/parser/Parser_Expressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1221,12 +1221,12 @@ void Parser::maybeAmbiguateCastExpression(ExpressionSyntax*& expr)
binExpr->oprtrTkIdx_ = prefixExpr->oprtrTkIdx_;
binExpr->rightExpr_ = prefixExpr->expr_;

auto ambiExpr = makeNode<AmbiguousCastOrBinaryExpressionSyntax>(AmbiguousCastOrBinaryExpression);
expr = ambiExpr;
ambiExpr->castExpr_ = castExpr;
ambiExpr->binExpr_ = binExpr;
auto ambigExpr = makeNode<AmbiguousCastOrBinaryExpressionSyntax>(AmbiguousCastOrBinaryExpression);
expr = ambigExpr;
ambigExpr->castExpr_ = castExpr;
ambigExpr->binExpr_ = binExpr;

diagReporter_.AmbiguousCastOrBinaryExpression();
diagReporter_.AmbiguousCastOrBinaryExpression(ambigExpr);
}

/* N-ary */
Expand Down
10 changes: 5 additions & 5 deletions C/parser/Parser_Statements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,14 +270,14 @@ void Parser::maybeAmbiguateStatement(StatementSyntax*& stmt)
varDecl->semicolonTkIdx_ = exprStmt->semicolonTkIdx_;
varDecl->decltors_ = makeNode<DeclaratorListSyntax>(decltor);

auto ambiStmt = makeNode<AmbiguousExpressionOrDeclarationStatementSyntax>(stmtK);
stmt = ambiStmt;
ambiStmt->exprStmt_ = exprStmt;
auto ambigStmt = makeNode<AmbiguousExpressionOrDeclarationStatementSyntax>(stmtK);
stmt = ambigStmt;
ambigStmt->exprStmt_ = exprStmt;
auto declStmt = makeNode<DeclarationStatementSyntax>();
declStmt->decl_ = varDecl;
ambiStmt->declStmt_ = declStmt;
ambigStmt->declStmt_ = declStmt;

diagReporter_.AmbiguousExpressionOrDeclarationStatement();
diagReporter_.AmbiguousExpressionOrDeclarationStatement(ambigStmt);
}

/**
Expand Down
16 changes: 10 additions & 6 deletions C/reparser/Disambiguator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<const SyntaxNode*> Disambiguator::persistentAmbiguities() const
{
return inconclusiveDisambigs_;
}

template <class ExprT>
Expand All @@ -63,7 +67,7 @@ SyntaxVisitor::Action Disambiguator::visitMaybeAmbiguousExpression(ExprT* const&
break;

case Disambiguation::Inconclusive:
++pendingAmbigs_;
inconclusiveDisambigs_.push_back(node);
break;

default:
Expand Down Expand Up @@ -101,7 +105,7 @@ SyntaxVisitor::Action Disambiguator::visitMaybeAmbiguousStatement(StmtT* const&
break;

case Disambiguation::Inconclusive:
++pendingAmbigs_;
inconclusiveDisambigs_.push_back(node);
break;

default:
Expand Down Expand Up @@ -138,7 +142,7 @@ SyntaxVisitor::Action Disambiguator::visitMaybeAmbiguousTypeReference(TypeRefT*
break;

case Disambiguation::Inconclusive:
++pendingAmbigs_;
inconclusiveDisambigs_.push_back(node);
break;

default:
Expand Down
7 changes: 5 additions & 2 deletions C/reparser/Disambiguator.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include <cstdint>
#include <string>
#include <vector>

namespace psy {
namespace C {
Expand All @@ -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<const SyntaxNode*> persistentAmbiguities() const;

PSY_INTERNAL_AND_EXTENSIBLE:
Disambiguator(SyntaxTree* tree);
Expand All @@ -66,7 +69,7 @@ class PSY_C_NON_API Disambiguator : public SyntaxVisitor
template <class StmtT> Action visitMaybeAmbiguousStatement(StmtT* const&);
template <class TypeRefT> Action visitMaybeAmbiguousTypeReference(TypeRefT* const&);

unsigned int pendingAmbigs_;
std::vector<const SyntaxNode*> inconclusiveDisambigs_;

protected:
//--------------//
Expand Down
7 changes: 3 additions & 4 deletions C/reparser/Disambiguator_SyntaxCorrelation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@
using namespace psy;
using namespace C;

SyntaxCorrelationDisambiguator::SyntaxCorrelationDisambiguator(SyntaxTree* tree)
SyntaxCorrelationDisambiguator::SyntaxCorrelationDisambiguator(
SyntaxTree* tree,
std::unique_ptr<NameCatalog> catalog)
: Disambiguator(tree)
{}

void SyntaxCorrelationDisambiguator::acquireCatalog(std::unique_ptr<NameCatalog> catalog)
{
catalog_ = std::move(catalog);
}
Expand Down
4 changes: 1 addition & 3 deletions C/reparser/Disambiguator_SyntaxCorrelation.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<NameCatalog> catalog);
SyntaxCorrelationDisambiguator(SyntaxTree* tree, std::unique_ptr<NameCatalog> catalog);

private:
std::unique_ptr<NameCatalog> catalog_;
Expand Down
Loading

0 comments on commit d9f6769

Please sign in to comment.