1 /******************************************************************************
3 * Copyright (C) 1997-2014 by Dimitri van Heesch.
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.
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
15 /******************************************************************************
16 * Parser for syntax hightlighting and references for vhdl subset
18 * supports VHDL-87/93/2008
19 ******************************************************************************/
31 #include <qstringlist.h>
36 #include "outputlist.h"
38 #include "membername.h"
39 #include "searchindex.h"
40 #include "vhdldocgen.h"
41 #include "arguments.h"
47 #define YY_NEVER_INTERACTIVE 1
50 // Toggle for some debugging info
51 //#define DBG_CTX(x) fprintf x
52 #define DBG_CTX(x) do { } while(0)
55 /* -----------------------------------------------------------------
59 // ----------------- <vhdl> ----------------------------------
61 //static bool isPackBody=FALSE;
62 //static bool isStartMap;
63 static bool isFuncProto=FALSE;
64 static bool isComponent=FALSE;
65 static bool isPackageBody=FALSE;
66 static bool isProto = FALSE;
67 static bool g_startCode = FALSE;
68 static QCString g_PrevString;
69 static QCString g_CurrClass;
70 static QDict<QCString>g_vhdlKeyDict;
71 static QCString g_tempClass;
72 static QCString g_tempComp;
73 static QCString g_PortMapComp;
74 static MemberDef *g_vhdlMember;
75 static QCString g_FuncProto;
77 //-----------------------------------------------------------
79 static CodeOutputInterface * g_code;
80 static QCString g_curClassName;
81 static QCString g_parmType;
82 static QCString g_parmName;
83 static const char * g_inputString; //!< the code fragment as text
84 static int g_inputPosition; //!< read offset during parsing
85 static int g_inputLines; //!< number of line in the code fragment
86 static int g_yyLineNr; //!< current line number
87 static bool g_needsTermination;
88 static Definition *g_searchCtx;
90 static QCString g_exampleName;
91 static QCString g_exampleFile;
93 static QCString g_type;
94 static QCString g_name;
95 static QCString g_args;
96 static QCString g_classScope;
98 static QCString g_CurrScope;
100 static FileDef * g_sourceFileDef;
101 static Definition * g_currentDefinition;
102 static MemberDef * g_currentMemberDef;
103 static bool g_includeCodeFragment;
104 static const char * g_currentFontClass;
106 static bool g_lexInit = FALSE;
107 static int g_braceCount=0;
110 static void writeFont(const char *s,const char* text);
111 static void generateMemLink(CodeOutputInterface &ol,QCString &clName,QCString& memberName);
112 static bool writeColoredWord(QCString& word );
113 static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName, bool typeOnly=FALSE);
114 static void endFontClass();
115 static void startFontClass(const char *s);
116 //-------------------------------------------------------------------
119 static void setCurrentDoc(const QCString &anchor)
121 if (Doxygen::searchIndex)
125 Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE);
129 Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE);
134 static bool checkVhdlString(QCString &name)
136 if (name.isEmpty()) return FALSE;
137 static QRegExp regg("[\\s\"]");
139 int len=name.length();
140 if (name.at(0)=='"' && name.at(len-1)=='"' && len > 2)
142 QStringList qrl=QStringList::split(regg,name,FALSE);
143 if (VhdlDocGen::isNumber(qrl[0].utf8()))
145 g_code->codify("\"");
146 startFontClass("vhdllogic");
147 QCString mid=name.mid(1,len-2); //" 1223 "
148 g_code->codify(mid.data());
150 g_code->codify("\"");
154 startFontClass("keyword");
155 g_code->codify(name.data());
161 if (VhdlDocGen::isNumber(name))
163 startFontClass("vhdllogic");
164 g_code->codify(name.data());
171 static void addToSearchIndex(const char *text)
173 if (Doxygen::searchIndex)
175 Doxygen::searchIndex->addWord(text,FALSE);
180 /*! start a new line of code, inserting a line number if g_sourceFileDef
181 * is TRUE. If a definition starts at the current line, then the line
182 * number is linked to the documentation of that definition.
184 static void startCodeLine()
186 //if (g_currentFontClass) { g_code->endFontClass(); }
190 //QCString lineNumber,lineAnchor;
191 //lineNumber.sprintf("%05d",g_yyLineNr);
192 //lineAnchor.sprintf("l%05d",g_yyLineNr);
193 // if ((g_yyLineNr % 500) == 0)
194 // fprintf(stderr,"\n starting Line %d:",g_yyLineNr);
195 Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr);
196 //printf("startCodeLine %d d=%s\n", g_yyLineNr,d ? d->name().data() : "<null>");
197 if (!g_includeCodeFragment && d)
199 g_currentDefinition = d;
200 g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr);
201 if (!g_tempComp.isEmpty() && g_currentMemberDef )
203 //ClassDef *cf=VhdlDocGen::getClass(g_tempComp.data());
204 QCString nn=g_currentMemberDef->name();
205 MemberDef* mdeff=VhdlDocGen::findMember(g_tempComp,nn);
208 g_currentMemberDef=mdeff;
212 g_parmType.resize(0);
213 g_parmName.resize(0);
215 lineAnchor.sprintf("l%05d",g_yyLineNr);
216 if (g_currentMemberDef)
218 g_code->writeLineNumber(g_currentMemberDef->getReference(),
219 g_currentMemberDef->getOutputFileBase(),
220 g_currentMemberDef->anchor(),g_yyLineNr);
221 setCurrentDoc(lineAnchor);
223 else if (d->isLinkableInProject())
225 g_code->writeLineNumber(d->getReference(),
226 d->getOutputFileBase(),
228 setCurrentDoc(lineAnchor);
233 g_code->writeLineNumber(0,0,0,g_yyLineNr);
236 g_code->startCodeLine(g_sourceFileDef);
237 if (g_currentFontClass)
239 g_code->startFontClass(g_currentFontClass);
243 static void endFontClass();
244 static void endCodeLine()
247 g_code->endCodeLine();
250 static void nextCodeLine()
254 endCodeLine(); // </div>
256 const char *fc = g_currentFontClass;
257 if (g_yyLineNr<g_inputLines)
259 g_currentFontClass = fc;
260 startCodeLine(); //<div>
264 /*! writes a word to the output.
265 * If curr_class is defined, the word belongs to a class
266 * and will be linked.
269 static void writeWord(const char *word,const char* curr_class=0,bool classLink=FALSE)
273 QCString tclass(curr_class);
275 if (ttt.isEmpty()) return;
276 for (unsigned int j=0;j<ttt.length();j++)
279 if (c==' '|| c==',' || c==';' || c==':' || c=='(' || c==')' || c=='\r' || c=='\t' || c=='.')
283 if (!writeColoredWord(temp)) // is it a keyword ?
285 //if (VhdlDocGen::findKeyWord(temp))
286 // writeFont("vhdlkeyword",temp.data());
287 //printf("writeWord: %s\n",temp.data());
288 if (!tclass.isEmpty())
292 generateMemLink(*g_code,tclass,temp);
296 generateClassOrGlobalLink(*g_code,temp);
301 if (!checkVhdlString(temp))
302 g_code->codify(temp.data());
323 if (!writeColoredWord(temp))
325 if (!tclass.isEmpty())
329 generateMemLink(*g_code,tclass,temp); // generateMemLink(*g_code,g_CurrClass,left);
333 generateClassOrGlobalLink(*g_code,temp);
338 QCString qc(temp.data());
339 if (VhdlDocGen::isNumber(qc)){
340 startFontClass("vhdllogic");
341 g_code->codify(temp.data());
345 g_code->codify(temp.data());
352 /*! write a code fragment `text' that may span multiple lines, inserting
353 * line numbers for each line.
355 static void codifyLines(const char *text,const char *cl=0,bool classlink=FALSE,bool comment=FALSE)
358 //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text);
359 const char *p=text,*sp=p;
365 while ((c=*p++) && c!='\n') {}
370 line = line.left((int)(p-sp)-1);
372 //g_code->codify(sp);
375 writeFont("keyword",line.data());
379 writeWord(line,cl,classlink);
386 writeFont("keyword",sp);
388 writeWord(sp,cl,classlink);
394 /*! writes a link to a fragment \a text that may span multiple lines, inserting
395 * line numbers for each line. If \a text contains newlines, the link will be
396 * split into multiple links with the same destination, one for each line.
398 static void writeMultiLineCodeLink(CodeOutputInterface &ol,
402 static bool sourceTooltips = Config_getBool("SOURCE_TOOLTIPS");
403 TooltipManager::instance()->addTooltip(d);
404 QCString ref = d->getReference();
405 QCString file = d->getOutputFileBase();
406 QCString anchor = d->anchor();
408 if (!sourceTooltips) // fall back to simple "title" tooltips
410 tooltip = d->briefDescriptionAsTooltip();
413 char *p=(char *)text;
418 while ((c=*p++) && c!='\n') {}
423 // printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
424 ol.writeCodeLink(ref,file,anchor,sp,tooltip);
429 ol.writeCodeLink(ref,file,anchor,sp,tooltip);
435 static void setParameterList(MemberDef *md)
437 g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : "";
438 ArgumentList *al = md->argumentList();
440 ArgumentListIterator ali(*al);
442 for (ali.toFirst();(a=ali.current());++ali)
444 g_parmName = a->name.copy();
445 g_parmType = a->type.copy();
446 int i = g_parmType.find('*');
447 if (i!=-1) g_parmType = g_parmType.left(i);
448 i = g_parmType.find('&');
449 if (i!=-1) g_parmType = g_parmType.left(i);
450 g_parmType.stripPrefix("const ");
451 g_parmType=g_parmType.stripWhiteSpace();
452 // g_theVarContext.addVariable(g_parmType,g_parmName);
457 /*! writes a link to a function or procedure
460 static void generateFuncLink(CodeOutputInterface &ol,MemberDef* mdef)
463 //printf("generateFuncLink(FuncName=%s)\n",mdef->name().data());
464 QCString memberName=mdef->name();
466 if (mdef && mdef->isLinkable()) // is it a linkable class
468 writeMultiLineCodeLink(ol,mdef,mdef->name());
469 addToSearchIndex(memberName);
472 codifyLines(memberName.data());
473 addToSearchIndex(memberName);
474 } // generateFuncLink
477 static void generateMemLink(CodeOutputInterface &ol,QCString &clName,QCString& memberName)
479 if (memberName.isEmpty()) return;
480 if (clName.isEmpty())
482 codifyLines(memberName.data());
487 QCString className=clName;
491 //bool isLocal=FALSE;
493 md=VhdlDocGen::findMember(className,memberName);
494 ClassDef *po=VhdlDocGen::getClass(className.data());
496 if (md==0 && po && (VhdlDocGen::VhdlClasses)po->protection()==VhdlDocGen::PACKBODYCLASS)
498 QCString temp=className;//.stripPrefix("_");
499 temp.stripPrefix("_");
500 md=VhdlDocGen::findMember(temp,memberName);
503 if (md && md->isLinkable()) // is it a linkable class
505 writeMultiLineCodeLink(ol,md,memberName);
506 addToSearchIndex(memberName);
509 // nothing found, just write out the word
510 codifyLines(memberName.data());
511 addToSearchIndex(memberName);
515 static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName, bool /*typeOnly*/)
517 QCString className=clName;
519 if (className.isEmpty()) return;
523 //bool isLocal=FALSE;
524 className.stripPrefix("_");
525 cd = getClass(className.data());
528 //className.stripPrefix("_");
529 QCString temp(clName);
530 temp.stripPrefix("_");
531 if (cd && cd->isLinkable()) // is it a linkable class
533 //if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ARCHITECTURECLASS)
535 // temp=VhdlDocGen::getClassName(cd);
537 writeMultiLineCodeLink(ol,cd,temp);
538 addToSearchIndex(className);
541 Definition *d = cd->getOuterScope();
542 if (d && d->definitionType()==Definition::TypeClass)
552 // nothing found, just write out the word
554 addToSearchIndex(clName);
555 }// generateClasss or global link
558 /*! counts the number of lines in the input */
559 static int countLines()
561 const char *p=g_inputString;
567 if (c=='\n') count++;
569 if (p>g_inputString && *(p-1)!='\n')
570 { // last line does not end with a \n, so we add an extra
571 // line and explicitly terminate the line after parsing.
573 g_needsTermination=TRUE;
578 static void endFontClass()
580 if (g_currentFontClass)
582 g_code->endFontClass();
583 g_currentFontClass=0;
587 static void startFontClass(const char *s)
591 g_code->startFontClass(s);
592 g_currentFontClass=s;
595 static void writeFont(const char *s,const char* text)
597 if (s==0 || text==0) return;
598 //printf("writeFont(%d,\"%s\")\n",g_yyLineNr,text);
599 g_code->startFontClass(s);
600 g_code->codify(text);
601 g_code->endFontClass();
604 //----------------------------------------------------------------------------
606 static void appStringLower(QCString& qcs,const char* text)
611 qcs=qcs.stripWhiteSpace();
614 //static void appString(QCString& qcs,const char* text)
620 static QCString g_temp;
622 /* writes and links a port map statement */
623 static void codifyMapLines(char *text)
630 //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text);
631 char *p=text; //,*sp=p;
637 while ((c=*p++) && c!='\n' && c!=':' && c != ' ' && c != '(' && c!='\0' && c!='\t')
643 if (!g_temp.isEmpty()) wordCounter++;
645 if (!g_temp.isEmpty())
647 // different kinds of component instantiations
648 // xxx:yyy (generic/port) map(
649 // xxx:(entity/component/configuration) yyy (generic/port) map(
650 // xxx: entity yyy(zzz) (generic/port) map(
651 if (wordCounter==2 || wordCounter==3)
653 QCString q=g_temp.lower(); // consider (upper/lower) cases
654 if (q=="entity" || q=="component" || q=="configuration" || q=="port" || q=="generic")
656 generateMemLink(*g_code,g_CurrClass,g_temp);
660 g_PortMapComp=g_temp;
661 generateClassOrGlobalLink(*g_code,g_temp);
666 generateMemLink(*g_code,g_CurrClass,g_temp);
670 codifyLines(ctemp.data());
677 * writes a function|procedure prototype and links the function|procedure name
680 static void writeFuncProto()
684 VhdlDocGen::parseFuncProto(g_FuncProto,ql,name,ret,FALSE);
688 codifyLines(g_FuncProto.data(),g_CurrClass.data());
691 QStringList qlist=QStringList::split(name,g_FuncProto,FALSE);
692 QCString temp=qlist[0].utf8();
693 codifyLines(temp.data(),g_CurrClass.data());
694 g_FuncProto.stripPrefix(temp.data());
699 temp.stripPrefix("_");// _{package body name}
701 MemberDef *mdef=VhdlDocGen::findFunction(ql,name,temp,FALSE);
705 generateFuncLink(*g_code,mdef);
706 g_FuncProto.stripPrefix(name.data());
707 codifyLines(g_FuncProto.data(),g_CurrClass.data());
711 codifyLines(g_FuncProto.data(),g_CurrClass.data());
715 /* writes a process prototype to the ouput */
717 static void writeProcessProto(){
718 codifyLines(g_FuncProto.data(),g_CurrClass.data());
719 g_vhdlKeyDict.clear();
720 }// writeProcessProto
722 /* writes a keyword */
724 static bool writeColoredWord(QCString& word )
726 QCString qcs=word.lower();
727 QCString *ss=VhdlDocGen::findKeyWord(qcs);
730 writeFont(ss->data(),word.data());
737 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
739 static int yyread(char *buf,int max_size)
742 while( c < max_size && g_inputString[g_inputPosition] )
744 *buf = g_inputString[g_inputPosition++] ;
756 NAME [a-z_A-Z][ a-z_A-Z0-9]*
757 FUNCNAME [a-z_A-Z"][a-z_A-Z0-9+*"/=<>-]*
758 ID "$"?[a-z_A-Z][a-z_A-Z0-9]*
759 SPECSIGN [:;, +*&\/=<>'\t]*
760 DIGITSS [0-9]+|[0-9]+("#")*[0-9_a-fA-F\+\.\-]+("#")*
761 ALLTYPESMAP {B}*[_a-zA-Z0-9. ]+{BN}*
762 ALLTYPESMAP1 {BN}*[_a-zA-Z0-9.() ]+{BN}*
764 ARCHITECTURE ^{B}*("architecture"){BN}+{FUNCNAME}{BN}+("of"){BN}+{FUNCNAME}
765 PROCESS ({BN}*{FUNCNAME}{BN}*[:]+{BN}*("process"){BN}*[(]*)|[^a-zA-Z]("process "|"process("){BN}*[ (]*|[^a-zA-Z]("process"){BN}+
767 END1 {B}*("end "){BN}+("if"|"case"|"loop"|"generate"|"for")
768 END2 [^a-zA-Z_]("end"){BN}*[;]
769 END3 {BN}*[^a-zA-Z]("end"){BN}+{FUNCNAME}{BN}*[;]
770 END4 {B}*("end"){BN}+"function"{BN}+{FUNCNAME}{BN}*[;]
771 ENDEFUNC {END3}|{END4}|{END2}
773 KEYWORD ("new"|"event"|"break"|"case"|"end"|"loop"|"else"|"for"|"goto"|"if"|"return"|"generate"|"is"|"while"|"in")
774 TYPEKW ^{B}*("type"|"subtype"|"constant"|"attribute"|"signal"|"variable","alias","configuration")
775 FUNC ^{B}*("function"|"procedure"){BN}*{FUNCNAME}{BN}*("(")
777 ARITHOP "+"|"-"|"/"|"*"|"%"|"/="|":="
778 ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|="
779 LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!"
780 BITOP "&"|"|"|"^"|"<<"|">>"|"~"
781 OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
783 PORT {B}*("port"){BN}*("(")
784 GENERIC {B}*("generic"){BN}*("(")
791 MAPCOMPONENT1 ({ALLTYPESMAP}[:]{ALLTYPESMAP}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1})
792 MAPCOMPONENT2 {BN}*("port"|"generic"){BN}+("map"){BN}*("("){1}
793 MAPCOMPONENT3 ({ALLTYPESMAP}[:]{BN}*{ALLTYPESMAP1}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1})
794 MAPCOMPONENT4 ({ALLTYPESMAP}[:]{BN}*("entity"|"component"|"configuration"){BN}+{ALLTYPESMAP1}{TEXTT}*{BN}*("port"|"generic"){BN}*("map"){BN}*("("){1})
796 XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFIG"|"CONFIG_MODE"|"COOL_CLK"|"DATA_GATE"|"DCI_VALUE"|"DISABLE"|"DRIVE"|"DROP_SPEC"|"ENABLE"|"FAST"|"FEEDBACK"|"FILE"|"FLOAT"|"FROM-THRU-TO"|"FROM-TO"|"HBLKNM"|"HU_SET"|"INREG"|"IOB"|"IOBDELAY"|"IOSTANDARD"|"KEEP"|"KEEPER"|"LOC"|"LOCATE"|"LOCK_PINS"|"MAP"|"MAXDELAY"|"MAXPT"|"MAXSKEW"|"NODELAY"|"NOREDUCE"|"OFFSET"|"OPEN_DRAIN"|"OPT_EFFORT"|"OPTIMIZE"|"PERIOD"|"PIN"|"PRIORITY"|"PROHIBIT"|"PULLDOWN"|"PULLUP"|"PWR_MODE"|"REG"|"RLOC"|"RLOC_ORIGIN"|"RLOC_RANGE"|"SAVE NET"|"FLAG"|"SYSTEM_JITTER"|"TEMPERATURE"|"TIMEGRP"|"TIMESPEC"|"VOLTAGE"
822 writeFont("vhdlchar",vhdlcodeYYtext);
826 <Map>[^()\n,--]* { /* write and link a port map lines */
827 QCString tt(vhdlcodeYYtext);
828 VhdlDocGen::deleteAllChars(tt,',');
830 QStringList ql=QStringList::split(r,tt,FALSE);
833 unsigned int index=0;
834 QCString t1=ql[0].utf8();
835 char cc=t1.at(index);
836 while (cc==' ' || cc=='\t')
843 if (index>=t1.size()) break;
848 s1=s1.stripWhiteSpace();
850 // if (!g_PortMapComp.isEmpty())
851 generateMemLink(*g_code,g_PortMapComp,s1);
852 while (index++<t1.size())
854 char cc=t1.at(index);
855 if (cc==' ' || cc=='\t')
865 QCString s2=ql[1].utf8();
868 while (cc==' ' || cc=='\t')
875 if (index>=t1.size()) break;
878 s2=s2.stripWhiteSpace();
879 if (!checkVhdlString(s2))
880 generateMemLink(*g_code,g_CurrClass,s2);
881 while (index++<t1.size())
883 if (t1.at(index)==' ')
891 codifyLines(vhdlcodeYYtext,g_CurrClass.data());
897 codifyLines(vhdlcodeYYtext);
903 writeFont("vhdlchar",vhdlcodeYYtext);
910 <ParseFuncProto>{NAME} {
911 QCString tmp(vhdlcodeYYtext);
912 tmp=tmp.stripWhiteSpace();
913 appStringLower(g_PrevString,vhdlcodeYYtext);
914 g_vhdlKeyDict.insert(g_PrevString,new QCString(g_PrevString.data()));
915 if (!writeColoredWord(tmp))
917 generateMemLink(*g_code,g_CurrClass,tmp);
922 <ParseType>{STRING} {
923 QCString qcs(vhdlcodeYYtext);
924 VhdlDocGen::deleteAllChars(qcs,'"');
925 VhdlDocGen::deleteAllChars(qcs,' ');
926 if (VhdlDocGen::isNumber(qcs))
927 writeFont("vhdllogic",vhdlcodeYYtext);
929 writeFont("keyword",vhdlcodeYYtext);
933 g_FuncProto.append(vhdlcodeYYtext);
936 codifyLines(vhdlcodeYYtext);
943 g_FuncProto.append(vhdlcodeYYtext);
946 writeFont("keyword",vhdlcodeYYtext);
951 <ParseType>{ENDEFUNC} {
952 QRegExp regg("[\\s]");
953 QCString tt(vhdlcodeYYtext);
954 codifyLines(vhdlcodeYYtext,g_CurrClass.data());
956 VhdlDocGen::deleteAllChars(tt,';');
957 tt.stripWhiteSpace();
958 QStringList ql=QStringList::split(regg,tt,FALSE);
959 int index=ql.findIndex(QCString("if"))+1;
960 index+=ql.findIndex(QCString("case"))+1;
961 index+=ql.findIndex(QCString("loop"))+1;
962 index+=ql.findIndex(QCString("generate"))+1;
974 codifyLines(vhdlcodeYYtext,g_CurrClass.data());
975 g_vhdlKeyDict.clear();
978 <ParseType>^{B}*("begin "|"begin") {
979 codifyLines(vhdlcodeYYtext,g_CurrClass.data());
983 <ParseType>{SPECSIGN} {
984 g_FuncProto.append(vhdlcodeYYtext);
987 codifyLines(vhdlcodeYYtext,g_CurrClass.data());
991 <ParseType>["_a-zA-Z0-9]* {
992 QCString val(vhdlcodeYYtext);
993 g_FuncProto.append(vhdlcodeYYtext);
994 appStringLower(g_PrevString,vhdlcodeYYtext);
996 if (isFuncProto && g_braceCount==0)
998 g_vhdlKeyDict.insert(g_PrevString,new QCString(g_PrevString.data()));
1003 if (!writeColoredWord(val))
1005 if (!isFuncProto && !g_vhdlKeyDict.find(g_PrevString))
1007 val=val.stripWhiteSpace();
1008 if (VhdlDocGen::isNumber(val))
1010 startFontClass("vhdllogic");
1011 codifyLines(vhdlcodeYYtext,g_CurrClass.data());
1015 generateMemLink(*g_code,g_CurrClass,val);
1019 codifyLines(vhdlcodeYYtext,g_CurrClass.data());
1026 <ParseType>{BRACEOPEN} {
1031 writeFont("vhdlchar",vhdlcodeYYtext);
1036 <ParseType>{BRACECLOSE} {
1041 writeFont("vhdlchar",vhdlcodeYYtext);
1043 if (g_braceCount==0 && !isProto)// && !isPackageBody)
1046 appStringLower(g_PrevString,vhdlcodeYYtext);
1057 <ClassesName>{FUNCNAME} {
1058 QDict<QCString> mem;
1059 appStringLower(g_PrevString,vhdlcodeYYtext);
1060 g_CurrClass.resize(0);
1061 g_CurrClass.append(vhdlcodeYYtext);
1062 g_CurrClass=g_CurrClass.stripWhiteSpace();
1064 if (!writeColoredWord(g_CurrScope))
1066 generateClassOrGlobalLink(*g_code,vhdlcodeYYtext);
1070 codifyLines(vhdlcodeYYtext,g_CurrClass.data());
1076 <ParseComponent>{BRACEOPEN} {
1078 g_code->codify(vhdlcodeYYtext);
1082 <ParseComponent>{BRACECLOSE} {
1084 g_code->codify(vhdlcodeYYtext);
1085 if (g_braceCount==0 && !isComponent)
1087 g_tempComp.resize(0);
1092 BEGIN(ParseComponent);
1096 <ParseComponent>{B}*"-" {
1097 if (strlen(vhdlcodeYYtext)>=2) // found text ?
1099 writeFont("keyword",vhdlcodeYYtext);
1103 writeFont("vhdlchar",vhdlcodeYYtext);
1107 <ParseComponent>{SPECSIGN} {
1108 codifyLines(vhdlcodeYYtext);
1113 <ParseComponent>"\n"|" " {
1114 codifyLines(vhdlcodeYYtext);
1117 <ParseComponent>{DIGITSS} {
1118 startFontClass("vhdllogic");
1119 codifyLines(vhdlcodeYYtext);
1123 <ParseComponent>{PORT} {
1124 codifyLines(vhdlcodeYYtext);
1129 <ParseComponent>{GENERIC} {
1130 codifyLines(vhdlcodeYYtext);
1134 <ParseComponent>[_a-zA_Z][_a-zA-Z0-9]* {
1135 QCString temp(vhdlcodeYYtext);
1136 appStringLower(g_PrevString,vhdlcodeYYtext);
1137 if (!checkVhdlString(temp)){
1138 if (!writeColoredWord(g_PrevString))
1140 generateMemLink(*g_code,g_tempComp,temp);
1145 <ParseComponent>{STRING} {
1146 QCString temp(vhdlcodeYYtext);
1147 if (!checkVhdlString(temp))
1148 codifyLines(vhdlcodeYYtext);
1152 <ParseProcessProto>[^()]* {
1153 g_FuncProto.append(vhdlcodeYYtext);
1158 <ParseProcessProto>{BRACEOPEN} {
1159 g_FuncProto.append(vhdlcodeYYtext);
1163 <ParseProcessProto>{BRACECLOSE} {
1164 g_FuncProto.append(vhdlcodeYYtext);
1166 if (g_braceCount==0)
1168 writeProcessProto();
1173 <ParsePackage>[^:;]* { //found package
1174 QCString temp(vhdlcodeYYtext);
1175 QStringList strl=QStringList::split(".",temp,FALSE);
1179 QCString s1=strl[0].utf8();
1180 QCString s2=strl[1].utf8();
1181 QCString s3=strl[2].utf8();
1184 codifyLines(s1.data(),g_CurrClass.data());
1185 ClassDef *cd=VhdlDocGen::getPackageName(s2);
1188 generateClassOrGlobalLink(*g_code,s2.data());
1192 codifyLines(s2.data());
1194 codifyLines(s3.data());
1198 writeFont("keywordflow",vhdlcodeYYtext);
1203 <Bases>{MAPCOMPONENT1}|{MAPCOMPONENT2}|{MAPCOMPONENT3}|{MAPCOMPONENT4} { // found port or generic map
1204 QCString tt(vhdlcodeYYtext);
1206 if (tt.contains(':',FALSE))
1219 QCString left=tt.left(j+1);
1220 codifyLines(left.data());
1221 tt=tt.right(tt.length()-j-1);
1222 left=VhdlDocGen::getIndexWord(tt.data(),0);
1223 if (!left.isEmpty())
1225 if (left.contains('('))
1227 j=left.find('(',FALSE);
1228 QCString name=left.left(j);
1229 generateClassOrGlobalLink(*g_code,name.data());
1231 name=tt.right(tt.length()-name.length());
1232 codifyLines(name.data());
1236 generateClassOrGlobalLink(*g_code,left.data());
1237 tt.stripPrefix(left.data()); //=tt.right(tt.length()-left.length()-1);
1240 codifyLines(tt.data());
1246 if (tt.contains(':',FALSE))
1247 codifyMapLines(tt.data());
1249 codifyLines(tt.data());
1255 <Bases>^{B}*("component"){BN}+{FUNCNAME} { // found component
1256 appStringLower(g_PrevString,vhdlcodeYYtext);
1257 // writeFont("keywordflow",VhdlDocGen::getIndexWord(vhdlcodeYYtext,0).data());
1258 // writeFont("vhdlkeyword"," ");
1259 QCString temp=VhdlDocGen::getIndexWord(vhdlcodeYYtext,1);
1260 temp=temp.stripWhiteSpace();
1261 VhdlDocGen::deleteAllChars(temp,'\n');
1263 codifyLines(vhdlcodeYYtext,temp.data(),TRUE);
1266 //if (getClass(temp.data()))
1267 // generateClassOrGlobalLink(*g_code,temp.data());
1269 // generateMemLink(*g_code,g_CurrClass,temp);
1272 BEGIN(ParseComponent);
1277 <Bases>{ARCHITECTURE} { // found architecture
1278 g_PortMapComp.resize(0);
1279 // writeFont("vhdlkeyword",VhdlDocGen::getIndexWord(vhdlcodeYYtext,0).data());
1280 // writeFont("vhdlkeyword"," ");
1281 // writeFont("vhdlchar",VhdlDocGen::getIndexWord(vhdlcodeYYtext,1).data());
1282 // writeFont("vhdlkeyword"," ");
1283 // writeFont("vhdlkeyword",VhdlDocGen::getIndexWord(vhdlcodeYYtext,2).data());
1284 // writeFont("vhdlkeyword"," ");
1285 //QCString temp=VhdlDocGen::getIndexWord(vhdlcodeYYtext,1);
1286 //temp=temp.stripWhiteSpace();
1288 //temp+=VhdlDocGen::getIndexWord(vhdlcodeYYtext,3);
1289 QCString temp = VhdlDocGen::getIndexWord(vhdlcodeYYtext,3);
1291 temp+=VhdlDocGen::getIndexWord(vhdlcodeYYtext,1);
1293 VhdlDocGen::deleteAllChars(temp,'\n');
1294 codifyLines(vhdlcodeYYtext,temp.data(),TRUE);
1295 //generateClassOrGlobalLink(*g_code,temp.data());
1296 isPackageBody=FALSE;
1301 <Bases>^{B}*("package "){BN}*("body"){BN}*{FUNCNAME} { // found package body
1302 QCString ss(vhdlcodeYYtext);
1303 QCString temp=VhdlDocGen::getIndexWord(vhdlcodeYYtext,2);
1304 QStringList ql=QStringList::split(temp,ss,FALSE);
1305 QCString ll=ql[0].utf8();
1306 codifyLines(ll.data(),g_CurrClass.data());
1307 temp=temp.stripWhiteSpace();
1309 generateClassOrGlobalLink(*g_code,temp.data());
1310 g_CurrClass.resize(0);
1314 // BEGIN(ClassesName);
1317 <Bases>{PROCESS} { // found process
1319 g_FuncProto.resize(0);
1320 g_FuncProto.append(vhdlcodeYYtext);
1321 g_vhdlKeyDict.clear();
1322 appStringLower(g_PrevString,vhdlcodeYYtext);
1323 if (g_PrevString.contains('('))
1326 BEGIN(ParseProcessProto);
1330 writeProcessProto();
1334 <Bases>("end"){BN}+("process") { // end of process
1336 codifyLines(vhdlcodeYYtext);
1341 <Bases>^{B}*("begin "|"begin") {
1343 writeFont("vhdlkeyword",vhdlcodeYYtext);
1346 <Bases>^{B}*("use"|"library"){BN}+ { //found package or library
1347 writeFont("vhdlkeyword",vhdlcodeYYtext);
1348 BEGIN(ParsePackage);
1352 <Bases>^{B}*("use"){BN}+("configuration")[^\n]* {
1353 codifyLines(vhdlcodeYYtext);
1358 <Bases>{FUNC} { // found function|procedure
1359 g_vhdlKeyDict.clear();
1360 g_FuncProto.resize(0);
1362 g_FuncProto.append(vhdlcodeYYtext);
1369 <Bases>^{B}*("entity"|"package"){BN}+ {
1370 appStringLower(g_PrevString,vhdlcodeYYtext);
1371 writeFont("keywordflow",vhdlcodeYYtext);
1372 isPackageBody=FALSE;
1377 <Bases>{KEYWORD} { // found keyword
1378 QCString qcs(vhdlcodeYYtext);
1379 if (!writeColoredWord(qcs))
1381 startFontClass("vhdlchar");
1382 g_code->codify(vhdlcodeYYtext);
1389 appStringLower(g_PrevString,vhdlcodeYYtext);
1390 QCString temp(vhdlcodeYYtext);
1391 temp=temp.stripWhiteSpace();
1393 if (!writeColoredWord(temp))
1395 startFontClass("vhdlchar");
1396 generateMemLink(*g_code,g_CurrClass,temp);
1401 <Bases,ParseComponent>{DIGITSS} {
1402 startFontClass("vhdllogic");
1403 codifyLines(vhdlcodeYYtext);
1407 <Bases>^{B}*("use"){BN}+("entity"|"component")[^\n]* {
1408 codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE);
1413 codifyLines(vhdlcodeYYtext);
1416 BEGIN(ParseFuncProto);
1425 startFontClass("vhdlchar");
1426 g_code->codify(vhdlcodeYYtext);
1430 <Bases>","|"."|":"|"'"|"("|")" {
1431 startFontClass("vhdlchar");
1432 g_code->codify(vhdlcodeYYtext);
1437 QCString qcs(vhdlcodeYYtext);
1438 VhdlDocGen::deleteAllChars(qcs,'"');
1439 VhdlDocGen::deleteAllChars(qcs,' ');
1441 if (VhdlDocGen::isNumber(qcs))
1442 writeFont("vhdllogic",vhdlcodeYYtext);
1444 writeFont("keyword",vhdlcodeYYtext);
1447 <Bases>{B}*"#"[^\n]* {
1448 writeFont("keyword",vhdlcodeYYtext);
1451 <Bases>^{B}*{XILINX}[^\n]* {
1453 //codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE);
1456 <Bases>^{B}*"set_"[^\n]* {
1461 codifyLines(vhdlcodeYYtext);
1466 g_code->codify(vhdlcodeYYtext);
1469 <*>\n{TEXTT} { // found normal or special comment on its own line
1470 QCString text(vhdlcodeYYtext);
1471 int i=text.find("--");
1472 if (text.mid(i,3)=="--!" && // hide special comment
1473 Config_getBool("STRIP_CODE_COMMENTS"))
1475 g_yyLineNr++; // skip complete line
1477 else // normal comment
1479 // startFontClass("keyword");
1480 codifyLines(text,0,FALSE,TRUE);
1484 <*>{TEXTT} { // found normal or special comment after something
1485 QCString text(vhdlcodeYYtext);
1486 int i=text.find("--");
1487 if (text.mid(i,3)=="--!" &&
1488 Config_getBool("STRIP_CODE_COMMENTS"))
1490 // hide special comment
1492 else // normal comment
1494 // startFontClass("keyword");
1495 codifyLines(text,0,FALSE,TRUE);
1503 /*@ ----------------------------------------------------------------------------
1506 void resetVhdlCodeParserState()
1508 g_vhdlKeyDict.setAutoDelete(TRUE);
1509 g_vhdlKeyDict.clear();
1512 void parseVhdlCode(CodeOutputInterface &od,const char *className,const QCString &s,
1513 bool /*exBlock*/, const char *exName,FileDef *fd,
1514 int startLine,int endLine,bool inlineFragment,
1515 MemberDef *memberDef,bool,Definition *searchCtx,
1516 bool /* collectXRefs */)
1518 //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd);
1519 if (s.isEmpty()) return;
1520 printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL);
1521 TooltipManager::instance()->clearTooltips();
1524 ClassDef *dd=memberDef->getClassDef();
1525 if (dd) g_CurrClass=dd->name();
1528 resetVhdlCodeParserState();
1531 g_inputPosition = 0;
1532 g_currentFontClass = 0;
1533 g_needsTermination = FALSE;
1534 g_searchCtx = searchCtx;
1537 g_inputLines = endLine+1;
1539 g_inputLines = countLines();
1542 g_yyLineNr = startLine;
1547 // g_theCallContext.clear();
1548 g_classScope = className;
1549 g_exampleName = exName;
1550 g_sourceFileDef = fd;
1551 bool cleanupSourceDef = FALSE;
1554 // create a dummy filedef for the example
1555 g_sourceFileDef = new FileDef("",exName);
1556 cleanupSourceDef = TRUE;
1558 if (g_sourceFileDef)
1560 setCurrentDoc("l00001");
1562 g_currentDefinition = 0;
1563 g_currentMemberDef = 0;
1565 if (!g_exampleName.isEmpty())
1567 g_exampleFile = convertNameToFile(g_exampleName+"-example");
1569 g_includeCodeFragment = inlineFragment;
1574 // g_type.resize(0);
1575 // g_name.resize(0);
1576 // g_args.resize(0);
1577 g_parmName.resize(0);
1578 g_parmType.resize(0);
1583 setParameterList(memberDef);
1585 /*int iLine=*/countLines();
1586 vhdlcodeYYrestart( vhdlcodeYYin );
1590 if (g_needsTermination)
1596 TooltipManager::instance()->writeTooltips(*g_code);
1598 if (cleanupSourceDef)
1600 // delete the temporary file definition used for this example
1601 delete g_sourceFileDef;
1605 printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL);
1608 void codeFreeVhdlScanner()
1610 #if defined(YY_FLEX_SUBMINOR_VERSION)
1613 vhdlcodeYYlex_destroy();
1618 #if !defined(YY_FLEX_SUBMINOR_VERSION)
1619 extern "C" { // some bogus code to keep the compiler happy
1620 void vhdlcodeYYdummy() { yy_flex_realloc(0,0); }
1622 #elif YY_FLEX_SUBMINOR_VERSION<33
1623 #error "You seem to be using a version of flex newer than 2.5.4 but older than 2.5.33. These versions do NOT work with doxygen! Please use version <=2.5.4 or >=2.5.33 or expect things to be parsed wrongly!"