1 /******************************************************************************
3 * Copyright (C) 2014 by M. Kreis
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
14 #include <qfileinfo.h>
15 #include <qcstringlist.h>
16 #include "vhdljjparser.h"
18 #include "vhdldocgen.h"
24 #include "commentscan.h"
26 #include "definition.h"
27 #include "searchindex.h"
28 #include "outputlist.h"
29 #include "arguments.h"
31 #include "VhdlParserIF.h"
33 using namespace vhdl::parser;
36 static ParserInterface *g_thisParser;
38 static QCString yyFileName;
39 static int yyLineNr = 1;
40 static int* lineParse;
41 static int iDocLine = -1;
42 static QCString inputString;
43 static Entry* gBlock = 0;
44 static Entry* previous = 0;
45 //-------------------------------------------------------
47 static Entry* oldEntry;
48 static bool varr=FALSE;
49 static QCString varName;
51 static QList<Entry> instFiles;
52 static QList<Entry> libUse;
53 static QList<Entry> lineEntry;
55 Entry* VhdlParser::currentCompound=0;
56 Entry* VhdlParser::tempEntry=0;
57 Entry* VhdlParser::lastEntity=0 ;
58 Entry* VhdlParser::lastCompound=0 ;
59 Entry* VhdlParser::current=0;
60 Entry* VhdlParser::current_root = 0;
61 QCString VhdlParser::compSpec;
62 QCString VhdlParser::currName;
63 QCString VhdlParser::confName;
64 QCString VhdlParser::genLabels;
65 QCString VhdlParser::lab;
66 QCString VhdlParser::forL;
68 int VhdlParser::param_sec = 0;
69 int VhdlParser::parse_sec=0;
70 int VhdlParser::currP=0;
71 int VhdlParser::levelCounter;
73 static QList<VhdlConfNode> configL;
83 static QCString strComment;
85 static const char *vhdlFileName = 0;
87 bool checkMultiComment(QCString& qcs,int line);
88 QList<Entry>* getEntryAtLine(const Entry* ce,int line);
90 //-------------------------------------
92 QList<VhdlConfNode>& getVhdlConfiguration() { return configL; }
93 QList<Entry>& getVhdlInstList() { return instFiles; }
95 Entry* getVhdlCompound()
97 if (VhdlParser::lastEntity) return VhdlParser::lastEntity;
98 if (VhdlParser::lastCompound) return VhdlParser::lastCompound;
102 bool isConstraintFile(const QCString &fileName,const QCString &ext)
104 return fileName.right(ext.length())==ext;
108 void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,Entry *root,
115 // fprintf(stderr,"\n ============= %s\n ==========\n",fileBuf);
117 if (strlen(fileName)==0)
122 yyFileName+=fileName;
124 bool xilinx_ucf=isConstraintFile(yyFileName,".ucf");
125 bool altera_qsf=isConstraintFile(yyFileName,".qsf");
127 // support XILINX(ucf) and ALTERA (qsf) file
131 VhdlDocGen::parseUCF(fileBuf,root,yyFileName,FALSE);
136 VhdlDocGen::parseUCF(fileBuf,root,yyFileName,TRUE);
139 libUse.setAutoDelete(true);
141 VhdlParser::current_root=root;
142 VhdlParser::lastCompound=0;
143 VhdlParser::lastEntity=0;
144 VhdlParser::currentCompound=0;
145 VhdlParser::lastEntity=0;
147 VhdlParser::current=new Entry();
148 VhdlParser::initEntry(VhdlParser::current);
149 groupEnterFile(fileName,yyLineNr);
150 vhdlFileName = fileName;
151 lineParse=new int[200]; // Dimitri: dangerous constant: should be bigger than largest token id in VhdlParserConstants.h
152 VhdlParserIF::parseVhdlfile(fileBuf,inLine);
154 delete VhdlParser::current;
155 VhdlParser::current=0;
158 VhdlParser::mapLibPackage(root);
161 yyFileName.resize(0);
163 VhdlDocGen::resetCodeVhdlParserState();
167 void VhdlParser::lineCount()
172 void VhdlParser::lineCount(const char* text)
174 for (const char* c=text ; *c ; ++c )
176 yyLineNr += (*c == '\n') ;
180 void isVhdlDocPending()
182 if (!str_doc.pending) return;
184 str_doc.pending=FALSE;
185 oldEntry=0; // prevents endless recursion
186 iDocLine=str_doc.iDocLine;
187 VhdlParser::handleCommentBlock(str_doc.doc,str_doc.brief);
191 void VhdlParser::initEntry(Entry *e)
193 e->fileName = yyFileName;
194 e->lang = SrcLangExt_VHDL;
199 void VhdlParser::newEntry()
201 if (current->spec==VhdlDocGen::ENTITY ||
202 current->spec==VhdlDocGen::PACKAGE ||
203 current->spec==VhdlDocGen::ARCHITECTURE ||
204 current->spec==VhdlDocGen::PACKAGE_BODY)
206 current_root->addSubEntry(current);
212 lastCompound->addSubEntry(current);
218 lastEntity->addSubEntry(current);
222 current_root->addSubEntry(current);
227 current = new Entry ;
231 void VhdlParser::handleFlowComment(const char* doc)
235 if (VhdlDocGen::getFlowMember())
238 qcs=qcs.stripWhiteSpace();
239 qcs.stripPrefix("--#");
240 FlowChart::addFlowChart(FlowChart::COMMENT_NO,0,0,qcs.data());
245 void VhdlParser::handleCommentBlock(const char* doc1,bool brief)
250 // fprintf(stderr,"\n %s",doc.data());
251 if (doc.isEmpty()) return;
253 if (checkMultiComment(doc,yyLineNr))
255 strComment.resize(0);
259 VhdlDocGen::prepareComment(doc);
261 bool needsEntry=FALSE;
262 Protection protection=Public;
264 if (oldEntry==current)
266 //printf("\n find pending message < %s > at line: %d \n ",doc.data(),iDocLine);
268 str_doc.iDocLine=iDocLine;
270 str_doc.pending=TRUE;
278 current->briefLine = yyLineNr;
282 current->docLine = yyLineNr;
284 // printf("parseCommentBlock file<%s>\n [%s]\n at line [%d] \n ",yyFileName.data(),doc.data(),iDocLine);
286 int j=doc.find("[plant]");
293 while (parseCommentBlock(
298 iDocLine, // line of block start
308 //printf("parseCommentBlock position=%d [%s]\n",position,doc.data()+position);
309 if (needsEntry) newEntry();
316 current->name=varName;
317 current->section=Entry::VARIABLEDOC_SEC;
323 strComment.resize(0);
326 void VHDLLanguageScanner::parsePrototype(const char *text)
332 void VhdlParser::addCompInst(const char *n, const char* instName, const char* comp,int iLine)
334 current->spec=VhdlDocGen::INSTANTIATION;
335 current->section=Entry::VARIABLE_SEC;
336 current->startLine=iLine;
337 current->bodyLine=iLine;
338 current->type=instName; // foo:instname e.g proto or work. proto(ttt)
339 current->exception=genLabels.lower(); // |arch|label1:label2...
340 current->name=n; // foo
343 current->args=lastCompound->name; // architecture name
345 current->includeName=comp; // component/enity/configuration
346 int u=genLabels.find("|",1);
349 current->write=genLabels.right(genLabels.length()-u);
350 current->read=genLabels.left(u);
352 //printf (" \n genlable: [%s] inst: [%s] name: [%s] %d\n",n,instName,comp,iLine);
356 current->args=lastCompound->name;
357 if (true) // !findInstant(current->type))
360 instFiles.append(new Entry(*current));
363 Entry *temp=current; // hold current pointer (temp=oldEntry)
364 current=new Entry; // (oldEntry != current)
373 void VhdlParser::addVhdlType(const char *n,int startLine,int section,
374 uint64 spec,const char* args,const char* type,Protection prot)
377 if (isFuncProcProced() || VhdlDocGen::getFlowMember()) return;
379 if (parse_sec==GEN_SEC)
381 spec= VhdlDocGen::GENERIC;
384 QCStringList ql=QCStringList::split(",",name);
386 for (uint u=0;u<ql.count();u++)
389 current->startLine=startLine;
390 current->bodyLine=startLine;
391 current->section=section;
393 current->fileName=yyFileName;
394 if (current->args.isEmpty())
399 current->protection=prot;
401 if (!lastCompound && (section==Entry::VARIABLE_SEC) && (spec == VhdlDocGen::USE || spec == VhdlDocGen::LIBRARY) )
403 libUse.append(new Entry(*current));
410 void VhdlParser::createFunction(const char *imp,uint64 spec,const char *fn)
412 QCString impure(imp);
415 current->section=Entry::FUNCTION_SEC;
417 if (impure=="impure" || impure=="pure")
419 current->exception=impure;
422 if (parse_sec==GEN_SEC)
424 current->spec= VhdlDocGen::GENERIC;
425 current->section=Entry::FUNCTION_SEC;
428 if (currP==VhdlDocGen::PROCEDURE)
430 current->name=impure;
431 current->exception="";
438 if (spec==VhdlDocGen::PROCESS)
441 current->name=impure;
442 VhdlDocGen::deleteAllChars(current->args,' ');
443 if (!fname.isEmpty())
445 QCStringList q1=QCStringList::split(",",fname);
446 for (uint ii=0;ii<q1.count();ii++)
448 Argument *arg=new Argument;
450 current->argList->append(arg);
458 bool VhdlParser::isFuncProcProced()
460 if (currP==VhdlDocGen::FUNCTION ||
461 currP==VhdlDocGen::PROCEDURE ||
462 currP==VhdlDocGen::PROCESS
470 void VhdlParser::pushLabel( QCString &label,QCString & val)
476 QCString VhdlParser::popLabel(QCString & q)
478 int i=q.findRev("|");
484 void VhdlParser::addConfigureNode(const char* a,const char*b, bool,bool isLeaf,bool inlineConf)
496 if (!configL.isEmpty())
498 VhdlConfNode* vc=configL.getLast();
504 else if (level<levelCounter)
511 else if (level>levelCounter)
523 confName=lastCompound->name;
526 //fprintf(stderr,"\n[%s %d %d]\n",forL.data(),levelCounter,level);
527 co=new VhdlConfNode(a,b,confName.lower().data(),forL.lower().data(),isLeaf);
531 co->isInlineConf=TRUE;
538 void VhdlParser::addProto(const char *s1,const char *s2,const char *s3,
539 const char *s4,const char *s5,const char *s6)
541 (void)s5; // avoid unused warning
543 QCStringList ql=QCStringList::split(",",name);
545 for (uint u=0;u<ql.count();u++)
547 Argument *arg=new Argument;
559 if (parse_sec==GEN_SEC && param_sec==0)
564 if (parse_sec==PARAM_SEC)
572 current->argList->append(arg);
580 * adds the library|use statements to the next class (entity|package|architecture|package body
590 void VhdlParser::mapLibPackage( Entry* root)
592 QList<Entry> epp=libUse;
593 EntryListIterator eli(epp);
595 for (;(rt=eli.current());++eli)
597 if (addLibUseClause(rt->name))
600 EntryListIterator eLib(*root->children());
602 for (eLib.toFirst();(current=eLib.current());++eLib)
604 if (VhdlDocGen::isVhdlClass(current))
606 if (current->startLine > rt->startLine)
609 current->addSubEntry(new Entry(*rt));
616 root->addSubEntry(new Entry(*rt));
622 bool VhdlParser::addLibUseClause(const QCString &type)
624 static bool showIEEESTD=Config_getBool(FORCE_LOCAL_INCLUDES);
626 if (showIEEESTD) // all standard packages and libraries will not be shown
628 if (type.lower().stripPrefix("ieee")) return FALSE;
629 if (type.lower().stripPrefix("std")) return FALSE;
634 int VhdlParser::getLine()
639 void VhdlParser::setLineParsed(int tok)
641 lineParse[tok]=yyLineNr;
644 int VhdlParser::getLine(int tok)
646 int val=lineParse[tok];
648 //assert(val>=0 && val<=yyLineNr);
653 void VhdlParser::createFlow()
655 if (!VhdlDocGen::getFlowMember())
661 if (currP==VhdlDocGen::FUNCTION)
664 FlowChart::alignFuncProc(q,tempEntry->argList,true);
667 else if (currP==VhdlDocGen::PROCEDURE)
670 FlowChart::alignFuncProc(q,tempEntry->argList,false);
675 q=":process( "+tempEntry->args;
679 q.prepend(VhdlDocGen::getFlowMember()->name().data());
681 FlowChart::addFlowChart(FlowChart::START_NO,q,0);
683 if (currP==VhdlDocGen::FUNCTION)
687 else if (currP==VhdlDocGen::PROCEDURE)
696 FlowChart::addFlowChart(FlowChart::END_NO,ret,0);
697 // FlowChart::printFlowList();
698 FlowChart::writeFlowChart();
702 void VhdlParser::setMultCommentLine()
707 void VhdlParser::oneLineComment(QCString qcs)
709 int j=qcs.find("--!");
710 qcs=qcs.right(qcs.length()-3-j);
711 if (!checkMultiComment(qcs,iDocLine))
713 handleCommentBlock(qcs,TRUE);
718 bool checkMultiComment(QCString& qcs,int line)
720 QList<Entry> *pTemp=getEntryAtLine(VhdlParser::current_root,line);
722 if (pTemp->isEmpty()) return false;
724 VhdlDocGen::prepareComment(qcs);
725 while (!pTemp->isEmpty())
727 Entry *e=(Entry*)pTemp->getFirst();
731 pTemp->removeFirst();
736 // returns the vhdl parsed types at line xxx
737 QList<Entry>* getEntryAtLine(const Entry* ce,int line)
739 EntryListIterator eli(*ce->children());
741 for (;(rt=eli.current());++eli)
743 if (rt->bodyLine==line)
745 lineEntry.insert(0,rt);
748 getEntryAtLine(rt,line);
753 const char *getVhdlFileName(void)