diff options
Diffstat (limited to 'src/vhdljjparser.cpp')
-rw-r--r-- | src/vhdljjparser.cpp | 828 |
1 files changed, 828 insertions, 0 deletions
diff --git a/src/vhdljjparser.cpp b/src/vhdljjparser.cpp new file mode 100644 index 0000000..f31c9fb --- /dev/null +++ b/src/vhdljjparser.cpp @@ -0,0 +1,828 @@ +/****************************************************************************** + * + * Copyright (C) 2014 by M. Kreis + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + */ + +#include <qcstring.h> +#include <qfileinfo.h> +#include <qstringlist.h> +#include "vhdljjparser.h" +#include "vhdlcode.h" +#include "vhdldocgen.h" +#include "message.h" +#include "config.h" +#include "doxygen.h" +#include "util.h" +#include "language.h" +#include "commentscan.h" +#include "index.h" +#include "definition.h" +#include "searchindex.h" +#include "outputlist.h" +#include "arguments.h" +#include "types.h" +#include "VhdlParserIF.h" + +using namespace vhdl::parser; +using namespace std; + +static ParserInterface *g_thisParser; + +static QCString yyFileName; +static int yyLineNr = 1; +static int* lineParse; +static int iDocLine = -1; +static QCString inputString; +static Entry gBlock; +static Entry* previous = 0; +#if 0 +int iLine; +QStringList qrl; +ParserInterface *g_thisParser; +int inputPosition; +int inputLen; +int startComment = 0; +QFile inputFile; +QCString inbuf; + +QCString yyFileName; +bool g_lexInit = FALSE; +int yyLineNr = 1; +int g_lastCommentContext = 0; +bool docBlockAutoBrief; +char docBlockTerm; +int iDocLine = -1; +int num_chars; +int* lineParse; +#endif +//------------------------------------------------------- + +static Entry* oldEntry; +static bool varr=FALSE; +static QCString varName; + +static QList<Entry> instFiles; +static QList<Entry> libUse; +static QList<Entry> lineEntry; + +Entry* VhdlParser::currentCompound=0; +Entry* VhdlParser::tempEntry=0; +Entry* VhdlParser::lastEntity=0 ; +Entry* VhdlParser::lastCompound=0 ; +Entry* VhdlParser::current=0; +Entry* VhdlParser::current_root = 0; +QCString VhdlParser::compSpec; +QCString VhdlParser::currName; +QCString VhdlParser::confName; +QCString VhdlParser::genLabels; +QCString VhdlParser::lab; +QCString VhdlParser::forL; + +int VhdlParser::param_sec = 0; +int VhdlParser::parse_sec=0; +int VhdlParser::currP=0; +int VhdlParser::levelCounter; + +static QList<VhdlConfNode> configL; + +struct +{ + QCString doc; + bool brief; + bool pending; + int iDocLine; +} str_doc; + +static bool doxComment=FALSE; // doxygen comment ? +static QCString strComment; +static int iCodeLen; + +bool checkMultiComment(QCString& qcs,int line); +QList<Entry>* getEntryAtLine(const Entry* ce,int line); + +//------------------------------------- + +QList<VhdlConfNode>& getVhdlConfiguration() { return configL; } +QList<Entry>& getVhdlInstList() { return instFiles; } + +Entry* getVhdlCompound() +{ + if (VhdlParser::lastEntity) return VhdlParser::lastEntity; + if (VhdlParser::lastCompound) return VhdlParser::lastCompound; + return NULL; +} + +void startCodeBlock(int index) +{ + int ll=strComment.length(); + iCodeLen=inputString.findRev(strComment.data())+ll; + // fprintf(stderr,"\n startin code..%d %d %d\n",iCodeLen,num_chars,ll); + //assert(false); + gBlock.reset(); + int len=strComment.length(); + QCString name=strComment.right(len-index);// + name=VhdlDocGen::getIndexWord(name.data(),1); + if (!name) + gBlock.name="misc"+ VhdlDocGen::getRecordNumber(); + else + gBlock.name=name; + + //int li=strComment.contains('\n'); + + gBlock.startLine=yyLineNr; + gBlock.bodyLine=yyLineNr; + + strComment=strComment.left(index); + VhdlDocGen::prepareComment(strComment); + gBlock.brief+=strComment; +} + +void makeInlineDoc(int endCode) +{ + int len=endCode-iCodeLen; + QCString par=inputString.mid(iCodeLen,len); + //fprintf(stderr,"\n inline code: \n<%s>",par.data()); + gBlock.doc=par; + gBlock.inbodyDocs=par; + gBlock.section=Entry::VARIABLE_SEC; + gBlock.spec=VhdlDocGen::MISCELLANEOUS; + gBlock.fileName = yyFileName; + gBlock.endBodyLine=yyLineNr-1; + gBlock.lang=SrcLangExt_VHDL; + Entry *temp=new Entry(gBlock); + Entry* compound=getVhdlCompound(); + + if (compound) + { + compound->addSubEntry(temp); + } + else + { + temp->type="misc"; // global code like library ieee... + VhdlParser::current_root->addSubEntry(temp); + } + strComment.resize(0); + gBlock.reset(); +}// makeInlineDoc + + +bool isConstraintFile(const QCString &fileName,const QCString &ext) +{ + return fileName.right(ext.length())==ext; +} + + +void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,Entry *root, + bool ,QStrList&) +{ + g_thisParser=this; + bool inLine=false; + inputString=fileBuf; + if (strlen(fileName)==0) + { + inLine=true; + } + + yyFileName+=fileName; + + bool xilinx_ucf=isConstraintFile(yyFileName,".ucf"); + bool altera_qsf=isConstraintFile(yyFileName,".qsf"); + + // support XILINX(ucf) and ALTERA (qsf) file + + if (xilinx_ucf) + { + VhdlDocGen::parseUCF(fileBuf,root,yyFileName,FALSE); + return; + } + if (altera_qsf) + { + VhdlDocGen::parseUCF(fileBuf,root,yyFileName,TRUE); + return; + } + libUse.setAutoDelete(true); + yyLineNr=1; + VhdlParser::current_root=root; + VhdlParser::lastCompound=0; + VhdlParser::lastEntity=0; + VhdlParser::currentCompound=0; + VhdlParser::lastEntity=0; + VhdlParser::current=new Entry(); + VhdlParser::initEntry(VhdlParser::current); + groupEnterFile(fileName,yyLineNr); + lineParse=new int[200]; + VhdlParserIF::parseVhdlfile(fileBuf,inLine); + + delete VhdlParser::current; + VhdlParser::current=0; + + if (!inLine) + VhdlParser::mapLibPackage(root); + + delete lineParse; + yyFileName.resize(0); + libUse.clear(); + VhdlDocGen::resetCodeVhdlParserState(); +} + +void VhdlParser::lineCount(){ yyLineNr++; } + +void VhdlParser::lineCount(const char* text) +{ + for (const char* c=text ; *c ; ++c ) + { + yyLineNr += (*c == '\n') ; + } +} + +void isVhdlDocPending() +{ + if (!str_doc.pending) return; + + str_doc.pending=FALSE; + oldEntry=0; // prevents endless recursion + iDocLine=str_doc.iDocLine; + VhdlParser::handleCommentBlock(str_doc.doc,str_doc.brief); + iDocLine=-1; +} + +void VhdlParser::initEntry(Entry *e) +{ + e->fileName = yyFileName; + e->lang = SrcLangExt_VHDL; + isVhdlDocPending(); + initGroupInfo(e); +} + +void VhdlParser::newEntry() +{ + if (current->spec==VhdlDocGen::ENTITY || + current->spec==VhdlDocGen::PACKAGE || + current->spec==VhdlDocGen::ARCHITECTURE || + current->spec==VhdlDocGen::PACKAGE_BODY) + { + current_root->addSubEntry(current); + } + else + { + if (lastCompound) + { + lastCompound->addSubEntry(current); + } + else + { + if (lastEntity) + { + lastEntity->addSubEntry(current); + } + else + { + current_root->addSubEntry(current); + } + } + } + previous = current; + current = new Entry ; + initEntry(current); +} + +bool checkInlineCode(QCString & doc) +{ + int index=doc.find("\\code"); + + if (index>0) + { + strComment+=doc; + startCodeBlock(index); + doxComment=TRUE; + return true; + } + return false; +} + +void VhdlParser::handleFlowComment(const char* doc) +{ + lineCount(doc); + if (VhdlDocGen::getFlowMember()) + { + QCString qcs(doc); + qcs=qcs.stripWhiteSpace(); + qcs.stripPrefix("--#"); + FlowChart::addFlowChart(FlowChart::COMMENT_NO,0,0,qcs.data()); + } +} + +void VhdlParser::handleCommentBlock(const char* doc1,bool brief) +{ + int position=0; + static bool isIn; + QCString doc(doc1); + if (doc.isEmpty()) return; + + if (checkMultiComment(doc,yyLineNr)) + { + lineCount(doc1); + return; + } + + isIn=checkInlineCode(doc); + bool isEndCode=doc.contains("\\endcode"); + // empty comment --! + if (isEndCode) + { + int end=inputString.find(doc.data(),iCodeLen); + makeInlineDoc(end); + strComment.resize(0); + isIn=false; + } + if (isIn) + { + isIn=false; + lineCount(doc1); + return; + } + + VhdlDocGen::prepareComment(doc); + + bool needsEntry=FALSE; + Protection protection=Public; + int lineNr = iDocLine; + + if (oldEntry==current) + { + //printf("\n find pending message < %s > at line: %d \n ",doc.data(),iDocLine); + str_doc.doc=doc; + str_doc.iDocLine=iDocLine; + str_doc.brief=brief; + str_doc.pending=TRUE; + return; + } + + oldEntry=current; + + if (brief) + { + current->briefLine = yyLineNr; + } + else + { + current->docLine = yyLineNr; + } + // printf("parseCommentBlock file<%s>\n [%s]\n",yyFileName.data(),doc.data()); + while (parseCommentBlock( + g_thisParser, + current, + doc, // text + yyFileName, // file + lineNr, // line of block start + brief, + 0, + FALSE, + protection, + position, + needsEntry + ) + ) + { + //printf("parseCommentBlock position=%d [%s]\n",position,doc.data()+position); + if (needsEntry) newEntry(); + } + if (needsEntry) + { + if (varr) + { + varr=FALSE; + current->name=varName; + current->section=Entry::VARIABLEDOC_SEC; + varName=""; + } + newEntry(); + } + lineCount(doc1); +} + +void VHDLLanguageScanner::parsePrototype(const char *text) +{ + varName=text; + varr=TRUE; +} + +void VhdlParser::addCompInst(char *n, char* instName, char* comp,int iLine) +{ + current->spec=VhdlDocGen::INSTANTIATION; + current->section=Entry::VARIABLE_SEC; + current->startLine=iLine; + current->bodyLine=iLine; + current->type=instName; // foo:instname e.g proto or work. proto(ttt) + current->exception=genLabels.lower(); // |arch|label1:label2... + current->name=n; // foo + current->args=lastCompound->name; // architecture name + current->includeName=comp; // component/enity/configuration + int u=genLabels.find("|",1); + if (u>0) + { + current->write=genLabels.right(genLabels.length()-u); + current->read=genLabels.left(u); + } + //printf (" \n genlable: [%s] inst: [%s] name: [%s] %d\n",n,instName,comp,iLine); + + if (lastCompound) + { + current->args=lastCompound->name; + if (true) // !findInstant(current->type)) + { + initEntry(current); + instFiles.append(new Entry(*current)); + } + + Entry *temp=current; // hold current pointer (temp=oldEntry) + current=new Entry; // (oldEntry != current) + delete temp; + } + else + { + newEntry(); + } +} + +void VhdlParser::addVhdlType(const char *n,int startLine,int section, + uint64 spec,const char* args,const char* type,Protection prot) +{ + static QRegExp reg("[\\s]"); + QCString name(n); + if (isFuncProcProced() || VhdlDocGen::getFlowMember()) return; + + if (parse_sec==GEN_SEC) + { + spec= VhdlDocGen::GENERIC; + } + + QStringList ql=QStringList::split(",",name,FALSE); + + for (uint u=0;u<ql.count();u++) + { + current->name=ql[u].utf8(); + current->startLine=startLine; + current->bodyLine=startLine; + current->section=section; + current->spec=spec; + current->fileName=yyFileName; + if (current->args.isEmpty()) + { + current->args=args; + } + current->type=type; + current->protection=prot; + + if (!lastCompound && (section==Entry::VARIABLE_SEC) && (spec == VhdlDocGen::USE || spec == VhdlDocGen::LIBRARY) ) + { + libUse.append(new Entry(*current)); + current->reset(); + } + newEntry(); + } +} + +void VhdlParser::createFunction(const char *imp,uint64 spec,const char *fn) +{ + QCString impure(imp); + QCString fname(fn); + current->spec=spec; + current->section=Entry::FUNCTION_SEC; + + if (impure=="impure" || impure=="pure") + { + current->exception=impure; + } + + if (parse_sec==GEN_SEC) + { + current->spec= VhdlDocGen::GENERIC; + current->section=Entry::FUNCTION_SEC; + } + + if (currP==VhdlDocGen::PROCEDURE) + { + current->name=impure; + current->exception=""; + } + else + { + current->name=fname; + } + + if (spec==VhdlDocGen::PROCESS) + { + current->args=fname; + current->name=impure; + VhdlDocGen::deleteAllChars(current->args,' '); + if (!fname.isEmpty()) + { + QStringList q1=QStringList::split(",",fname); + for (uint ii=0;ii<q1.count();ii++) + { + Argument *arg=new Argument; + arg->name=q1[ii].utf8(); + current->argList->append(arg); + } + } + return; + } + } + + +bool VhdlParser::isFuncProcProced() +{ + if (currP==VhdlDocGen::FUNCTION || + currP==VhdlDocGen::PROCEDURE || + currP==VhdlDocGen::PROCESS + ) + { + return TRUE; + } + return FALSE; +} + +void VhdlParser::pushLabel( QCString &label,QCString & val) +{ + label+="|"; + label+=val; +} + + QCString VhdlParser::popLabel(QCString & q) +{ + QCString u=q; + int i=q.findRev("|"); + if (i<0) return ""; + q = q.left(i); + return q; +} + +void VhdlParser::addConfigureNode(const char* a,const char*b, bool,bool isLeaf,bool inlineConf) +{ + VhdlConfNode* co=0; + QCString ent,arch,lab; + QCString l=genLabels; + ent=a; + // lab = VhdlDocGen::parseForConfig(ent,arch); + + if (b) + { + ent=b; + // lab=VhdlDocGen::parseForBinding(ent,arch); + } + int level=0; + + if (!configL.isEmpty()) + { + VhdlConfNode* vc=configL.getLast(); + level=vc->level; + if (levelCounter==0) + { + pushLabel(forL,ent); + } + else if (level<levelCounter) + { + if (!isLeaf) + { + pushLabel(forL,ent); + } + } + else if (level>levelCounter) + { + forL=popLabel(forL); + } + } + else + { + pushLabel(forL,ent); + } + + if (inlineConf) + { + confName=lastCompound->name; + } + + //fprintf(stderr,"\n[%s %d %d]\n",forL.data(),levelCounter,level); + co=new VhdlConfNode(a,b,confName.lower().data(),forL.lower().data(),isLeaf); + + if (inlineConf) + { + co->isInlineConf=TRUE; + } + + configL.append(co); + +}// addConfigure + + +void VhdlParser::addProto(const char *s1,const char *s2,const char *s3, + const char *s4,const char *s5,const char *s6) +{ + (void)s5; // avoid unused warning + static QRegExp reg("[\\s]"); + QCString name=s2; + QStringList ql=QStringList::split(",",name,FALSE); + + for (uint u=0;u<ql.count();u++) + { + Argument *arg=new Argument; + arg->name=ql[u].utf8(); + if (s3) + { + arg->type=s3; + } + arg->type+=" "; + arg->type+=s4; + if (s6) + { + arg->type+=s6; + } + if (parse_sec==GEN_SEC && param_sec==0) + { + arg->defval="gen!"; + } + + if (parse_sec==PARAM_SEC) + { + // assert(false); + } + + arg->defval+=s1; + arg->attrib="";//s6; + + current->argList->append(arg); + current->args+=s2; + current->args+=","; + } +} + + +/* + * adds the library|use statements to the next class (entity|package|architecture|package body + * library ieee + * entity xxx + * ..... + * library + * package + * enity zzz + * ..... + * and so on.. + */ +void VhdlParser::mapLibPackage( Entry* root) +{ + QList<Entry> epp=libUse; + EntryListIterator eli(epp); + Entry *rt; + for (;(rt=eli.current());++eli) + { + if (addLibUseClause(rt->name)) + { + Entry *current; + EntryListIterator eLib(*root->children()); + bool bFound=FALSE; + for (eLib.toFirst();(current=eLib.current());++eLib) + { + if (VhdlDocGen::isVhdlClass(current)) + { + if (current->startLine > rt->startLine) + { + bFound=TRUE; + current->addSubEntry(new Entry(*rt)); + break; + } + } + }//for + if (!bFound) + { + root->addSubEntry(new Entry(*rt)); + } + } //if + }// for +}//MapLib + +bool VhdlParser::addLibUseClause(const QCString &type) +{ + static bool showIEEESTD=Config_getBool("FORCE_LOCAL_INCLUDES"); + + if (showIEEESTD) // all standard packages and libraries will not be shown + { + if (type.lower().stripPrefix("ieee")) return FALSE; + if (type.lower().stripPrefix("std")) return FALSE; + } + return TRUE; +} + +int VhdlParser::getLine() +{ + return yyLineNr; +} + +void VhdlParser::setLineParsed(int tok) +{ + lineParse[tok]=yyLineNr; +} + +int VhdlParser::getLine(int tok) +{ + int val=lineParse[tok]; + if (val<0) val=0; + //assert(val>=0 && val<=yyLineNr); + return val; +} + + +void VhdlParser::createFlow() +{ + if (!VhdlDocGen::getFlowMember()) + { + return; + } + QCString q,ret; + + if (currP==VhdlDocGen::FUNCTION) + { + q=":function( "; + FlowChart::alignFuncProc(q,tempEntry->argList,true); + q+=")"; + } + else if (currP==VhdlDocGen::PROCEDURE) + { + q=":procedure ("; + FlowChart::alignFuncProc(q,tempEntry->argList,false); + q+=")"; + } + else + { + q=":process( "+tempEntry->args; + q+=")"; + } + + q.prepend(VhdlDocGen::getFlowMember()->name().data()); + + FlowChart::addFlowChart(FlowChart::START_NO,q,0); + + if (currP==VhdlDocGen::FUNCTION) + { + ret="end function "; + } + else if (currP==VhdlDocGen::PROCEDURE) + { + ret="end procedure"; + } + else + { + ret="end process "; + } + + FlowChart::addFlowChart(FlowChart::END_NO,ret,0); + // FlowChart::printFlowList(); + FlowChart::writeFlowChart(); + currP=0; +} + +bool checkMultiComment(QCString& qcs,int line) +{ + QList<Entry> *pTemp=getEntryAtLine(VhdlParser::current_root,line); + + if (pTemp->isEmpty()) return false; + + //int ii=pTemp->count(); + // qcs.stripPrefix("--!"); + VhdlDocGen::prepareComment(qcs); + while (!pTemp->isEmpty()) + { + Entry *e=(Entry*)pTemp->getFirst(); + e->briefLine=line; + e->brief+=qcs; + iDocLine=-1; + pTemp->removeFirst(); + //ii=pTemp->count(); + } + return true; +} + +// returns the vhdl parsed types at line xxx +QList<Entry>* getEntryAtLine(const Entry* ce,int line) +{ + EntryListIterator eli(*ce->children()); + Entry *rt; + for (;(rt=eli.current());++eli) + { + if (rt->bodyLine==line) + { + lineEntry.insert(0,rt); + } // if + + getEntryAtLine(rt,line); + } + return &lineEntry; +} + |