#include "vhdl_element_parser.h" #include #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 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 *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()); } } }while(((currentNode->type!=endKw) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); } closeAndMatchBlock(¤tNode,openBlocksContext,QList()< *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 " <line <<" column "<column<<"\n"; } walk_forward(¤tNode,-1); if(Q_UNLIKELY(currentNode->type!=identifier)) { qDebug()<<"Error expected return type @line " <line <<" column "<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(startNode->type | closedByEnd); return parse_body(rootNode,openBlocksContext); } else { startNode->type=static_cast(currentNode->type | closedBySemicolon); closeAndMatchBlock(rootNode,openBlocksContext,QList()); } return -1; } int VHDL_Tools::parse_Attribute(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); return 0; } int VHDL_Tools::parse_Package(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *openBlocksContext) { VHDL_AST_Node *currentNode=*rootNode; openBlocksContext->append(currentNode); parse_DeclarativeBlock(¤tNode,openBlocksContext,false); closeAndMatchBlock(¤tNode,openBlocksContext,QList()<* openBlocksContext,QListskipTypes,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;itype==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 *openBlocksContext) { VHDL_AST_Node *currentNode=*rootNode; VHDL_AST_Node *startNode=openBlocksContext->top(); if(Q_UNLIKELY(currentNode->type!=begin)) { qDebug()<<"Error expected begin keyword @line " <line <<" column "<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()<()<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(),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 *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()); 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()); break; default: walk_forward(¤tNode,-1); break; } } } openBlocksContext->pop(); closeAndMatchBlock(¤tNode,openBlocksContext,QList()); *rootNode=currentNode; return 0; } int __private_parse_Architecture_Identifier(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); 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 *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()< *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 " <line <<" column "<column<<"\n"; } } } else { walk_forward(¤tNode,-1); if(Q_UNLIKELY(currentNode->type!=identifier)) { qDebug()<<"Error expected return type @line " <line <<" column "<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(startNode->type | closedByEnd); return parse_body(rootNode,openBlocksContext); } else { startNode->type=static_cast(currentNode->type | closedBySemicolon); closeAndMatchBlock(rootNode,openBlocksContext,QList()); } return -1; } int VHDL_Tools::parse_DeclarativeBlock(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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 " <line <<" column "<column<<"\n"; } *rootNode=currentNode; return 0; } int VHDL_Tools::parse_Type(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); } } }while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); if(currentNode->type == semicolon) { closeAndMatchBlock(¤tNode,openBlocksContext,QList()); } 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()); 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()); } } }while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); if(currentNode->type == semicolon) { closeAndMatchBlock(¤tNode,openBlocksContext,QList()); } 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()); } } }while((((currentNode->type!=semicolon) && (currentNode->type!=units)) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); if(currentNode->type == semicolon) { closeAndMatchBlock(¤tNode,openBlocksContext,QList()); } 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()); CHECK_TOKEN_EXIT(rootNode,currentNode,semicolon,"\";\""); closeAndMatchBlock(¤tNode,openBlocksContext,QList()); break; default: break; } *rootNode=currentNode; return 0; } int VHDL_Tools::parse_Subtype(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); *rootNode=currentNode; return 0; } int VHDL_Tools::parse_Component(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()< *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()); } } }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()); } } walk_forward(¤tNode,-1); }while(((currentNode->type!=rightParen) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); closeAndMatchBlock(¤tNode,openBlocksContext,QList()); break; default: break; } *rootNode=currentNode; return 0; } int VHDL_Tools::parse_Units(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); if(currentNode->type!=endKw) { FORCE_CLOSETYPE(currentNode,closedBySemicolon); openBlocksContext->push(currentNode); } } }while((currentNode->type!=endKw) && currentNode->childs.count()); closeAndMatchBlock(¤tNode,openBlocksContext,QList()<move(openBlocksContext->pop()->parent()); *rootNode=currentNode; return 0; } int VHDL_Tools::parse_Record(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); if(currentNode->type!=endKw) { FORCE_CLOSETYPE(currentNode,closedBySemicolon); openBlocksContext->push(currentNode); } } }while((currentNode->type!=endKw) && currentNode->childs.count()); closeAndMatchBlock(¤tNode,openBlocksContext,QList()<move(openBlocksContext->pop()->parent()); *rootNode=currentNode; return 0; } int VHDL_Tools::parse_File(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); } } }while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); if(currentNode->type == semicolon) { closeAndMatchBlock(¤tNode,openBlocksContext,QList()); } *rootNode=currentNode; return 0; } int VHDL_Tools::parse_Alias(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); } } }while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); if(currentNode->type == semicolon) { closeAndMatchBlock(¤tNode,openBlocksContext,QList()); } *rootNode=currentNode; return 0; } int VHDL_Tools::parse_Report(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); } } }while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); if(currentNode->type == semicolon) { closeAndMatchBlock(¤tNode,openBlocksContext,QList()); } *rootNode=currentNode; return 0; } int VHDL_Tools::parse_Process(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); 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()< *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()); } } }while(((currentNode->type!=semicolon) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); if(Q_LIKELY(currentNode->type == semicolon)) { closeAndMatchBlock(¤tNode,openBlocksContext,QList()); } *rootNode=currentNode; return 0; } int VHDL_Tools::parse_Port_or_Generic(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); } *rootNode=currentNode; return 0; } int VHDL_Tools::parse_Block(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); openBlocksContext->push(currentNode); break; default: walk_forward(¤tNode,-1); break; } }while(((currentNode->type!=endKw) || (startNode!=openBlocksContext->top())) && currentNode->childs.count()); } closeAndMatchBlock(¤tNode,openBlocksContext,QList()< *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()); *rootNode=currentNode; return 0; } int VHDL_Tools::parse_Wait(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); *rootNode=currentNode; return 0; } int VHDL_Tools::parse_AssociationList(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); 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()); break; default: walk_forward(¤tNode,-1); break; } } } openBlocksContext->pop(); closeAndMatchBlock(¤tNode,openBlocksContext,QList()); *rootNode=currentNode; return 0; } int VHDL_Tools::parse_Case(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *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()); *rootNode=currentNode; return 0; } int VHDL_Tools::parse_When_case(VHDL_Tools::VHDL_AST_Node **rootNode, QStack *openBlocksContext) { VHDL_AST_Node *currentNode=*rootNode; VHDL_AST_Node *startNode=*rootNode; *rootNode=currentNode; return 0; }