vhdl_element_parser.cpp
1128 lines
| 40.0 KiB
| text/x-c
|
CppLexer
/ vhdlparser / vhdl_element_parser.cpp
r2 | #include "vhdl_element_parser.h" | |||
#include <QDebug> | ||||
#define ERROR_EXPECTING(node,expectedKW) qDebug()<<"Error expected "<< (expectedKW) <<" @line " <<(node)->line <<" column "<<(node)->column<<"\n" | ||||
#define CHECK_TOKEN(rootNode,node,expectedType,expectedTypeText) \ | ||||
if(Q_UNLIKELY((node)->type!=(expectedType))) \ | ||||
{\ | ||||
ERROR_EXPECTING((node),expectedTypeText); \ | ||||
} | ||||
#define CHECK_TOKEN_EXIT(rootNode,node,expectedType,expectedTypeText) \ | ||||
if(Q_UNLIKELY((node)->type!=(expectedType))) \ | ||||
{\ | ||||
ERROR_EXPECTING((node),expectedTypeText); \ | ||||
*(rootNode)=(node); \ | ||||
return -1; \ | ||||
}\ | ||||
bool VHDL_Tools::isInContext(QStack<VHDL_Tools::VHDL_AST_Node *> openBlocksContext, VHDL_Tools::VHDL_AST_Node_type type) | ||||
{ | ||||
while (openBlocksContext.count()) | ||||
{ | ||||
//Copy of the stack -> pop() is safe | ||||
if(openBlocksContext.pop()->type==type) | ||||
{ | ||||
return true; | ||||
} | ||||
} | ||||
return false; | ||||
} | ||||
int VHDL_Tools::parse_Entity(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->append(currentNode); | ||||
VHDL_AST_Node *startNode = currentNode; | ||||
walk_forward(¤tNode,-1); | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Type identifier"); | ||||
walk_forward(¤tNode,-1); | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,is,"\"is\" keyword"); | ||||
walk_forward(¤tNode,-1); | ||||
if(currentNode->type==generic) | ||||
{ | ||||
parse_Port_or_Generic(¤tNode,openBlocksContext); | ||||
} | ||||
if(currentNode->type==port) | ||||
{ | ||||
parse_Port_or_Generic(¤tNode,openBlocksContext); | ||||
} | ||||
if(currentNode->type!=endKw) | ||||
{ | ||||
parse_DeclarativeBlock(¤tNode,openBlocksContext,false); | ||||
do | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_UNLIKELY(currentNode->type==leftParen)) | ||||
{ | ||||
openBlocksContext->push(currentNode); | ||||
} | ||||
else | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type==rightParen)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
} | ||||
}while(((currentNode->type!=endKw) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); | ||||
} | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()<<identifier,true,true); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Function(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node* startNode = *rootNode; | ||||
VHDL_AST_Node* currentNode = *rootNode; | ||||
openBlocksContext->push(startNode); | ||||
walk_forward(¤tNode,-1); // skip Function | ||||
walk_forward(¤tNode,-1); // skip Name | ||||
parse_InterfaceList(¤tNode,openBlocksContext); | ||||
if(Q_UNLIKELY(currentNode->type!=return_t) ) | ||||
{ | ||||
qDebug()<<"Error expected return Keyword @line " <<currentNode->line <<" column "<<currentNode->column<<"\n"; | ||||
} | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_UNLIKELY(currentNode->type!=identifier)) | ||||
{ | ||||
qDebug()<<"Error expected return type @line " <<currentNode->line <<" column "<<currentNode->column<<"\n"; | ||||
} | ||||
walk_forward(¤tNode,-1); | ||||
*rootNode=currentNode; | ||||
if(currentNode->type==is) | ||||
{ | ||||
walk_forward(rootNode,-1); //skip is | ||||
parse_DeclarativeBlock(rootNode,openBlocksContext); | ||||
startNode->type=static_cast<VHDL_AST_Node_type>(startNode->type | closedByEnd); | ||||
return parse_body(rootNode,openBlocksContext); | ||||
} | ||||
else | ||||
{ | ||||
startNode->type=static_cast<VHDL_AST_Node_type>(currentNode->type | closedBySemicolon); | ||||
closeAndMatchBlock(rootNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
return -1; | ||||
} | ||||
int VHDL_Tools::parse_Attribute(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node* startNode = *rootNode; | ||||
VHDL_AST_Node* currentNode = *rootNode; | ||||
openBlocksContext->push(startNode); | ||||
while(currentNode->type!=semicolon) | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
} | ||||
*rootNode=currentNode; | ||||
closeAndMatchBlock(rootNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Package(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->append(currentNode); | ||||
parse_DeclarativeBlock(¤tNode,openBlocksContext,false); | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()<<identifier,true,true); | ||||
*rootNode =currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::closeAndMatchBlock(VHDL_Tools::VHDL_AST_Node** currentNode,QStack<VHDL_Tools::VHDL_AST_Node*>* openBlocksContext,QList<VHDL_Tools::VHDL_AST_Node_type>skipTypes,bool skipOpenType,bool endWithSemicolon) | ||||
{ | ||||
if(openBlocksContext->size()) | ||||
{ | ||||
VHDL_AST_Node* startNode = openBlocksContext->pop(); | ||||
if( IS_CLOSED_BY(startNode->type,(*currentNode)->type)) | ||||
{ | ||||
walk_forward(currentNode,-1); | ||||
if(skipOpenType) | ||||
{ | ||||
skipTokens((*currentNode),(startNode->type)); | ||||
} | ||||
for(int i=0;i<skipTypes.length();i++) | ||||
{ | ||||
skipTokens((*currentNode),skipTypes.at(i)); | ||||
} | ||||
if(endWithSemicolon && ((*currentNode)->type==semicolon)) | ||||
{ | ||||
if(walk_forward(currentNode,-1)!=-1) | ||||
(*currentNode)->move(startNode->parent()); | ||||
} | ||||
else | ||||
{ | ||||
(*currentNode)->move(startNode->parent()); | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
// TODO improve message ! | ||||
qDebug() << "Got unexpected close token! @ line:" << (*currentNode)->line << " column:"<< (*currentNode)->column; | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
walk_forward(currentNode,-1); | ||||
return -1; | ||||
} | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_body(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
VHDL_AST_Node *startNode=openBlocksContext->top(); | ||||
if(Q_UNLIKELY(currentNode->type!=begin)) | ||||
{ | ||||
qDebug()<<"Error expected begin keyword @line " <<currentNode->line <<" column "<<currentNode->column<<"\n"; | ||||
return -1; | ||||
} | ||||
walk_forward(¤tNode,-1); | ||||
while (currentNode->childs.count()) | ||||
{ | ||||
switch (currentNode->type) | ||||
{ | ||||
case block: | ||||
if(!isInContext(*openBlocksContext,attribute)) | ||||
openBlocksContext->push(currentNode); | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
case process: | ||||
if(!isInContext(*openBlocksContext,attribute)) | ||||
parse_Process(¤tNode,openBlocksContext); | ||||
// openBlocksContext->push(currentNode); | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
case wait: | ||||
parse_Wait(¤tNode,openBlocksContext); | ||||
break; | ||||
case component: | ||||
parse_Component(¤tNode,openBlocksContext); | ||||
break; | ||||
case endKw: | ||||
if(openBlocksContext->top()==startNode) | ||||
{ | ||||
*rootNode=currentNode; | ||||
closeAndMatchBlock(rootNode,openBlocksContext,QList<VHDL_AST_Node_type>()<<identifier,true,true); | ||||
return 0; | ||||
} | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()<<loop<<block<<identifier,true,true); | ||||
break; | ||||
case attribute: | ||||
parse_Attribute(¤tNode,openBlocksContext); | ||||
break; | ||||
case constant: | ||||
if(!isInContext(*openBlocksContext,procedure) && !isInContext(*openBlocksContext,function) && !isInContext(*openBlocksContext,attribute)) | ||||
openBlocksContext->push(currentNode); | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
case signal: | ||||
parse_Signal_or_Constant(¤tNode,openBlocksContext); | ||||
break; | ||||
case variable: | ||||
if(!isInContext(*openBlocksContext,procedure) && !isInContext(*openBlocksContext,function) && !isInContext(*openBlocksContext,attribute)) | ||||
openBlocksContext->push(currentNode); | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
case semicolon: | ||||
if( (openBlocksContext->size()) && (IS_CLOSED_BY_SEMICOLON(openBlocksContext->top()->type))) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>(),false); | ||||
} | ||||
else | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
} | ||||
break; | ||||
default: | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
} | ||||
} | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_InterfaceList(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
/* interface-list –› [ constant | signal | file ] identifier { ‘,’ identifier } ‘:’ [ in ] subtype-indication [ := static_expression ]*/ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
walk_forward(¤tNode,-1); | ||||
if(currentNode->type!=rightParen) | ||||
{ | ||||
FORCE_CLOSETYPE(currentNode, closedBySemicolon); | ||||
openBlocksContext->push(currentNode); | ||||
VHDL_AST_Node *currentLine=currentNode; | ||||
while((currentNode->type!=rightParen) || openBlocksContext->top()!=currentLine) | ||||
{ | ||||
switch (currentNode->type) | ||||
{ | ||||
case semicolon: | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_Tools::VHDL_AST_Node_type>()); | ||||
if(currentNode->childs.first()->type!=rightParen) | ||||
{ | ||||
FORCE_CLOSETYPE(currentNode, closedBySemicolon); | ||||
openBlocksContext->push(currentNode); | ||||
currentLine = currentNode; | ||||
} | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
case leftParen: | ||||
openBlocksContext->push(currentNode); | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
case rightParen: | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_Tools::VHDL_AST_Node_type>()); | ||||
break; | ||||
default: | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
} | ||||
} | ||||
} | ||||
openBlocksContext->pop(); | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_Tools::VHDL_AST_Node_type>()); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int __private_parse_Architecture_Identifier(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_Tools::VHDL_AST_Node *currentNode=*rootNode; | ||||
VHDL_Tools::VHDL_AST_Node *startNode = currentNode; | ||||
VHDL_Tools::walk_forward(¤tNode,-1); | ||||
switch (currentNode->type) | ||||
{ | ||||
case VHDL_Tools::colon: | ||||
VHDL_Tools::parse_Block(¤tNode,openBlocksContext); | ||||
break; | ||||
case VHDL_Tools::leSym: | ||||
currentNode = currentNode->parent(); | ||||
VHDL_Tools::parse_Assignment(¤tNode,openBlocksContext); | ||||
break; | ||||
case VHDL_Tools::leftParen: //function/procedure call | ||||
FORCE_CLOSETYPE(currentNode->parent(),closedBySemicolon); | ||||
openBlocksContext->push(currentNode->parent()); | ||||
VHDL_Tools::parse_AssociationList(¤tNode,openBlocksContext); | ||||
VHDL_Tools::closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_Tools::VHDL_AST_Node_type>()); | ||||
break; | ||||
case VHDL_Tools::varAsgn: | ||||
VHDL_Tools::parse_Assignment(¤tNode,openBlocksContext); | ||||
break; | ||||
default: | ||||
break; | ||||
} | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Architecture(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->append(currentNode); | ||||
VHDL_AST_Node *startNode = currentNode; | ||||
walk_forward(¤tNode,-1); | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Type identifier"); | ||||
walk_forward(¤tNode,-1); | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,of,"\"of\" keyword"); | ||||
walk_forward(¤tNode,-1); | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Type identifier"); | ||||
walk_forward(¤tNode,-1); | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,is,"\"is\" keyword"); | ||||
walk_forward(¤tNode,-1); | ||||
parse_DeclarativeBlock(¤tNode,openBlocksContext,true); | ||||
/*if(currentNode->type!=endKw) | ||||
{ | ||||
do | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
switch (currentNode->type) { | ||||
case identifier: | ||||
__private_parse_Architecture_Identifier(¤tNode,openBlocksContext); | ||||
case block: | ||||
break; | ||||
default: | ||||
break; | ||||
} | ||||
}while(((currentNode->type!=endKw) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); | ||||
}*/ | ||||
parse_body(¤tNode,openBlocksContext); | ||||
// closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()<<identifier,true,true); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Procedure(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node* startNode = *rootNode; | ||||
VHDL_AST_Node* currentNode = *rootNode; | ||||
openBlocksContext->push(startNode); | ||||
walk_forward(¤tNode,-1); // skip Procedure | ||||
walk_forward(¤tNode,-1); // skip Name | ||||
if(currentNode->type==leftParen) | ||||
{ | ||||
parse_InterfaceList(¤tNode,openBlocksContext); | ||||
} | ||||
if(Q_UNLIKELY(currentNode->type!=return_t) ) | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type!=is)) | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type!=semicolon)) | ||||
{ | ||||
qDebug()<<"Error expected semicolon or \"return\" or \"is\" Keyword @line " <<currentNode->line <<" column "<<currentNode->column<<"\n"; | ||||
} | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_UNLIKELY(currentNode->type!=identifier)) | ||||
{ | ||||
qDebug()<<"Error expected return type @line " <<currentNode->line <<" column "<<currentNode->column<<"\n"; | ||||
} | ||||
walk_forward(¤tNode,-1); | ||||
} | ||||
*rootNode=currentNode; | ||||
if(currentNode->type==is) | ||||
{ | ||||
walk_forward(rootNode,-1); //skip is | ||||
parse_DeclarativeBlock(rootNode,openBlocksContext); | ||||
startNode->type=static_cast<VHDL_AST_Node_type>(startNode->type | closedByEnd); | ||||
return parse_body(rootNode,openBlocksContext); | ||||
} | ||||
else | ||||
{ | ||||
startNode->type=static_cast<VHDL_AST_Node_type>(currentNode->type | closedBySemicolon); | ||||
closeAndMatchBlock(rootNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
return -1; | ||||
} | ||||
int VHDL_Tools::parse_DeclarativeBlock(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext, bool mustHaveBegin) | ||||
{ | ||||
//Parse until begin or end | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
VHDL_AST_Node *startNode=openBlocksContext->top(); | ||||
while(( ((currentNode->type!=begin) && (currentNode->type!=endKw)) || (openBlocksContext->top()!=startNode) ) && (currentNode->childs.count())) | ||||
{ | ||||
switch(currentNode->type) | ||||
{ | ||||
case block: | ||||
parse_Block(¤tNode,openBlocksContext); | ||||
break; | ||||
case function: | ||||
parse_Function(¤tNode,openBlocksContext); | ||||
break; | ||||
case procedure: | ||||
parse_Procedure(¤tNode,openBlocksContext); | ||||
break; | ||||
case clause: //use / lib / subtype | ||||
parse_Clause(¤tNode,openBlocksContext); | ||||
break; | ||||
case constant: | ||||
parse_Signal_or_Constant(¤tNode,openBlocksContext); | ||||
break; | ||||
case signal: | ||||
parse_Signal_or_Constant(¤tNode,openBlocksContext); | ||||
break; | ||||
case type: | ||||
parse_Type(¤tNode,openBlocksContext); | ||||
break; | ||||
case file: | ||||
parse_File(¤tNode,openBlocksContext); | ||||
break; | ||||
case subtype: | ||||
parse_Subtype(¤tNode,openBlocksContext); | ||||
break; | ||||
case component: | ||||
parse_Component(¤tNode,openBlocksContext); | ||||
break; | ||||
case alias: | ||||
parse_Alias(¤tNode,openBlocksContext); | ||||
break; | ||||
case report: | ||||
parse_Report(¤tNode,openBlocksContext); | ||||
break; | ||||
default: | ||||
walk_forward(¤tNode,0); | ||||
break; | ||||
} | ||||
} | ||||
if(Q_UNLIKELY(mustHaveBegin && (currentNode->type!=begin))) | ||||
{ | ||||
qDebug()<<"Error expected \"begin\" keyword and got " << currentNode->a_value << " @line " <<currentNode->line <<" column "<<currentNode->column<<"\n"; | ||||
} | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Type(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
VHDL_AST_Node *startNode=openBlocksContext->top(); | ||||
VHDL_AST_Node *startNode2; | ||||
walk_forward(¤tNode,-1); // skip type | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Type identifier"); | ||||
walk_forward(¤tNode,-1); // got Type identifier | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,is,"is"); | ||||
walk_forward(¤tNode,-1); // got is | ||||
switch (currentNode->type) | ||||
{ | ||||
case array: | ||||
do | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_UNLIKELY(currentNode->type==leftParen)) | ||||
{ | ||||
openBlocksContext->push(currentNode); | ||||
} | ||||
else | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type==rightParen)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
} | ||||
}while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); | ||||
if(currentNode->type == semicolon) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
break; | ||||
case record: | ||||
parse_Record(¤tNode,openBlocksContext); | ||||
break; | ||||
case access: | ||||
walk_forward(¤tNode,-1); | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Type identifier"); | ||||
walk_forward(¤tNode,-1); | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,semicolon,"semicolon"); | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
break; | ||||
case file: | ||||
do | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_UNLIKELY(currentNode->type==leftParen)) | ||||
{ | ||||
openBlocksContext->push(currentNode); | ||||
} | ||||
else | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type==rightParen)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
} | ||||
}while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); | ||||
if(currentNode->type == semicolon) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
break; | ||||
case range: | ||||
do | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_UNLIKELY(currentNode->type==leftParen)) | ||||
{ | ||||
openBlocksContext->push(currentNode); | ||||
} | ||||
else | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type==rightParen)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
} | ||||
}while((((currentNode->type!=semicolon) && (currentNode->type!=units)) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); | ||||
if(currentNode->type == semicolon) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
else | ||||
{ | ||||
if(currentNode->type == units) | ||||
{ | ||||
parse_Units(¤tNode,openBlocksContext); | ||||
} | ||||
} | ||||
break; | ||||
case leftParen: | ||||
openBlocksContext->push(currentNode); | ||||
startNode2 = currentNode; | ||||
walk_forward(¤tNode,-1); | ||||
openBlocksContext->push(currentNode); | ||||
do | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type==comma)) | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
currentNode->move(openBlocksContext->pop()->parent()); | ||||
openBlocksContext->push(currentNode); | ||||
} | ||||
else | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
} | ||||
}while(currentNode->childs.count() && ((currentNode->type!=rightParen))); | ||||
if(openBlocksContext->top()!=startNode2) | ||||
{ | ||||
openBlocksContext->pop(); | ||||
} | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,rightParen,"\")\""); | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,semicolon,"\";\""); | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
break; | ||||
default: | ||||
break; | ||||
} | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Subtype(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
/*========================================================================================== | ||||
SUBTYPE MyArray IS BIT_VECTOR(7 DOWNTO 3); | ||||
subtype-declaration –› | ||||
subtype identifier is subtype-indication ';' | ||||
subtype-indication, type-indication –› | ||||
[ resolution-function-name ] type-name [ range-constraint | index-constraint ] | ||||
=============================================================================================*/ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
//VHDL_AST_Node *startNode=openBlocksContext->top(); | ||||
openBlocksContext->append(currentNode); | ||||
walk_forward(¤tNode,-1); // skip subtype | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Subtype identifier"); | ||||
walk_forward(¤tNode,-1); // got Subtype identifier | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,is,"is"); | ||||
walk_forward(¤tNode,-1); // got is | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"type name"); | ||||
walk_forward(¤tNode,-1); | ||||
switch (currentNode->type) { | ||||
case leftParen: | ||||
parse_ConstrainedRange(¤tNode,openBlocksContext); | ||||
break; | ||||
case identifier: | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
case range: | ||||
parse_ConstrainedRange(¤tNode,openBlocksContext); | ||||
break; | ||||
default: | ||||
break; | ||||
} | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,semicolon,"\";\""); | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Component(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->append(currentNode); | ||||
walk_forward(¤tNode,-1); | ||||
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Type identifier"); | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_LIKELY(currentNode->type==is)) | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
} | ||||
do | ||||
{ | ||||
switch (currentNode->type) | ||||
{ | ||||
case port: | ||||
parse_Port_or_Generic(¤tNode,openBlocksContext); | ||||
break; | ||||
case generic: | ||||
parse_Port_or_Generic(¤tNode,openBlocksContext); | ||||
break; | ||||
default: | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
} | ||||
}while(currentNode->type!=endKw); | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()<<identifier,true,true); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_ConstrainedRange(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
//range 0 to 9 | ||||
//(1 to 20) | ||||
//(20 dowto 1) | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
VHDL_AST_Node *startNode=openBlocksContext->top(); | ||||
switch (currentNode->type) | ||||
{ | ||||
case range: | ||||
//Expecting a constrained range so must get an identifier or a literal or an expression | ||||
do | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_UNLIKELY(currentNode->type==leftParen)) | ||||
{ | ||||
openBlocksContext->push(currentNode); | ||||
} | ||||
else | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type==rightParen)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
} | ||||
}while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); | ||||
break; | ||||
case leftParen: | ||||
openBlocksContext->push(currentNode); | ||||
startNode = currentNode; | ||||
walk_forward(¤tNode,-1); | ||||
do | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type==leftParen)) | ||||
{ | ||||
openBlocksContext->push(currentNode); | ||||
} | ||||
else | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type==rightParen)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
} | ||||
walk_forward(¤tNode,-1); | ||||
}while(((currentNode->type!=rightParen) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
break; | ||||
default: | ||||
break; | ||||
} | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Units(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
openBlocksContext->push(currentNode->childs.first()); | ||||
FORCE_CLOSETYPE(currentNode->childs.first(),closedBySemicolon); | ||||
do | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_UNLIKELY(currentNode->type==semicolon)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
if(currentNode->type!=endKw) | ||||
{ | ||||
FORCE_CLOSETYPE(currentNode,closedBySemicolon); | ||||
openBlocksContext->push(currentNode); | ||||
} | ||||
} | ||||
}while((currentNode->type!=endKw) && currentNode->childs.count()); | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()<<identifier,true,true); | ||||
currentNode->move(openBlocksContext->pop()->parent()); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Record(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
openBlocksContext->push(currentNode->childs.first()); | ||||
FORCE_CLOSETYPE(currentNode->childs.first(),closedBySemicolon); | ||||
do | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_UNLIKELY(currentNode->type==semicolon)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
if(currentNode->type!=endKw) | ||||
{ | ||||
FORCE_CLOSETYPE(currentNode,closedBySemicolon); | ||||
openBlocksContext->push(currentNode); | ||||
} | ||||
} | ||||
}while((currentNode->type!=endKw) && currentNode->childs.count()); | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()<<identifier,true,true); | ||||
currentNode->move(openBlocksContext->pop()->parent()); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_File(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
VHDL_AST_Node *startNode=openBlocksContext->top(); | ||||
FORCE_CLOSETYPE(currentNode->childs.first(),closedBySemicolon); | ||||
do | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_UNLIKELY(currentNode->type==leftParen)) | ||||
{ | ||||
openBlocksContext->push(currentNode); | ||||
} | ||||
else | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type==rightParen)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
} | ||||
}while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); | ||||
if(currentNode->type == semicolon) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Alias(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
VHDL_AST_Node *startNode=openBlocksContext->top(); | ||||
FORCE_CLOSETYPE(currentNode->childs.first(),closedBySemicolon); | ||||
do | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_UNLIKELY(currentNode->type==leftParen)) | ||||
{ | ||||
openBlocksContext->push(currentNode); | ||||
} | ||||
else | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type==rightParen)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
} | ||||
}while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); | ||||
if(currentNode->type == semicolon) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Report(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
VHDL_AST_Node *startNode=openBlocksContext->top(); | ||||
FORCE_CLOSETYPE(currentNode->childs.first(),closedBySemicolon); | ||||
do | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_UNLIKELY(currentNode->type==leftParen)) | ||||
{ | ||||
openBlocksContext->push(currentNode); | ||||
} | ||||
else | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type==rightParen)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
} | ||||
}while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); | ||||
if(currentNode->type == semicolon) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Process(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
if(currentNode->parent()->type==colon) | ||||
{ | ||||
if(currentNode->parent()->parent()->type==identifier) | ||||
{ | ||||
FORCE_CLOSETYPE(currentNode->parent()->parent(),closedByEnd); | ||||
openBlocksContext->append(currentNode->parent()->parent()); | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
openBlocksContext->append(currentNode); | ||||
} | ||||
VHDL_AST_Node *startNode=openBlocksContext->top(); | ||||
parse_DeclarativeBlock(¤tNode,openBlocksContext,true); | ||||
if(currentNode->type!=endKw) | ||||
{ | ||||
do | ||||
{ | ||||
switch (currentNode->type) | ||||
{ | ||||
case identifier: | ||||
if(currentNode->childs.count() && currentNode->childs.first()->type==colon) | ||||
{ | ||||
openBlocksContext->push(currentNode); | ||||
walk_forward(¤tNode,-1); | ||||
walk_forward(¤tNode,-1); | ||||
if(currentNode->type==block) | ||||
{ | ||||
FORCE_CLOSETYPE(openBlocksContext->top(),closedByEnd); | ||||
} | ||||
else | ||||
{ | ||||
FORCE_CLOSETYPE(openBlocksContext->top(),closedBySemicolon); | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
} | ||||
break; | ||||
case block: | ||||
parse_Block(¤tNode,openBlocksContext); | ||||
break; | ||||
case semicolon: | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
openBlocksContext->push(currentNode); | ||||
break; | ||||
case caseKw: | ||||
break; | ||||
default: | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
} | ||||
}while(((currentNode->type!=endKw) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); | ||||
} | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()<<identifier,true,true); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Signal_or_Constant(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
VHDL_AST_Node *startNode=openBlocksContext->top(); | ||||
do | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
if(Q_UNLIKELY(currentNode->type==leftParen)) | ||||
{ | ||||
openBlocksContext->push(currentNode); | ||||
} | ||||
else | ||||
{ | ||||
if(Q_UNLIKELY(currentNode->type==rightParen)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
} | ||||
}while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); | ||||
if(Q_LIKELY(currentNode->type == semicolon)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Port_or_Generic(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
walk_forward(¤tNode,-1); | ||||
if(currentNode->type==leftParen) | ||||
{ | ||||
parse_InterfaceList(¤tNode,openBlocksContext); | ||||
} | ||||
if(Q_LIKELY(currentNode->type == semicolon)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
} | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Block(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
VHDL_AST_Node *startNode=currentNode; | ||||
walk_forward(¤tNode,-1); | ||||
if(currentNode->type!=endKw) | ||||
{ | ||||
do | ||||
{ | ||||
switch (currentNode->type) | ||||
{ | ||||
case identifier: | ||||
__private_parse_Architecture_Identifier(¤tNode,openBlocksContext); | ||||
break; | ||||
case block: | ||||
parse_Block(¤tNode,openBlocksContext); | ||||
break; | ||||
case wait: | ||||
parse_Wait(¤tNode,openBlocksContext); | ||||
break; | ||||
case semicolon: | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
openBlocksContext->push(currentNode); | ||||
break; | ||||
default: | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
} | ||||
}while(((currentNode->type!=endKw) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); | ||||
} | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()<<identifier,true,true); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Assignment(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
VHDL_AST_Node *startNode = currentNode; | ||||
FORCE_CLOSETYPE(currentNode,closedBySemicolon); | ||||
while (currentNode->type!=semicolon) | ||||
{ | ||||
if(Q_UNLIKELY(walk_forward(¤tNode,-1))) | ||||
{ | ||||
openBlocksContext->pop(); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
} | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Wait(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
while(currentNode->type!=semicolon) | ||||
{ | ||||
if(Q_UNLIKELY(walk_forward(¤tNode,-1))) | ||||
{ | ||||
*rootNode=currentNode; | ||||
return -1; | ||||
} | ||||
} | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_AST_Node_type>()); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_AssociationList(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
/* association-list –› [ formal-part ‘=>’ ] actual-part { ‘,’ [ formal-part ‘=>’ ] actual-part }*/ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
walk_forward(¤tNode,-1); | ||||
if(currentNode->type!=rightParen) | ||||
{ | ||||
FORCE_CLOSETYPE(currentNode, closedBySemicolon); | ||||
openBlocksContext->push(currentNode); | ||||
VHDL_AST_Node *currentLine=currentNode; | ||||
while((currentNode->type!=rightParen) || openBlocksContext->top()!=currentLine) | ||||
{ | ||||
switch (currentNode->type) | ||||
{ | ||||
case colon: | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_Tools::VHDL_AST_Node_type>()); | ||||
if(currentNode->childs.first()->type!=rightParen) | ||||
{ | ||||
FORCE_CLOSETYPE(currentNode, closedBySemicolon); | ||||
openBlocksContext->push(currentNode); | ||||
currentLine = currentNode; | ||||
} | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
case leftParen: | ||||
openBlocksContext->push(currentNode); | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
case rightParen: | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_Tools::VHDL_AST_Node_type>()); | ||||
break; | ||||
default: | ||||
walk_forward(¤tNode,-1); | ||||
break; | ||||
} | ||||
} | ||||
} | ||||
openBlocksContext->pop(); | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_Tools::VHDL_AST_Node_type>()); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_Case(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
/* | ||||
case-statement –› [ case-label ‘:’ ] case expression is | ||||
when choices ‘=>’ { sequential-statement } | ||||
{ when choices ‘=>’ { sequential-statement }} | ||||
end case [ case-label ] ‘;’ | ||||
choices –› choice { | choice } | ||||
*/ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
openBlocksContext->push(currentNode); | ||||
do | ||||
{ | ||||
walk_forward(¤tNode); | ||||
}while(currentNode->type!=is); | ||||
do{ | ||||
if(currentNode->type==when) | ||||
{ | ||||
parse_When_case(¤tNode,openBlocksContext); | ||||
} | ||||
else | ||||
{ | ||||
walk_forward(¤tNode,-1); | ||||
} | ||||
}while(currentNode!=endKw); | ||||
closeAndMatchBlock(¤tNode,openBlocksContext,QList<VHDL_Tools::VHDL_AST_Node_type>()); | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||
int VHDL_Tools::parse_When_case(VHDL_Tools::VHDL_AST_Node **rootNode, QStack<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext) | ||||
{ | ||||
VHDL_AST_Node *currentNode=*rootNode; | ||||
VHDL_AST_Node *startNode=*rootNode; | ||||
*rootNode=currentNode; | ||||
return 0; | ||||
} | ||||