##// END OF EJS Templates
Work in progress.
Work in progress.

File last commit:

r2:f40b36fd7205 tip default
r2:f40b36fd7205 tip default
Show More
vhdl_element_parser.cpp
1128 lines | 40.0 KiB | text/x-c | CppLexer
/ vhdlparser / vhdl_element_parser.cpp
#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(&currentNode,-1);
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Type identifier");
walk_forward(&currentNode,-1);
CHECK_TOKEN_EXIT(rootNode,currentNode,is,"\"is\" keyword");
walk_forward(&currentNode,-1);
if(currentNode->type==generic)
{
parse_Port_or_Generic(&currentNode,openBlocksContext);
}
if(currentNode->type==port)
{
parse_Port_or_Generic(&currentNode,openBlocksContext);
}
if(currentNode->type!=endKw)
{
parse_DeclarativeBlock(&currentNode,openBlocksContext,false);
do
{
walk_forward(&currentNode,-1);
if(Q_UNLIKELY(currentNode->type==leftParen))
{
openBlocksContext->push(currentNode);
}
else
{
if(Q_UNLIKELY(currentNode->type==rightParen))
{
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
}
}
}while(((currentNode->type!=endKw) || (startNode!=openBlocksContext->top())) && currentNode->childs.count());
}
closeAndMatchBlock(&currentNode,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(&currentNode,-1); // skip Function
walk_forward(&currentNode,-1); // skip Name
parse_InterfaceList(&currentNode,openBlocksContext);
if(Q_UNLIKELY(currentNode->type!=return_t) )
{
qDebug()<<"Error expected return Keyword @line " <<currentNode->line <<" column "<<currentNode->column<<"\n";
}
walk_forward(&currentNode,-1);
if(Q_UNLIKELY(currentNode->type!=identifier))
{
qDebug()<<"Error expected return type @line " <<currentNode->line <<" column "<<currentNode->column<<"\n";
}
walk_forward(&currentNode,-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(&currentNode,-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(&currentNode,openBlocksContext,false);
closeAndMatchBlock(&currentNode,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(&currentNode,-1);
while (currentNode->childs.count())
{
switch (currentNode->type)
{
case block:
if(!isInContext(*openBlocksContext,attribute))
openBlocksContext->push(currentNode);
walk_forward(&currentNode,-1);
break;
case process:
if(!isInContext(*openBlocksContext,attribute))
parse_Process(&currentNode,openBlocksContext);
// openBlocksContext->push(currentNode);
walk_forward(&currentNode,-1);
break;
case wait:
parse_Wait(&currentNode,openBlocksContext);
break;
case component:
parse_Component(&currentNode,openBlocksContext);
break;
case endKw:
if(openBlocksContext->top()==startNode)
{
*rootNode=currentNode;
closeAndMatchBlock(rootNode,openBlocksContext,QList<VHDL_AST_Node_type>()<<identifier,true,true);
return 0;
}
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>()<<loop<<block<<identifier,true,true);
break;
case attribute:
parse_Attribute(&currentNode,openBlocksContext);
break;
case constant:
if(!isInContext(*openBlocksContext,procedure) && !isInContext(*openBlocksContext,function) && !isInContext(*openBlocksContext,attribute))
openBlocksContext->push(currentNode);
walk_forward(&currentNode,-1);
break;
case signal:
parse_Signal_or_Constant(&currentNode,openBlocksContext);
break;
case variable:
if(!isInContext(*openBlocksContext,procedure) && !isInContext(*openBlocksContext,function) && !isInContext(*openBlocksContext,attribute))
openBlocksContext->push(currentNode);
walk_forward(&currentNode,-1);
break;
case semicolon:
if( (openBlocksContext->size()) && (IS_CLOSED_BY_SEMICOLON(openBlocksContext->top()->type)))
{
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>(),false);
}
else
{
walk_forward(&currentNode,-1);
}
break;
default:
walk_forward(&currentNode,-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(&currentNode,-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(&currentNode,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(&currentNode,-1);
break;
case leftParen:
openBlocksContext->push(currentNode);
walk_forward(&currentNode,-1);
break;
case rightParen:
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_Tools::VHDL_AST_Node_type>());
break;
default:
walk_forward(&currentNode,-1);
break;
}
}
}
openBlocksContext->pop();
closeAndMatchBlock(&currentNode,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(&currentNode,-1);
switch (currentNode->type)
{
case VHDL_Tools::colon:
VHDL_Tools::parse_Block(&currentNode,openBlocksContext);
break;
case VHDL_Tools::leSym:
currentNode = currentNode->parent();
VHDL_Tools::parse_Assignment(&currentNode,openBlocksContext);
break;
case VHDL_Tools::leftParen: //function/procedure call
FORCE_CLOSETYPE(currentNode->parent(),closedBySemicolon);
openBlocksContext->push(currentNode->parent());
VHDL_Tools::parse_AssociationList(&currentNode,openBlocksContext);
VHDL_Tools::closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_Tools::VHDL_AST_Node_type>());
break;
case VHDL_Tools::varAsgn:
VHDL_Tools::parse_Assignment(&currentNode,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(&currentNode,-1);
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Type identifier");
walk_forward(&currentNode,-1);
CHECK_TOKEN_EXIT(rootNode,currentNode,of,"\"of\" keyword");
walk_forward(&currentNode,-1);
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Type identifier");
walk_forward(&currentNode,-1);
CHECK_TOKEN_EXIT(rootNode,currentNode,is,"\"is\" keyword");
walk_forward(&currentNode,-1);
parse_DeclarativeBlock(&currentNode,openBlocksContext,true);
/*if(currentNode->type!=endKw)
{
do
{
walk_forward(&currentNode,-1);
switch (currentNode->type) {
case identifier:
__private_parse_Architecture_Identifier(&currentNode,openBlocksContext);
case block:
break;
default:
break;
}
}while(((currentNode->type!=endKw) || (startNode!=openBlocksContext->top())) && currentNode->childs.count());
}*/
parse_body(&currentNode,openBlocksContext);
// closeAndMatchBlock(&currentNode,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(&currentNode,-1); // skip Procedure
walk_forward(&currentNode,-1); // skip Name
if(currentNode->type==leftParen)
{
parse_InterfaceList(&currentNode,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(&currentNode,-1);
if(Q_UNLIKELY(currentNode->type!=identifier))
{
qDebug()<<"Error expected return type @line " <<currentNode->line <<" column "<<currentNode->column<<"\n";
}
walk_forward(&currentNode,-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(&currentNode,openBlocksContext);
break;
case function:
parse_Function(&currentNode,openBlocksContext);
break;
case procedure:
parse_Procedure(&currentNode,openBlocksContext);
break;
case clause: //use / lib / subtype
parse_Clause(&currentNode,openBlocksContext);
break;
case constant:
parse_Signal_or_Constant(&currentNode,openBlocksContext);
break;
case signal:
parse_Signal_or_Constant(&currentNode,openBlocksContext);
break;
case type:
parse_Type(&currentNode,openBlocksContext);
break;
case file:
parse_File(&currentNode,openBlocksContext);
break;
case subtype:
parse_Subtype(&currentNode,openBlocksContext);
break;
case component:
parse_Component(&currentNode,openBlocksContext);
break;
case alias:
parse_Alias(&currentNode,openBlocksContext);
break;
case report:
parse_Report(&currentNode,openBlocksContext);
break;
default:
walk_forward(&currentNode,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(&currentNode,-1); // skip type
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Type identifier");
walk_forward(&currentNode,-1); // got Type identifier
CHECK_TOKEN_EXIT(rootNode,currentNode,is,"is");
walk_forward(&currentNode,-1); // got is
switch (currentNode->type)
{
case array:
do
{
walk_forward(&currentNode,-1);
if(Q_UNLIKELY(currentNode->type==leftParen))
{
openBlocksContext->push(currentNode);
}
else
{
if(Q_UNLIKELY(currentNode->type==rightParen))
{
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
}
}
}while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count());
if(currentNode->type == semicolon)
{
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
}
break;
case record:
parse_Record(&currentNode,openBlocksContext);
break;
case access:
walk_forward(&currentNode,-1);
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Type identifier");
walk_forward(&currentNode,-1);
CHECK_TOKEN_EXIT(rootNode,currentNode,semicolon,"semicolon");
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
break;
case file:
do
{
walk_forward(&currentNode,-1);
if(Q_UNLIKELY(currentNode->type==leftParen))
{
openBlocksContext->push(currentNode);
}
else
{
if(Q_UNLIKELY(currentNode->type==rightParen))
{
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
}
}
}while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count());
if(currentNode->type == semicolon)
{
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
}
break;
case range:
do
{
walk_forward(&currentNode,-1);
if(Q_UNLIKELY(currentNode->type==leftParen))
{
openBlocksContext->push(currentNode);
}
else
{
if(Q_UNLIKELY(currentNode->type==rightParen))
{
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
}
}
}while((((currentNode->type!=semicolon) && (currentNode->type!=units)) || (startNode!=openBlocksContext->top())) && currentNode->childs.count());
if(currentNode->type == semicolon)
{
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
}
else
{
if(currentNode->type == units)
{
parse_Units(&currentNode,openBlocksContext);
}
}
break;
case leftParen:
openBlocksContext->push(currentNode);
startNode2 = currentNode;
walk_forward(&currentNode,-1);
openBlocksContext->push(currentNode);
do
{
if(Q_UNLIKELY(currentNode->type==comma))
{
walk_forward(&currentNode,-1);
currentNode->move(openBlocksContext->pop()->parent());
openBlocksContext->push(currentNode);
}
else
{
walk_forward(&currentNode,-1);
}
}while(currentNode->childs.count() && ((currentNode->type!=rightParen)));
if(openBlocksContext->top()!=startNode2)
{
openBlocksContext->pop();
}
CHECK_TOKEN_EXIT(rootNode,currentNode,rightParen,"\")\"");
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
CHECK_TOKEN_EXIT(rootNode,currentNode,semicolon,"\";\"");
closeAndMatchBlock(&currentNode,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(&currentNode,-1); // skip subtype
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Subtype identifier");
walk_forward(&currentNode,-1); // got Subtype identifier
CHECK_TOKEN_EXIT(rootNode,currentNode,is,"is");
walk_forward(&currentNode,-1); // got is
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"type name");
walk_forward(&currentNode,-1);
switch (currentNode->type) {
case leftParen:
parse_ConstrainedRange(&currentNode,openBlocksContext);
break;
case identifier:
walk_forward(&currentNode,-1);
break;
case range:
parse_ConstrainedRange(&currentNode,openBlocksContext);
break;
default:
break;
}
CHECK_TOKEN_EXIT(rootNode,currentNode,semicolon,"\";\"");
closeAndMatchBlock(&currentNode,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(&currentNode,-1);
CHECK_TOKEN_EXIT(rootNode,currentNode,identifier,"Type identifier");
walk_forward(&currentNode,-1);
if(Q_LIKELY(currentNode->type==is))
{
walk_forward(&currentNode,-1);
}
do
{
switch (currentNode->type)
{
case port:
parse_Port_or_Generic(&currentNode,openBlocksContext);
break;
case generic:
parse_Port_or_Generic(&currentNode,openBlocksContext);
break;
default:
walk_forward(&currentNode,-1);
break;
}
}while(currentNode->type!=endKw);
closeAndMatchBlock(&currentNode,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(&currentNode,-1);
if(Q_UNLIKELY(currentNode->type==leftParen))
{
openBlocksContext->push(currentNode);
}
else
{
if(Q_UNLIKELY(currentNode->type==rightParen))
{
closeAndMatchBlock(&currentNode,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(&currentNode,-1);
do
{
if(Q_UNLIKELY(currentNode->type==leftParen))
{
openBlocksContext->push(currentNode);
}
else
{
if(Q_UNLIKELY(currentNode->type==rightParen))
{
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
}
}
walk_forward(&currentNode,-1);
}while(((currentNode->type!=rightParen) || (startNode!=openBlocksContext->top())) && currentNode->childs.count());
closeAndMatchBlock(&currentNode,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(&currentNode,-1);
if(Q_UNLIKELY(currentNode->type==semicolon))
{
closeAndMatchBlock(&currentNode,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(&currentNode,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(&currentNode,-1);
if(Q_UNLIKELY(currentNode->type==semicolon))
{
closeAndMatchBlock(&currentNode,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(&currentNode,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(&currentNode,-1);
if(Q_UNLIKELY(currentNode->type==leftParen))
{
openBlocksContext->push(currentNode);
}
else
{
if(Q_UNLIKELY(currentNode->type==rightParen))
{
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
}
}
}while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count());
if(currentNode->type == semicolon)
{
closeAndMatchBlock(&currentNode,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(&currentNode,-1);
if(Q_UNLIKELY(currentNode->type==leftParen))
{
openBlocksContext->push(currentNode);
}
else
{
if(Q_UNLIKELY(currentNode->type==rightParen))
{
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
}
}
}while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count());
if(currentNode->type == semicolon)
{
closeAndMatchBlock(&currentNode,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(&currentNode,-1);
if(Q_UNLIKELY(currentNode->type==leftParen))
{
openBlocksContext->push(currentNode);
}
else
{
if(Q_UNLIKELY(currentNode->type==rightParen))
{
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
}
}
}while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count());
if(currentNode->type == semicolon)
{
closeAndMatchBlock(&currentNode,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(&currentNode,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(&currentNode,-1);
walk_forward(&currentNode,-1);
if(currentNode->type==block)
{
FORCE_CLOSETYPE(openBlocksContext->top(),closedByEnd);
}
else
{
FORCE_CLOSETYPE(openBlocksContext->top(),closedBySemicolon);
}
}
else
{
walk_forward(&currentNode,-1);
}
break;
case block:
parse_Block(&currentNode,openBlocksContext);
break;
case semicolon:
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
openBlocksContext->push(currentNode);
break;
case caseKw:
break;
default:
walk_forward(&currentNode,-1);
break;
}
}while(((currentNode->type!=endKw) || (startNode!=openBlocksContext->top())) && currentNode->childs.count());
}
closeAndMatchBlock(&currentNode,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(&currentNode,-1);
if(Q_UNLIKELY(currentNode->type==leftParen))
{
openBlocksContext->push(currentNode);
}
else
{
if(Q_UNLIKELY(currentNode->type==rightParen))
{
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
}
}
}while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count());
if(Q_LIKELY(currentNode->type == semicolon))
{
closeAndMatchBlock(&currentNode,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(&currentNode,-1);
if(currentNode->type==leftParen)
{
parse_InterfaceList(&currentNode,openBlocksContext);
}
if(Q_LIKELY(currentNode->type == semicolon))
{
closeAndMatchBlock(&currentNode,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(&currentNode,-1);
if(currentNode->type!=endKw)
{
do
{
switch (currentNode->type)
{
case identifier:
__private_parse_Architecture_Identifier(&currentNode,openBlocksContext);
break;
case block:
parse_Block(&currentNode,openBlocksContext);
break;
case wait:
parse_Wait(&currentNode,openBlocksContext);
break;
case semicolon:
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_AST_Node_type>());
openBlocksContext->push(currentNode);
break;
default:
walk_forward(&currentNode,-1);
break;
}
}while(((currentNode->type!=endKw) || (startNode!=openBlocksContext->top())) && currentNode->childs.count());
}
closeAndMatchBlock(&currentNode,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(&currentNode,-1)))
{
openBlocksContext->pop();
*rootNode=currentNode;
return 0;
}
}
closeAndMatchBlock(&currentNode,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(&currentNode,-1)))
{
*rootNode=currentNode;
return -1;
}
}
closeAndMatchBlock(&currentNode,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(&currentNode,-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(&currentNode,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(&currentNode,-1);
break;
case leftParen:
openBlocksContext->push(currentNode);
walk_forward(&currentNode,-1);
break;
case rightParen:
closeAndMatchBlock(&currentNode,openBlocksContext,QList<VHDL_Tools::VHDL_AST_Node_type>());
break;
default:
walk_forward(&currentNode,-1);
break;
}
}
}
openBlocksContext->pop();
closeAndMatchBlock(&currentNode,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(&currentNode);
}while(currentNode->type!=is);
do{
if(currentNode->type==when)
{
parse_When_case(&currentNode,openBlocksContext);
}
else
{
walk_forward(&currentNode,-1);
}
}while(currentNode!=endKw);
closeAndMatchBlock(&currentNode,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;
}