vhdl_file.cpp
169 lines
| 4.9 KiB
| text/x-c
|
CppLexer
/ vhdlparser / vhdl_file.cpp
r0 | #include "vhdl_file.h" | |||
r1 | #include <QDebug> | |||
r0 | ||||
VHDL_Tools::VHDL_File::VHDL_File() | ||||
{ | ||||
this->scanner = NULL; | ||||
} | ||||
r1 | #define walkForward( node , code ) \ | |||
if((node)->childs.count())\ | ||||
{\ | ||||
(node) = (node)->childs.first();\ | ||||
}\ | ||||
else\ | ||||
{\ | ||||
return (code);\ | ||||
}\ | ||||
r0 | ||||
r1 | ||||
#define skipTokens(node,TokenType) while ((node)->type==(TokenType)){walkForward((node),-1);} | ||||
bool VHDL_Tools::VHDL_File::parseFile(const QString &file, bool trashPreviousTree) | ||||
r0 | { | |||
std::ifstream in_file( file.toStdString().c_str() ); | ||||
if( ! in_file.good() ) return false; | ||||
r1 | // 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) | ||||
r0 | { | |||
r1 | 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; | ||||
} | ||||
r0 | } | |||
r1 | scanner->newFile(&in_file,file,trashPreviousTree); | |||
r0 | while (scanner->scan()!=0); | |||
r1 | makeParseTree(scanner->getScanTree()); | |||
r0 | return false; | |||
} | ||||
r1 | ||||
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<VHDL_AST_Node*> 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<VHDL_AST_Node_type>(currentNode->type | closedBySemicolon); | ||||
openBlocks.push(currentNode); | ||||
break; | ||||
case generic: | ||||
if(!(currentNode->childs.first()->type==map)) | ||||
{ | ||||
currentNode->type = static_cast<VHDL_AST_Node_type>(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<VHDL_AST_Node_type>()<<units<<block<<identifier,true); | ||||
break; | ||||
case leftParen: | ||||
openBlocks.push(currentNode); | ||||
walkForward(currentNode,-1); | ||||
break; | ||||
case rightParen: | ||||
if((openBlocks.top()->parent->type==port)||(openBlocks.top()->parent->type==generic)) | ||||
closeAndMatchBlock(¤tNode,&openBlocks,QList<VHDL_AST_Node_type>(),false); | ||||
else | ||||
closeAndMatchBlock(¤tNode,&openBlocks,QList<VHDL_AST_Node_type>(),false); | ||||
break; | ||||
case semicolon: | ||||
if(IS_CLOSED_BY_SEMICOLON(openBlocks.top()->type)) | ||||
{ | ||||
closeAndMatchBlock(¤tNode,&openBlocks,QList<VHDL_AST_Node_type>(),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<VHDL_Tools::VHDL_AST_Node *> *openBlocksContext, QList<VHDL_Tools::VHDL_AST_Node_type> skipTypes, bool endWithSemicolon) | ||||
{ | ||||
VHDL_AST_Node* startNode = openBlocksContext->pop(); | ||||
if( IS_CLOSED_BY(startNode->type,(*currentNode)->type)) | ||||
{ | ||||
walkForward((*currentNode),-1); | ||||
for(int i=0;i<skipTypes.length();i++) | ||||
{ | ||||
skipTokens((*currentNode),skipTypes.at(i)); | ||||
} | ||||
if(endWithSemicolon && ((*currentNode)->type==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; | ||||
} | ||||