Skip to content

Commit

Permalink
- Fix for Issue #21: If not allowed after switch statement.
Browse files Browse the repository at this point in the history
- String bitset initializer length must match the bitset width.
  • Loading branch information
steleman committed Nov 13, 2023
1 parent c7609a4 commit b494a38
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 8 deletions.
12 changes: 9 additions & 3 deletions include/qasm/AST/ASTIfStatementTracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,9 @@ class ASTIfStatementTracker : public ASTBase {
CIF = IL.Size() ? IL.back() : nullptr;
}

void CheckDeclarationContext();
void CheckDeclarationContext() const ;

void CheckDeclarationContext(const ASTStatementList* SL) const;

void RemoveOutOfScope(ASTIfStatementNode* IFN);

Expand Down Expand Up @@ -432,7 +434,9 @@ class ASTElseIfStatementTracker : public ASTBase {
ISCQ.pop_back();
}

void CheckDeclarationContext();
void CheckDeclarationContext() const;

void CheckDeclarationContext(const ASTStatementList* SL) const;

void RemoveOutOfScope(ASTElseIfStatementNode* EIN);

Expand Down Expand Up @@ -560,7 +564,9 @@ class ASTElseStatementTracker : public ASTBase {
CIF = IL.Size() ? IL.back() : nullptr;
}

void CheckDeclarationContext();
void CheckDeclarationContext() const;

void CheckDeclarationContext(const ASTStatementList* SL) const;

void RemoveOutOfScope(ASTElseStatementNode* ESN);

Expand Down
116 changes: 113 additions & 3 deletions lib/AST/ASTIfStatementTracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ std::deque<unsigned> ASTElseStatementTracker::ISCQ;
std::map<unsigned, ASTStatementList*> ASTElseStatementTracker::ESM;

