#include "vhdl_file.h" #include VHDL_Tools::VHDL_File::VHDL_File() { this->scanner = NULL; } #define walkForward( node , code ) \ if((node)->childs.count())\ {\ (node) = (node)->childs.first();\ }\ else\ {\ return (code);\ }\ #define skipTokens(node,TokenType) while ((node)->type==(TokenType)){walkForward((node),-1);} bool VHDL_Tools::VHDL_File::parseFile(const QString &file, bool trashPreviousTree) { std::ifstream in_file( file.toStdString().c_str() ); if( ! in_file.good() ) return false; // if(scanner) // delete(scanner); // try // { // scanner = new VHDL_Tools::vhdl_Scanner( &in_file ,file); // } // catch( std::bad_alloc &ba ) // { // std::cerr << "Failed to allocate scanner: (" << // ba.what() << ")\n"; // return false; // } if(scanner==NULL) { try { scanner = new VHDL_Tools::vhdl_Scanner( &in_file ,file); } catch( std::bad_alloc &ba ) { std::cerr << "Failed to allocate scanner: (" << ba.what() << ")\n"; return false; } } scanner->newFile(&in_file,file,trashPreviousTree); while (scanner->scan()!=0); makeParseTree(scanner->getScanTree()); return false; } VHDL_Tools::VHDL_AST_Node *VHDL_Tools::VHDL_File::getParseTree() { return rootNode; } int VHDL_Tools::VHDL_File::makeParseTree(VHDL_AST_Node *rootNode) { this->rootNode = rootNode; VHDL_AST_Node *currentNode=rootNode; QStack openBlocks; openBlocks.push(rootNode); while (currentNode) { switch (currentNode->type) { case block: openBlocks.push(currentNode); walkForward(currentNode,-1); break; case entity: //Declaration or instanciation? if(!((currentNode->parent->type == colon) && (currentNode->parent->parent->type==identifier))) { openBlocks.push(currentNode); } walkForward(currentNode,-1); break; case units: if(openBlocks.top()->type==clause) { openBlocks.top()->type=units; walkForward(currentNode,-1); } break; case port: currentNode->type = static_cast(currentNode->type | closedBySemicolon); openBlocks.push(currentNode); break; case generic: if(!(currentNode->childs.first()->type==map)) { currentNode->type = static_cast(currentNode->type | closedBySemicolon); openBlocks.push(currentNode); } walkForward(currentNode,-1); break; case clause: openBlocks.push(currentNode); walkForward(currentNode,-1); break; case endKw: closeAndMatchBlock(¤tNode,&openBlocks,QList()<parent->type==port)||(openBlocks.top()->parent->type==generic)) closeAndMatchBlock(¤tNode,&openBlocks,QList(),false); else closeAndMatchBlock(¤tNode,&openBlocks,QList(),false); break; case semicolon: if(IS_CLOSED_BY_SEMICOLON(openBlocks.top()->type)) { closeAndMatchBlock(¤tNode,&openBlocks,QList(),false); } else { walkForward(currentNode,0); } break; default: walkForward(currentNode,0); break; } } return 0; } int VHDL_Tools::VHDL_File::closeAndMatchBlock(VHDL_Tools::VHDL_AST_Node **currentNode, QStack *openBlocksContext, QList skipTypes, bool endWithSemicolon) { VHDL_AST_Node* startNode = openBlocksContext->pop(); if( IS_CLOSED_BY(startNode->type,(*currentNode)->type)) { walkForward((*currentNode),-1); for(int i=0;itype==semicolon)) { walkForward((*currentNode),-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; } return 0; }