|
|
#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;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|