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

File last commit:

r1:648bfc2c61c7 default
r1:648bfc2c61c7 default
Show More
vhdl_file.cpp
169 lines | 4.9 KiB | text/x-c | CppLexer
#include "vhdl_file.h"
#include <QDebug>
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<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(&currentNode,&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(&currentNode,&openBlocks,QList<VHDL_AST_Node_type>(),false);
else
closeAndMatchBlock(&currentNode,&openBlocks,QList<VHDL_AST_Node_type>(),false);
break;
case semicolon:
if(IS_CLOSED_BY_SEMICOLON(openBlocks.top()->type))
{
closeAndMatchBlock(&currentNode,&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;
}