/****************************************************************************** * * Copyright (C) 1997-2012 by Dimitri van Heesch. * * 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. * * Documents produced by Doxygen are derivative works derived from the * input used in their production; they are not affected by this license. * */ /****************************************************************************** * Parser for syntax hightlighting and references for vhdl subset * written by M. Kreis * supports VHDL-87 * does not support VHDL-AMS ******************************************************************************/ %{ /* * includes */ #include #include #include #include #include #include #include "qtbc.h" #include "entry.h" #include "doxygen.h" #include "message.h" #include "outputlist.h" #include "util.h" #include "membername.h" #include "searchindex.h" #include "vhdldocgen.h" #include "arguments.h" #define YY_NEVER_INTERACTIVE 1 #define YY_NO_INPUT 1 // Toggle for some debugging info //#define DBG_CTX(x) fprintf x #define DBG_CTX(x) do { } while(0) /* ----------------------------------------------------------------- * statics */ // ----------------- ---------------------------------- //static bool isPackBody=FALSE; //static bool isStartMap; static bool isFuncProto=FALSE; static bool isComponent=FALSE; static bool isPackageBody=FALSE; static bool isProto = FALSE; static QCString g_PrevString; static QCString g_CurrClass; static QDictg_vhdlKeyDict; static QCString g_tempClass; static QCString g_tempComp; static QCString g_PortMapComp; static MemberDef *g_vhdlMember; static QCString g_FuncProto; //----------------------------------------------------------- static CodeOutputInterface * g_code; static QCString g_curClassName; static QCString g_parmType; static QCString g_parmName; static const char * g_inputString; //!< the code fragment as text static int g_inputPosition; //!< read offset during parsing static int g_inputLines; //!< number of line in the code fragment static int g_yyLineNr; //!< current line number static bool g_needsTermination; static Definition *g_searchCtx; static QCString g_exampleName; static QCString g_exampleFile; static QCString g_type; static QCString g_name; static QCString g_args; static QCString g_classScope; static QCString g_CurrScope; static FileDef * g_sourceFileDef; static Definition * g_currentDefinition; static MemberDef * g_currentMemberDef; static bool g_includeCodeFragment; static const char * g_currentFontClass; static bool g_lexInit = FALSE; static int g_braceCount=0; static void writeFont(const char *s,const char* text); static void generateMemLink(CodeOutputInterface &ol,QCString &clName,QCString& memberName); static bool writeColoredWord(QCString& word ); static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName, bool typeOnly=FALSE); static void endFontClass(); static void startFontClass(const char *s); //------------------------------------------------------------------- static void setCurrentDoc(const QCString &anchor) { if (Doxygen::searchIndex) { if (g_searchCtx) { Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE); } else { Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE); } } } static bool checkVhdlString(QCString &name) { if (name.isEmpty()) return FALSE; static QRegExp regg("[\\s\"]"); int len=name.length(); if (name.at(0)=='"' && name.at(len-1)=='"' && len > 2) { QStringList qrl=QStringList::split(regg,name,FALSE); if (VhdlDocGen::isNumber(qrl[0].utf8())) { g_code->codify("\""); startFontClass("vhdllogic"); QCString mid=name.mid(1,len-2); //" 1223 " g_code->codify(mid.data()); endFontClass(); g_code->codify("\""); } else { startFontClass("keyword"); g_code->codify(name.data()); endFontClass(); } return TRUE; } if (VhdlDocGen::isNumber(name)) { startFontClass("vhdllogic"); g_code->codify(name.data()); endFontClass(); return TRUE; } return FALSE; } static void addToSearchIndex(const char *text) { if (Doxygen::searchIndex) { Doxygen::searchIndex->addWord(text,FALSE); } } /*! start a new line of code, inserting a line number if g_sourceFileDef * is TRUE. If a definition starts at the current line, then the line * number is linked to the documentation of that definition. */ static void startCodeLine() { //if (g_currentFontClass) { g_code->endFontClass(); } if (g_sourceFileDef) { //QCString lineNumber,lineAnchor; //lineNumber.sprintf("%05d",g_yyLineNr); //lineAnchor.sprintf("l%05d",g_yyLineNr); // if ((g_yyLineNr % 500) == 0) // fprintf(stderr,"\n starting Line %d:",g_yyLineNr); Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr); //printf("startCodeLine %d d=%s\n", g_yyLineNr,d ? d->name().data() : ""); if (!g_includeCodeFragment && d) { g_currentDefinition = d; g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr); if (!g_tempComp.isEmpty() && g_currentMemberDef ) { //ClassDef *cf=VhdlDocGen::getClass(g_tempComp.data()); QCString nn=g_currentMemberDef->name(); MemberDef* mdeff=VhdlDocGen::findMember(g_tempComp,nn); if (mdeff) { g_currentMemberDef=mdeff; } } g_parmType.resize(0); g_parmName.resize(0); QCString lineAnchor; lineAnchor.sprintf("l%05d",g_yyLineNr); if (g_currentMemberDef) { g_code->writeLineNumber(g_currentMemberDef->getReference(), g_currentMemberDef->getOutputFileBase(), g_currentMemberDef->anchor(),g_yyLineNr); setCurrentDoc(lineAnchor); } else if (d->isLinkableInProject()) { g_code->writeLineNumber(d->getReference(), d->getOutputFileBase(), 0,g_yyLineNr); setCurrentDoc(lineAnchor); } } else { g_code->writeLineNumber(0,0,0,g_yyLineNr); } } g_code->startCodeLine(g_sourceFileDef); if (g_currentFontClass) { g_code->startFontClass(g_currentFontClass); } } static void endFontClass(); static void endCodeLine() { endFontClass(); g_code->endCodeLine(); } static void nextCodeLine() { const char *fc = g_currentFontClass; endCodeLine(); if (g_yyLineNrcodify(temp.data()); } } temp.resize(0); found=FALSE; } char cc[2]; cc[0]=c; cc[1]=0; g_code->codify(cc); } else { found=TRUE; temp+=c; } } // for if (!temp.isEmpty()) { if (!writeColoredWord(temp)) { if (!tclass.isEmpty()) { if (!classLink) { generateMemLink(*g_code,tclass,temp); // generateMemLink(*g_code,g_CurrClass,left); } else { generateClassOrGlobalLink(*g_code,temp); } } else { QCString qc(temp.data()); if (VhdlDocGen::isNumber(qc)){ startFontClass("vhdllogic"); g_code->codify(temp.data()); endFontClass(); } else g_code->codify(temp.data()); } } } }// writeWord /*! write a code fragment `text' that may span multiple lines, inserting * line numbers for each line. */ static void codifyLines(const char *text,const char *cl=0,bool classlink=FALSE) { if (text==0) return; //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text); const char *p=text,*sp=p; char c; bool done=FALSE; while (!done) { sp=p; while ((c=*p++) && c!='\n') {} if (c=='\n') { g_yyLineNr++; QCString line = sp; line = line.left(p-sp-1); //*(p-1)='\0'; //g_code->codify(sp); writeWord(line,cl,classlink); nextCodeLine(); } else { //g_code->codify(sp); writeWord(sp,cl,classlink); done=TRUE; } } } /*! writes a link to a fragment \a text that may span multiple lines, inserting * line numbers for each line. If \a text contains newlines, the link will be * split into multiple links with the same destination, one for each line. */ static void writeMultiLineCodeLink(CodeOutputInterface &ol, const char *ref,const char *file, const char *anchor,const char *text, const char *tooltip) { bool done=FALSE; char *p=(char *)text; while (!done) { char *sp=p; char c; while ((c=*p++) && c!='\n') {} if (c=='\n') { g_yyLineNr++; *(p-1)='\0'; // printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp); ol.writeCodeLink(ref,file,anchor,sp,tooltip); nextCodeLine(); } else { ol.writeCodeLink(ref,file,anchor,sp,tooltip); done=TRUE; } } } static void setParameterList(MemberDef *md) { g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : ""; LockingPtr al = md->argumentList(); if (al==0) return; Argument *a = al->first(); while (a) { g_parmName = a->name.copy(); g_parmType = a->type.copy(); int i = g_parmType.find('*'); if (i!=-1) g_parmType = g_parmType.left(i); i = g_parmType.find('&'); if (i!=-1) g_parmType = g_parmType.left(i); g_parmType.stripPrefix("const "); g_parmType=g_parmType.stripWhiteSpace(); // g_theVarContext.addVariable(g_parmType,g_parmName); a = al->next(); } } /*! writes a link to a function or procedure */ static void generateFuncLink(CodeOutputInterface &ol,MemberDef* mdef) { //printf("generateFuncLink(FuncName=%s)\n",mdef->name().data()); QCString memberName=mdef->name(); if (mdef && mdef->isLinkable()) // is it a linkable class { writeMultiLineCodeLink(ol,mdef->getReference(), mdef->getOutputFileBase(), mdef->anchor(), mdef->name(), mdef->briefDescriptionAsTooltip()); addToSearchIndex(memberName); return; } ol.linkableSymbol(g_yyLineNr,memberName,0,g_currentMemberDef?g_currentMemberDef:g_currentDefinition); codifyLines(memberName.data()); addToSearchIndex(memberName); } // generateFuncLink static void generateMemLink(CodeOutputInterface &ol,QCString &clName,QCString& memberName) { if (memberName.isEmpty()) return; if (clName.isEmpty()) { codifyLines(memberName.data()); return; } QCString className=clName; MemberDef *md=0; //MemberDef *comp=0; //bool isLocal=FALSE; md=VhdlDocGen::findMember(className,memberName); ClassDef *po=VhdlDocGen::getClass(className.data()); if (md==0 && po && (VhdlDocGen::VhdlClasses)po->protection()==VhdlDocGen::PACKBODYCLASS) { QCString temp=className;//.stripPrefix("_"); temp.stripPrefix("_"); md=VhdlDocGen::findMember(temp,memberName); } if (md && md->isLinkable()) // is it a linkable class { writeMultiLineCodeLink(ol,md->getReference(), md->getOutputFileBase(), md->anchor(), memberName, md->briefDescriptionAsTooltip()); addToSearchIndex(memberName); return; } // nothing found, just write out the word ol.linkableSymbol(g_yyLineNr,memberName,0,g_currentMemberDef?g_currentMemberDef:g_currentDefinition); codifyLines(memberName.data()); addToSearchIndex(memberName); }// generateMemLink static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName, bool /*typeOnly*/) { QCString className=clName; if (className.isEmpty()) return; ClassDef *cd=0; //MemberDef *md=0; //bool isLocal=FALSE; className.stripPrefix("_"); cd = getClass(className.data()); while (cd) { //className.stripPrefix("_"); QCString temp(clName); temp.stripPrefix("_"); if (cd && cd->isLinkable()) // is it a linkable class { //if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ARCHITECTURECLASS) //{ // temp=VhdlDocGen::getClassName(cd); //} ol.linkableSymbol(g_yyLineNr,temp,cd, g_currentMemberDef ? g_currentMemberDef : g_currentDefinition); writeMultiLineCodeLink(ol,cd->getReference(), cd->getOutputFileBase(), cd->anchor(), temp, cd->briefDescriptionAsTooltip()); addToSearchIndex(className); return; } Definition *d = cd->getOuterScope(); if (d && d->definitionType()==Definition::TypeClass) { cd = (ClassDef*)d; } else { cd = 0; } } // nothing found, just write out the word ol.linkableSymbol(g_yyLineNr,clName,0,g_currentMemberDef?g_currentMemberDef:g_currentDefinition); codifyLines(clName); addToSearchIndex(clName); }// generateClasss or global link /*! counts the number of lines in the input */ static int countLines() { const char *p=g_inputString; char c; int count=1; while ((c=*p)) { p++ ; if (c=='\n') count++; } if (p>g_inputString && *(p-1)!='\n') { // last line does not end with a \n, so we add an extra // line and explicitly terminate the line after parsing. count++, g_needsTermination=TRUE; } return count; } static void endFontClass() { if (g_currentFontClass) { g_code->endFontClass(); g_currentFontClass=0; } } static void startFontClass(const char *s) { if (s==0) return; endFontClass(); g_code->startFontClass(s); g_currentFontClass=s; } static void writeFont(const char *s,const char* text) { if (s==0 || text==0) return; //printf("writeFont(%d,\"%s\")\n",g_yyLineNr,text); g_code->startFontClass(s); g_code->codify(text); g_code->endFontClass(); } //---------------------------------------------------------------------------- static void appStringLower(QCString& qcs,const char* text) { qcs.resize(0); qcs.append(text); //qcs=qcs.lower(); qcs=qcs.stripWhiteSpace(); } //static void appString(QCString& qcs,const char* text) //{ // qcs.resize(0); // qcs.append(text); //} static QCString g_temp; /* writes and links a port map statement */ static void codifyMapLines(char *text) { if (text==0) return; g_temp.resize(0); //bool dot=FALSE; int wordCounter=0; QCString ctemp; //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text); char *p=text; //,*sp=p; char c; bool done=FALSE; while (!done) { //sp=p; while ((c=*p++) && c!='\n' && c!=':' && c != ' ' && c != '(' && c!='\0' && c!='\t') { if (c!=0x9) g_temp+=c; } if (c=='\0') return; if (!g_temp.isEmpty()) wordCounter++; if (!g_temp.isEmpty()) { // different kinds of component instantiations // xxx:yyy (generic/port) map( // xxx:(entity/component/configuration) yyy (generic/port) map( // xxx: entity yyy(zzz) (generic/port) map( if (wordCounter==2 || wordCounter==3) { QCString q=g_temp.lower(); // consider (upper/lower) cases if (q=="entity" || q=="component" || q=="configuration" || q=="port" || q=="generic") { generateMemLink(*g_code,g_CurrClass,g_temp); } else { g_PortMapComp=g_temp; generateClassOrGlobalLink(*g_code,g_temp); } } else { generateMemLink(*g_code,g_CurrClass,g_temp); } } ctemp.fill(c,1); codifyLines(ctemp.data()); ctemp.resize(0); g_temp.resize(0); }//while }//codifymaplines /* * writes a function|procedure prototype and links the function|procedure name */ static void writeFuncProto() { QList ql; QCString name,ret; VhdlDocGen::parseFuncProto(g_FuncProto,ql,name,ret,FALSE); if (name.isEmpty()) { codifyLines(g_FuncProto.data(),g_CurrClass.data()); return; } QStringList qlist=QStringList::split(name,g_FuncProto,FALSE); QCString temp=qlist[0].utf8(); codifyLines(temp.data(),g_CurrClass.data()); g_FuncProto.stripPrefix(temp.data()); temp.resize(0); temp=g_CurrClass; if (isPackageBody) { temp.stripPrefix("_");// _{package body name} } MemberDef *mdef=VhdlDocGen::findFunction(ql,name,temp,FALSE); if (mdef) { generateFuncLink(*g_code,mdef); g_FuncProto.stripPrefix(name.data()); codifyLines(g_FuncProto.data(),g_CurrClass.data()); } else { codifyLines(g_FuncProto.data(),g_CurrClass.data()); } }// writeFuncProto /* writes a process prototype to the ouput */ static void writeProcessProto(){ codifyLines(g_FuncProto.data(),g_CurrClass.data()); g_vhdlKeyDict.clear(); }// writeProcessProto /* writes a keyword */ static bool writeColoredWord(QCString& word ) { QCString qcs=word.lower(); QCString *ss=VhdlDocGen::findKeyWord(qcs); if (ss) { writeFont(ss->data(),word.data()); return TRUE; } return FALSE; } #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); static int yyread(char *buf,int max_size) { int c=0; while( c < max_size && g_inputString[g_inputPosition] ) { *buf = g_inputString[g_inputPosition++] ; c++; buf++; } return c; } %} B [ \t] BN [ \t\n\r] STRING ["][^"\n]*["] NAME [a-z_A-Z][ a-z_A-Z0-9]* FUNCNAME [a-z_A-Z"][a-z_A-Z0-9+*"/=<>-]* ID "$"?[a-z_A-Z][a-z_A-Z0-9]* SPECSIGN [:;, +*&\/=<>'\t]* DIGITSS [0-9]+|[0-9]+("#")*[0-9_a-fA-F\+\.\-]+("#")* ALLTYPESMAP {B}*[_a-zA-Z0-9. ]+{BN}* ALLTYPESMAP1 {BN}*[_a-zA-Z0-9.() ]+{BN}* ARCHITECTURE ^{B}*("architecture"){BN}+{FUNCNAME}{BN}+("of"){BN}+{FUNCNAME} PROCESS ({BN}*{FUNCNAME}{BN}*[:]+{BN}*("process"){BN}*[(]*)|[^a-zA-Z]("process "|"process("){BN}*[ (]*|[^a-zA-Z]("process"){BN}+ END1 {B}*("end "){BN}+("if"|"case"|"loop"|"generate"|"for") END2 [^a-zA-Z_]("end"){BN}*[;] END3 {BN}*[^a-zA-Z]("end"){BN}+{FUNCNAME}{BN}*[;] END4 {B}*("end"){BN}+"function"{BN}+{FUNCNAME}{BN}*[;] ENDEFUNC {END3}|{END4}|{END2} KEYWORD ("new"|"event"|"break"|"case"|"end"|"loop"|"else"|"for"|"goto"|"if"|"return"|"generate"|"is"|"while"|"in") TYPEKW ^{B}*("type"|"subtype"|"constant"|"attribute"|"signal"|"variable","alias","configuration") FUNC ^{B}*("function"|"procedure"){BN}*{FUNCNAME}{BN}*("(") ARITHOP "+"|"-"|"/"|"*"|"%"|"/="|":=" ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|=" LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!" BITOP "&"|"|"|"^"|"<<"|">>"|"~" OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} PORT {B}*("port"){BN}*("(") GENERIC {B}*("generic"){BN}*("(") BRACEOPEN [(]{1} BRACECLOSE [)]{1} TEXTT {B}*"--"[^\n]* MAPCOMPONENT1 ({ALLTYPESMAP}[:]{ALLTYPESMAP}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1}) MAPCOMPONENT2 {BN}*("port"|"generic"){BN}+("map"){BN}*("("){1} MAPCOMPONENT3 ({ALLTYPESMAP}[:]{BN}*{ALLTYPESMAP1}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1}) MAPCOMPONENT4 ({ALLTYPESMAP}[:]{BN}*("entity"|"component"|"configuration"){BN}+{ALLTYPESMAP1}{TEXTT}*{BN}*("port"|"generic"){BN}*("map"){BN}*("("){1}) 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" %option noyywrap %option nounput %x Bases %x ParseType %x ParseFuncProto %x ParseComponent %x ParsePackage %x ParseProcessProto %x ClassName %x PackageName %x ClassVar %x ClassesName %x Map %x Body %% . { BEGIN(Bases); } {BRACEOPEN} { g_braceCount++; writeFont("vhdlchar",vhdlcodeYYtext); BEGIN(Map); } [^()\n,--]* { /* write and link a port map lines */ QCString tt(vhdlcodeYYtext); VhdlDocGen::deleteAllChars(tt,','); QRegExp r("=>"); QStringList ql=QStringList::split(r,tt,FALSE); if (ql.count()>=2) { unsigned int index=0; QCString t1=ql[0].utf8(); char cc=t1.at(index); while (cc==' ' || cc=='\t') { char c2[2]; c2[0]=cc; c2[1]=0; g_code->codify(c2); index++; if (index>=t1.size()) break; cc=t1.at(index); } QCString s1=t1; s1=s1.stripWhiteSpace(); // if (!g_PortMapComp.isEmpty()) generateMemLink(*g_code,g_PortMapComp,s1); while (index++codify(c2); } } codifyLines("=>"); index=0; QCString s2=ql[1].utf8(); t1=s2; cc=t1.at(index); while (cc==' ' || cc=='\t') { char c2[2]; c2[0]=cc; c2[1]=0; g_code->codify(c2); index++; if (index>=t1.size()) break; cc=t1.at(index); } s2=s2.stripWhiteSpace(); if (!checkVhdlString(s2)) generateMemLink(*g_code,g_CurrClass,s2); while (index++codify(" "); } } } else { codifyLines(vhdlcodeYYtext,g_CurrClass.data()); } BEGIN(Map); } "\n"|"," { codifyLines(vhdlcodeYYtext); BEGIN(Map); } {BRACECLOSE} { g_braceCount--; writeFont("vhdlchar",vhdlcodeYYtext); if (g_braceCount==0) { BEGIN(Bases); } } {NAME} { QCString tmp(vhdlcodeYYtext); tmp=tmp.stripWhiteSpace(); appStringLower(g_PrevString,vhdlcodeYYtext); g_vhdlKeyDict.insert(g_PrevString,new QCString(g_PrevString.data())); if (!writeColoredWord(tmp)) { generateMemLink(*g_code,g_CurrClass,tmp); } BEGIN(Bases); } {STRING} { QCString qcs(vhdlcodeYYtext); VhdlDocGen::deleteAllChars(qcs,'"'); VhdlDocGen::deleteAllChars(qcs,' '); if (VhdlDocGen::isNumber(qcs)) writeFont("vhdllogic",vhdlcodeYYtext); else writeFont("keyword",vhdlcodeYYtext); } "\n" { g_FuncProto.append(vhdlcodeYYtext); if (isProto) { codifyLines(vhdlcodeYYtext); } BEGIN(ParseType); } {TEXTT} { g_FuncProto.append(vhdlcodeYYtext); if (isProto) { writeFont("keyword",vhdlcodeYYtext); } BEGIN(ParseType); } {ENDEFUNC} { QRegExp regg("[\\s]"); QCString tt(vhdlcodeYYtext); codifyLines(vhdlcodeYYtext,g_CurrClass.data()); tt=tt.lower(); VhdlDocGen::deleteAllChars(tt,';'); tt.stripWhiteSpace(); QStringList ql=QStringList::split(regg,tt,FALSE); int index=ql.findIndex(QCString("if"))+1; index+=ql.findIndex(QCString("case"))+1; index+=ql.findIndex(QCString("loop"))+1; index+=ql.findIndex(QCString("generate"))+1; if (index==0) { BEGIN(Bases); } else { BEGIN(ParseType); } } {END1} { codifyLines(vhdlcodeYYtext,g_CurrClass.data()); g_vhdlKeyDict.clear(); } ^{B}*("begin "|"begin") { codifyLines(vhdlcodeYYtext,g_CurrClass.data()); isFuncProto=FALSE; } {SPECSIGN} { g_FuncProto.append(vhdlcodeYYtext); if (isProto) { codifyLines(vhdlcodeYYtext,g_CurrClass.data()); } } ["_a-zA-Z0-9]* { QCString val(vhdlcodeYYtext); g_FuncProto.append(vhdlcodeYYtext); appStringLower(g_PrevString,vhdlcodeYYtext); if (isFuncProto && g_braceCount==0) { g_vhdlKeyDict.insert(g_PrevString,new QCString(g_PrevString.data())); } if (isProto) { if (!writeColoredWord(val)) { if (!isFuncProto && !g_vhdlKeyDict.find(g_PrevString)) { val=val.stripWhiteSpace(); if (VhdlDocGen::isNumber(val)) { startFontClass("vhdllogic"); codifyLines(vhdlcodeYYtext,g_CurrClass.data()); endFontClass(); } else generateMemLink(*g_code,g_CurrClass,val); } else { codifyLines(vhdlcodeYYtext,g_CurrClass.data()); } } } BEGIN(ParseType); } {BRACEOPEN} { g_braceCount++; g_FuncProto+='('; if (isProto) { writeFont("vhdlchar",vhdlcodeYYtext); } BEGIN(ParseType); } {BRACECLOSE} { g_braceCount--; g_FuncProto+=')'; if (isProto) { writeFont("vhdlchar",vhdlcodeYYtext); } if (g_braceCount==0 && !isProto)// && !isPackageBody) { isProto=TRUE; appStringLower(g_PrevString,vhdlcodeYYtext); writeFuncProto(); BEGIN(Bases); } if (isPackageBody) { BEGIN(ParseType); } } {FUNCNAME} { QDict mem; appStringLower(g_PrevString,vhdlcodeYYtext); g_CurrClass.resize(0); g_CurrClass.append(vhdlcodeYYtext); g_CurrClass=g_CurrClass.stripWhiteSpace(); if (!writeColoredWord(g_CurrScope)) { generateClassOrGlobalLink(*g_code,vhdlcodeYYtext); } else { codifyLines(vhdlcodeYYtext,g_CurrClass.data()); } BEGIN(Bases); } {BRACEOPEN} { g_braceCount++; g_code->codify(vhdlcodeYYtext); } {BRACECLOSE} { g_braceCount--; g_code->codify(vhdlcodeYYtext); if (g_braceCount==0 && !isComponent) { g_tempComp.resize(0); BEGIN(Bases); } else { BEGIN(ParseComponent); } } {B}*"-" { if (strlen(vhdlcodeYYtext)>=2) // found text ? { writeFont("keyword",vhdlcodeYYtext); } else { writeFont("vhdlchar",vhdlcodeYYtext); } } {SPECSIGN} { codifyLines(vhdlcodeYYtext); } "\n"|" " { codifyLines(vhdlcodeYYtext); } {DIGITSS} { startFontClass("vhdllogic"); codifyLines(vhdlcodeYYtext); endFontClass(); } {PORT} { codifyLines(vhdlcodeYYtext); g_braceCount=1; isComponent=FALSE; } {GENERIC} { codifyLines(vhdlcodeYYtext); g_braceCount=1; } [_a-zA_Z][_a-zA-Z0-9]* { QCString temp(vhdlcodeYYtext); appStringLower(g_PrevString,vhdlcodeYYtext); if (!checkVhdlString(temp)){ if (!writeColoredWord(g_PrevString)) { generateMemLink(*g_code,g_tempComp,temp); } } } {STRING} { QCString temp(vhdlcodeYYtext); if (!checkVhdlString(temp)) codifyLines(vhdlcodeYYtext); } [^()]* { g_FuncProto.append(vhdlcodeYYtext); } {BRACEOPEN} { g_FuncProto.append(vhdlcodeYYtext); g_braceCount++; } {BRACECLOSE} { g_FuncProto.append(vhdlcodeYYtext); g_braceCount--; if (g_braceCount==0) { writeProcessProto(); BEGIN(Bases); } } [^:;]* { //found package QCString temp(vhdlcodeYYtext); QStringList strl=QStringList::split(".",temp,FALSE); if (strl.count()>2) { QCString s1=strl[0].utf8(); QCString s2=strl[1].utf8(); QCString s3=strl[2].utf8(); s1.append("."); s3.prepend("."); codifyLines(s1.data(),g_CurrClass.data()); ClassDef *cd=VhdlDocGen::getPackageName(s2); if (cd) { generateClassOrGlobalLink(*g_code,s2.data()); } else { codifyLines(s2.data()); } codifyLines(s3.data()); } else { writeFont("keywordflow",vhdlcodeYYtext); } BEGIN(Bases); } {MAPCOMPONENT1}|{MAPCOMPONENT2}|{MAPCOMPONENT3}|{MAPCOMPONENT4} { // found port or generic map QCString tt(vhdlcodeYYtext); /* if (tt.contains(':',FALSE)) { isStartMap=TRUE; } else { isStartMap=FALSE; } */ int j=tt.find('.'); if (j>0) { QCString left=tt.left(j+1); codifyLines(left.data()); tt=tt.right(tt.length()-j-1); left=VhdlDocGen::getIndexWord(tt.data(),0); if (!left.isEmpty()) { if (left.contains('(')) { j=left.find('(',FALSE); QCString name=left.left(j); generateClassOrGlobalLink(*g_code,name.data()); g_PortMapComp=name; name=tt.right(tt.length()-name.length()); codifyLines(name.data()); } else { generateClassOrGlobalLink(*g_code,left.data()); tt.stripPrefix(left.data()); //=tt.right(tt.length()-left.length()-1); g_PortMapComp=left; codifyLines(tt.data()); } } } else { if (tt.contains(':',FALSE)) codifyMapLines(tt.data()); else codifyLines(tt.data()); } g_braceCount=1; BEGIN(Map); } ^{B}*("component"){BN}+{FUNCNAME} { // found component appStringLower(g_PrevString,vhdlcodeYYtext); // writeFont("keywordflow",VhdlDocGen::getIndexWord(vhdlcodeYYtext,0).data()); // writeFont("vhdlkeyword"," "); QCString temp=VhdlDocGen::getIndexWord(vhdlcodeYYtext,1); temp=temp.stripWhiteSpace(); VhdlDocGen::deleteAllChars(temp,'\n'); g_tempComp=temp; codifyLines(vhdlcodeYYtext,temp.data(),TRUE); g_braceCount=0; //if (getClass(temp.data())) // generateClassOrGlobalLink(*g_code,temp.data()); //else // generateMemLink(*g_code,g_CurrClass,temp); isComponent=TRUE; BEGIN(ParseComponent); } {ARCHITECTURE} { // found architecture g_PortMapComp.resize(0); // writeFont("vhdlkeyword",VhdlDocGen::getIndexWord(vhdlcodeYYtext,0).data()); // writeFont("vhdlkeyword"," "); // writeFont("vhdlchar",VhdlDocGen::getIndexWord(vhdlcodeYYtext,1).data()); // writeFont("vhdlkeyword"," "); // writeFont("vhdlkeyword",VhdlDocGen::getIndexWord(vhdlcodeYYtext,2).data()); // writeFont("vhdlkeyword"," "); //QCString temp=VhdlDocGen::getIndexWord(vhdlcodeYYtext,1); //temp=temp.stripWhiteSpace(); //temp+=("-"); //temp+=VhdlDocGen::getIndexWord(vhdlcodeYYtext,3); QCString temp = VhdlDocGen::getIndexWord(vhdlcodeYYtext,3); temp+="::"; temp+=VhdlDocGen::getIndexWord(vhdlcodeYYtext,1); g_CurrClass=temp; VhdlDocGen::deleteAllChars(temp,'\n'); codifyLines(vhdlcodeYYtext,temp.data(),TRUE); //generateClassOrGlobalLink(*g_code,temp.data()); isPackageBody=FALSE; BEGIN(ClassName); } ^{B}*("package "){BN}*("body"){BN}*{FUNCNAME} { // found package body QCString ss(vhdlcodeYYtext); QCString temp=VhdlDocGen::getIndexWord(vhdlcodeYYtext,2); QStringList ql=QStringList::split(temp,ss,FALSE); QCString ll=ql[0].utf8(); codifyLines(ll.data(),g_CurrClass.data()); temp=temp.stripWhiteSpace(); temp.prepend("_"); generateClassOrGlobalLink(*g_code,temp.data()); g_CurrClass.resize(0); g_CurrClass=temp; isProto=FALSE; isPackageBody=TRUE; // BEGIN(ClassesName); } {PROCESS} { // found process isFuncProto=TRUE; g_FuncProto.resize(0); g_FuncProto.append(vhdlcodeYYtext); g_vhdlKeyDict.clear(); appStringLower(g_PrevString,vhdlcodeYYtext); if (g_PrevString.contains('(')) { g_braceCount=1; BEGIN(ParseProcessProto); } else { writeProcessProto(); } } ("end"){BN}+("process") { // end of process isFuncProto=FALSE; codifyLines(vhdlcodeYYtext); BEGIN(Bases); } ^{B}*("begin "|"begin") { isFuncProto=FALSE; writeFont("vhdlkeyword",vhdlcodeYYtext); } ^{B}*("use"|"library"){BN}+ { //found package or library writeFont("vhdlkeyword",vhdlcodeYYtext); BEGIN(ParsePackage); } ^{B}*("use"){BN}+("configuration")[^\n]* { codifyLines(vhdlcodeYYtext); } {FUNC} { // found function|procedure g_vhdlKeyDict.clear(); g_FuncProto.resize(0); isProto=FALSE; g_FuncProto.append(vhdlcodeYYtext); g_braceCount=1; BEGIN(ParseType); } ^{B}*("entity"|"package"){BN}+ { appStringLower(g_PrevString,vhdlcodeYYtext); writeFont("keywordflow",vhdlcodeYYtext); isPackageBody=FALSE; BEGIN(ClassesName); } {KEYWORD} { // found keyword QCString qcs(vhdlcodeYYtext); if (!writeColoredWord(qcs)) { startFontClass("vhdlchar"); g_code->codify(vhdlcodeYYtext); endFontClass(); } } {ID} { appStringLower(g_PrevString,vhdlcodeYYtext); QCString temp(vhdlcodeYYtext); temp=temp.stripWhiteSpace(); if (!writeColoredWord(temp)) { startFontClass("vhdlchar"); generateMemLink(*g_code,g_CurrClass,temp); endFontClass(); } } {DIGITSS} { startFontClass("vhdllogic"); codifyLines(vhdlcodeYYtext); endFontClass(); } ^{B}*("use"){BN}+("entity"|"component")[^\n]* { codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE); } {TYPEKW} { codifyLines(vhdlcodeYYtext); if (isFuncProto) { BEGIN(ParseFuncProto); } else { BEGIN(Bases); } } {OPERATOR} { startFontClass("vhdlchar"); g_code->codify(vhdlcodeYYtext); endFontClass(); } ","|"."|":"|"'"|"("|")" { startFontClass("vhdlchar"); g_code->codify(vhdlcodeYYtext); endFontClass(); } {STRING} { QCString qcs(vhdlcodeYYtext); VhdlDocGen::deleteAllChars(qcs,'"'); VhdlDocGen::deleteAllChars(qcs,' '); if (VhdlDocGen::isNumber(qcs)) writeFont("vhdllogic",vhdlcodeYYtext); else writeFont("keyword",vhdlcodeYYtext); } {B}*"#"[^\n]* { writeFont("keyword",vhdlcodeYYtext); } ^{B}*{XILINX}[^\n]* { writeWord(yytext); //codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE); } ^{B}*"set_"[^\n]* { writeWord(yytext); } <*>\n { codifyLines(vhdlcodeYYtext); BEGIN(Bases); } <*>. { g_code->codify(vhdlcodeYYtext); } <*>\n{TEXTT} { // found normal or special comment on its own line QCString text(vhdlcodeYYtext); int i=text.find("--"); if (text.mid(i,3)=="--!" && // hide special comment Config_getBool("STRIP_CODE_COMMENTS")) { g_yyLineNr++; // skip complete line } else // normal comment { startFontClass("keyword"); codifyLines(text); endFontClass(); } } <*>{TEXTT} { // found normal or special comment after something QCString text(vhdlcodeYYtext); int i=text.find("--"); if (text.mid(i,3)=="--!" && Config_getBool("STRIP_CODE_COMMENTS")) { // hide special comment } else // normal comment { startFontClass("keyword"); codifyLines(text); endFontClass(); } } %% /*@ ---------------------------------------------------------------------------- */ void resetVhdlCodeParserState() { g_vhdlKeyDict.setAutoDelete(TRUE); g_vhdlKeyDict.clear(); } void parseVhdlCode(CodeOutputInterface &od,const char *className,const QCString &s, bool /*exBlock*/, const char *exName,FileDef *fd, int startLine,int endLine,bool inlineFragment, MemberDef *memberDef,bool,Definition *searchCtx) { //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd); if (s.isEmpty()) return; if (memberDef) { ClassDef *dd=memberDef->getClassDef(); if (dd) g_CurrClass=dd->className(); startLine--; } resetVhdlCodeParserState(); g_code = &od; g_inputString = s; g_inputPosition = 0; g_currentFontClass = 0; g_needsTermination = FALSE; g_searchCtx = searchCtx; if (endLine!=-1) g_inputLines = endLine+1; else g_inputLines = countLines(); if (startLine!=-1) g_yyLineNr = startLine; else g_yyLineNr = 1; // g_theCallContext.clear(); g_classScope = className; g_exampleName = exName; g_sourceFileDef = fd; bool cleanupSourceDef = FALSE; if (fd==0) { // create a dummy filedef for the example g_sourceFileDef = new FileDef("",exName); cleanupSourceDef = TRUE; } if (g_sourceFileDef) { setCurrentDoc("l00001"); } g_currentDefinition = 0; g_currentMemberDef = 0; g_vhdlMember=0; if (!g_exampleName.isEmpty()) { g_exampleFile = convertNameToFile(g_exampleName+"-example"); } g_includeCodeFragment = inlineFragment; if (!memberDef) { startCodeLine(); } // g_type.resize(0); // g_name.resize(0); // g_args.resize(0); g_parmName.resize(0); g_parmType.resize(0); if (memberDef) { setParameterList(memberDef); } int iLine=countLines(); vhdlcodeYYrestart( vhdlcodeYYin ); BEGIN( Bases ); vhdlcodeYYlex(); g_lexInit=TRUE; if (g_needsTermination) { endCodeLine(); } if (cleanupSourceDef) { // delete the temporary file definition used for this example delete g_sourceFileDef; g_sourceFileDef=0; } assert(g_yyLineNr==iLine); return; } void codeFreeVhdlScanner() { #if defined(YY_FLEX_SUBMINOR_VERSION) if (g_lexInit) { vhdlcodeYYlex_destroy(); } #endif } #if !defined(YY_FLEX_SUBMINOR_VERSION) extern "C" { // some bogus code to keep the compiler happy void vhdlcodeYYdummy() { yy_flex_realloc(0,0); } } #elif YY_FLEX_SUBMINOR_VERSION<33 #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!" #endif