void
ASTIfStatementTracker::CheckDeclarationContext() {
ASTIfStatementTracker::CheckDeclarationContext() const {
const ASTDeclarationContext* CTX =
ASTDeclarationContextTracker::Instance().GetCurrentContext();
assert(CTX && "Could not obtain a valid ASTDeclarationContext!");
Expand Down Expand Up @@ -93,6 +93,9 @@ ASTIfStatementTracker::CheckDeclarationContext() {
case ASTTypeElseStatement:
return;
break;
case ASTTypeSwitchStatement:
return;
break;
default:
break;
}
Expand All @@ -105,7 +108,42 @@ ASTIfStatementTracker::CheckDeclarationContext() {
}

void
ASTElseIfStatementTracker::CheckDeclarationContext() {
ASTIfStatementTracker::CheckDeclarationContext(const ASTStatementList* SL) const {
assert(SL && "Invalid ASTStatementList argument!");

const ASTDeclarationContext* DCX = nullptr;
for (ASTStatementList::const_iterator I = SL->begin(); I != SL->end(); ++I) {
if (const ASTIfStatementNode* ISN = dynamic_cast<const ASTIfStatementNode*>(*I)) {
if (ISN->GetASTType() == ASTTypeIfStatement) {
DCX = ISN->GetDeclarationContext();
assert(DCX && "Could not obtain a valid ASTDeclarationContext!");

switch (DCX->GetContextType()) {
case ASTTypeCaseStatement:
case ASTTypeDefaultStatement:
ASTIfStatementTracker::Instance().Erase(ISN);
ASTElseIfStatementTracker::Instance().Erase(ISN);
ASTElseStatementTracker::Instance().Erase(ISN);
break;
case ASTTypeSwitchStatement: {
std::stringstream M;
M << "An If Statement is not allowed here ("
<< PrintTypeEnum(DCX->GetContextType()) << ").";
QasmDiagnosticEmitter::Instance().EmitDiagnostic(
DIAGLineCounter::Instance().GetLocation(), M.str(), DiagLevel::Error);
return;
}
break;
default:
break;
}
}
}
}
}

void
ASTElseIfStatementTracker::CheckDeclarationContext() const {
const ASTDeclarationContext* CTX =
ASTDeclarationContextTracker::Instance().GetCurrentContext();
assert(CTX && "Could not obtain a valid ASTDeclarationContext!");
Expand Down Expand Up @@ -137,6 +175,9 @@ ASTElseIfStatementTracker::CheckDeclarationContext() {
case ASTTypeElseStatement:
return;
break;
case ASTTypeSwitchStatement:
return;
break;
default:
break;
}
Expand All @@ -149,7 +190,40 @@ ASTElseIfStatementTracker::CheckDeclarationContext() {
}

void
ASTElseStatementTracker::CheckDeclarationContext() {
ASTElseIfStatementTracker::CheckDeclarationContext(const ASTStatementList* SL) const {
assert(SL && "Invalid ASTStatementList argument!");

const ASTDeclarationContext* DCX = nullptr;
for (ASTStatementList::const_iterator I = SL->begin(); I != SL->end(); ++I) {
if (const ASTElseIfStatementNode* EIS =
dynamic_cast<const ASTElseIfStatementNode*>(*I)) {
if (EIS->GetASTType() == ASTTypeElseIfStatement) {
DCX = EIS->GetDeclarationContext();
assert(DCX && "Could not obtain a valid ASTDeclarationContext!");

switch (DCX->GetContextType()) {
case ASTTypeCaseStatement:
case ASTTypeDefaultStatement:
break;
case ASTTypeSwitchStatement: {
std::stringstream M;
M << "An ElseIf Statement is not allowed here ("
<< PrintTypeEnum(DCX->GetContextType()) << ").";
QasmDiagnosticEmitter::Instance().EmitDiagnostic(
DIAGLineCounter::Instance().GetLocation(), M.str(), DiagLevel::Error);
return;
}
break;
default:
break;
}
}
}
}
}

void
ASTElseStatementTracker::CheckDeclarationContext() const {
const ASTDeclarationContext* CTX =
ASTDeclarationContextTracker::Instance().GetCurrentContext();
assert(CTX && "Could not obtain a valid ASTDeclarationContext!");
Expand Down Expand Up @@ -181,6 +255,9 @@ ASTElseStatementTracker::CheckDeclarationContext() {
case ASTTypeElseStatement:
return;
break;
case ASTTypeSwitchStatement:
return;
break;
default:
break;
}
Expand All @@ -192,6 +269,39 @@ ASTElseStatementTracker::CheckDeclarationContext() {
DIAGLineCounter::Instance().GetLocation(), M.str(), DiagLevel::Error);
}

void
ASTElseStatementTracker::CheckDeclarationContext(const ASTStatementList* SL) const {
assert(SL && "Invalid ASTStatementList argument!");

const ASTDeclarationContext* DCX = nullptr;
for (ASTStatementList::const_iterator I = SL->begin(); I != SL->end(); ++I) {
if (const ASTElseStatementNode* ESN =
dynamic_cast<const ASTElseStatementNode*>(*I)) {
if (ESN->GetASTType() == ASTTypeElseStatement) {
DCX = ESN->GetDeclarationContext();
assert(DCX && "Could not obtain a valid ASTDeclarationContext!");

switch (DCX->GetContextType()) {
case ASTTypeCaseStatement:
case ASTTypeDefaultStatement:
break;
case ASTTypeSwitchStatement: {
std::stringstream M;
M << "An Else Statement is not allowed here ("
<< PrintTypeEnum(DCX->GetContextType()) << ").";
QasmDiagnosticEmitter::Instance().EmitDiagnostic(
DIAGLineCounter::Instance().GetLocation(), M.str(), DiagLevel::Error);
return;
}
break;
default:
break;
}
}
}
}
}

void ASTIfStatementTracker::RemoveOutOfScope(ASTIfStatementNode* IFN) {
assert(IFN && "Invalid ASTIfStatementNode argument!");

Expand Down
36 changes: 34 additions & 2 deletions lib/AST/ASTProductionFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2859,6 +2859,15 @@ ASTProductionFactory::ProductionRule_202(const ASTToken* TK,
const ASTStringNode* STN = dynamic_cast<const ASTStringNode*>(EN);
assert(STN && "Could not dynamic_cast to a valid ASTStringNode!");

std::string VS = ASTStringUtils::Instance().Sanitize(STN->GetValue());
if (VS.length() != Bits && VS.length() != 1U) {
std::stringstream M;
M << "Bitset initializer length does not match the bitset width.";
QasmDiagnosticEmitter::Instance().EmitDiagnostic(
DIAGLineCounter::Instance().GetLocation(EN), M.str(), DiagLevel::Error);
return ASTDeclarationNode::DeclarationError(Id, M.str());
}

DCBN = ASTBuilder::Instance().CreateASTCBitNode(Id, Bits,
STN->GetValue());
} else if (FromBitset || FromValue) {
Expand Down Expand Up @@ -26527,7 +26536,7 @@ ASTProductionFactory::ProductionRule_3010(const ASTToken* TK,

CTX->SetContextType(ASTTypeElseIfStatement);
ASTArgumentNodeBuilder::Instance().Clear();
ASTIfStatementNode* CIF = ASTElseIfStatementTracker::Instance().GetCurrentIf();
ASTIfStatementNode* CIF = ASTIfStatementTracker::Instance().GetCurrentIf();

if (!CIF) {
std::stringstream M;
Expand Down Expand Up @@ -26731,7 +26740,7 @@ ASTProductionFactory::ProductionRule_3011(const ASTToken* TK,
}

ASTArgumentNodeBuilder::Instance().Clear();
ASTIfStatementNode* CIF = ASTElseIfStatementTracker::Instance().GetCurrentIf();
ASTIfStatementNode* CIF = ASTIfStatementTracker::Instance().GetCurrentIf();
ASTIfStatementNode* SCIF = nullptr;

if (!CIF) {
Expand Down Expand Up @@ -27239,6 +27248,10 @@ ASTProductionFactory::ProductionRule_3110(const ASTToken* TK,
ASTSymbolTable::Instance().TransferLocalContextSymbols(CTX, STM);
}

ASTIfStatementTracker::Instance().CheckDeclarationContext(SL);
ASTElseIfStatementTracker::Instance().CheckDeclarationContext(SL);
ASTElseStatementTracker::Instance().CheckDeclarationContext(SL);

if (SC)
ASTDeclarationContextTracker::Instance().PopCurrentContext();

Expand Down Expand Up @@ -27326,6 +27339,10 @@ ASTProductionFactory::ProductionRule_3111(const ASTToken* TK,
ASTSymbolTable::Instance().TransferLocalContextSymbols(CTX, STM);
}

ASTIfStatementTracker::Instance().CheckDeclarationContext(SL);
ASTElseIfStatementTracker::Instance().CheckDeclarationContext(SL);
ASTElseStatementTracker::Instance().CheckDeclarationContext(SL);

if (SC)
ASTDeclarationContextTracker::Instance().PopCurrentContext();

Expand Down Expand Up @@ -27370,6 +27387,10 @@ ASTProductionFactory::ProductionRule_3120(const ASTToken* TK,
SL->TransferStatements(STM);
}

ASTIfStatementTracker::Instance().CheckDeclarationContext(SL);
ASTElseIfStatementTracker::Instance().CheckDeclarationContext(SL);
ASTElseStatementTracker::Instance().CheckDeclarationContext(SL);

if (SC)
ASTDeclarationContextTracker::Instance().PopCurrentContext();

Expand Down Expand Up @@ -27416,6 +27437,10 @@ ASTProductionFactory::ProductionRule_3121(const ASTToken* TK,
SL->TransferStatements(STM);
}

ASTIfStatementTracker::Instance().CheckDeclarationContext(SL);
ASTElseIfStatementTracker::Instance().CheckDeclarationContext(SL);
ASTElseStatementTracker::Instance().CheckDeclarationContext(SL);

if (SC)
ASTDeclarationContextTracker::Instance().PopCurrentContext();

Expand Down Expand Up @@ -27535,6 +27560,7 @@ ASTProductionFactory::ProductionRule_3100(const ASTToken* TK,

ASTIdentifierTypeController::Instance().Reset();
ASTIdentifierTypeController::Instance().SetCurrentType(ASTTypeUndefined);
ASTDeclarationContextTracker::Instance().PopCurrentContext();
return SN;
}

Expand Down Expand Up @@ -27596,6 +27622,7 @@ ASTProductionFactory::ProductionRule_3101(const ASTToken* TK,

ASTIdentifierTypeController::Instance().Reset();
ASTIdentifierTypeController::Instance().SetCurrentType(ASTTypeUndefined);
ASTDeclarationContextTracker::Instance().PopCurrentContext();
return SN;
}

Expand Down Expand Up @@ -27657,6 +27684,7 @@ ASTProductionFactory::ProductionRule_3102(const ASTToken* TK,

ASTIdentifierTypeController::Instance().Reset();
ASTIdentifierTypeController::Instance().SetCurrentType(ASTTypeUndefined);
ASTDeclarationContextTracker::Instance().PopCurrentContext();
return SN;
}

Expand Down Expand Up @@ -27718,6 +27746,7 @@ ASTProductionFactory::ProductionRule_3103(const ASTToken* TK,

ASTIdentifierTypeController::Instance().Reset();
ASTIdentifierTypeController::Instance().SetCurrentType(ASTTypeUndefined);
ASTDeclarationContextTracker::Instance().PopCurrentContext();
return SN;
}

Expand Down Expand Up @@ -27779,6 +27808,7 @@ ASTProductionFactory::ProductionRule_3104(const ASTToken* TK,

ASTIdentifierTypeController::Instance().Reset();
ASTIdentifierTypeController::Instance().SetCurrentType(ASTTypeUndefined);
ASTDeclarationContextTracker::Instance().PopCurrentContext();
return SN;
}

Expand Down Expand Up @@ -27840,6 +27870,7 @@ ASTProductionFactory::ProductionRule_3105(const ASTToken* TK,

ASTIdentifierTypeController::Instance().Reset();
ASTIdentifierTypeController::Instance().SetCurrentType(ASTTypeUndefined);
ASTDeclarationContextTracker::Instance().PopCurrentContext();
return SN;
}

Expand Down Expand Up @@ -27896,6 +27927,7 @@ ASTProductionFactory::ProductionRule_3106(const ASTToken* TK,

ASTIdentifierTypeController::Instance().Reset();
ASTIdentifierTypeController::Instance().SetCurrentType(ASTTypeUndefined);
ASTDeclarationContextTracker::Instance().PopCurrentContext();

std::stringstream M;
M << "Switch statement production rule fall-through. "
Expand Down

0 comments on commit b494a38

Please sign in to comment.