1 /************** VHDL scanner in LEX format **********
3 * Version 0.2 Wed Aug 11, 1993
5 * This scanner is derived from a scanner of the ALLIANCE CAD toolset,
6 * release 1.1. That toolset was written from:
7 * MASI/CAO-VLSI CAD Team
8 * Laboratoire MASI/CAO-VLSI
9 * Tour 55-65, 2eme etage, Porte 13
10 * Universite Pierre et Marie Curie (PARIS VI)
11 * 4, place Jussieu 75252 PARIS Cedex 05, FRANCE
12 * The ALLIANCE CAD Toolset can be obtained from ftp site : ftp-masi.ibp.fr
14 * This scanner is avail at: ftp.cs.utwente.nl in pub/src/VHDL/Grammar
15 * A corresponding Yacc grammar is available at the same site
17 * author of this derived scanner version:
20 * Dept. of Computer Scienc, LS1
22 * D-44221 Dortmund (Germany)
23 * Phone: +49-231-755-6464
24 * e-mail: dettmer@ls1.informatik.uni-dortmund.de
27 ****************************************************************
29 * This file is intended not to be used for commercial purposes
30 * without permission of the University of Dortmund
32 * NOTE THAT THERE IS NO WARRANTY FOR CORRECTNES, COMPLETENESS, SUPPORT
34 *******************************************************/
35 /******************************************************************************
36 * modified for doxygen by M. Kreis
37 * extended to VHDL 93/2002/2008
38 ******************************************************************************/
53 #include "commentscan.h"
54 #include "vhdlparser.h"
55 #include "vhdlscanner.h"
58 #include "searchindex.h"
61 #include "vhdldocgen.h"
71 extern void vhdlParse(); // defined in vhdlparser.y
73 static bool g_lexInit = FALSE;
74 static ParserInterface *g_thisParser;
75 static VhdlContainer* yycont=NULL;
76 static Entry* current_root;
79 static int yyLineNr =1;
80 static int g_lastCommentContext;
81 static int inputPosition;
82 static int startComment;
83 static QCString inputVhdlString;
84 static QFile inputFile;
85 static QCString yyFileName;
86 static QList<QCString> qlist;
87 static QCString lastLetter;
89 static bool doxComment=FALSE; // doxygen comment ?
90 static QCString strComment;
91 static int iDocLine=-1;
92 static int* lineIndex=NULL;
97 static QMap<QCString, int> keyMap;
98 static QList<Entry> lineEntry;
99 static bool checkMultiComment(QCString& qcs,int line);
100 static void handleCommentBlock(const QCString &doc,bool brief);
101 static void mapLibPackage(const Entry* ce);
102 static QList<Entry>* getEntryAtLine(const Entry* ce,int line);
103 static bool addLibUseClause(const QCString &type);
104 static Entry* oldEntry;
105 static bool varr=FALSE;
106 static QCString varName;
116 #define YY_NEVER_INTERACTIVE 1
117 #define YY_USER_ACTION num_chars += vhdlScanYYleng;
119 #define MAX_KEYWORD_LEN 20
123 char nom[MAX_KEYWORD_LEN];
127 static el_mc tab_mc []=
130 { "access", t_ACCESS },
131 { "after", t_AFTER },
132 { "alias", t_ALIAS },
135 { "architecture", t_ARCHITECTURE },
136 { "array", t_ARRAY },
137 { "assert", t_ASSERT },
138 { "assume", t_ASSUME },
139 { "assume_guarantee", t_ASSUME_GUARANTEE },
140 { "attribute", t_ATTRIBUTE },
142 { "begin", t_BEGIN },
143 { "block", t_BLOCK },
145 { "buffer", t_BUFFER },
149 { "component", t_COMPONENT },
150 { "configuration", t_CONFIGURATION },
151 { "constant", t_CONSTANT },
152 { "context", t_CONTEXT },
153 { "cover", t_COVER },
155 { "default", t_DEFAULT },
156 { "disconnect", t_DISCONNECT },
157 { "downto", t_DOWNTO },
160 { "elsif", t_ELSIF },
162 { "entity", t_ENTITY },
165 { "fairness", t_FAIRNESS },
168 { "force", t_FORCE },
169 { "function", t_FUNCTION },
171 { "generate", t_GENERATE },
172 { "generic", t_GENERIC },
173 { "group", t_GROUP },
174 { "guarded", t_GUARDED },
177 { "impure", t_IMPURE },
179 { "inertial", t_INERTIAL },
180 { "inout", t_INOUT },
183 { "label", t_LABEL },
184 { "library", t_LIBRARY },
185 { "linkage", t_LINKAGE },
186 { "literal", t_LITERAL },
203 { "others", t_OTHERS },
206 { "package", t_PACKAGE },
207 { "parameter", t_PARAMETER },
209 { "postponed", t_POSTPONED },
210 { "procedure", t_PROCEDURE },
211 { "process", t_PROCESS },
212 { "property", t_PROPERTY },
213 { "protected", t_PROTECTED },
216 { "range", t_RANGE },
217 { "record", t_RECORD },
218 { "register", t_REGISTER },
219 { "reject", t_REJECT },
220 { "release", t_RELEASE },
221 { "restrict", t_RESTRICT },
222 { "restrict_guarantee", t_RESTRICT_GUARANTEE },
224 { "report", t_REPORT },
227 { "return", t_RETURN },
229 { "select", t_SELECT },
230 { "sequence", t_SEQUENCE },
231 { "severity", t_SEVERITY },
232 { "signal", t_SIGNAL },
233 { "shared", t_SHARED },
238 { "strong", t_STRONG },
239 { "subtype", t_SUBTYPE },
243 { "transport", t_TRANSPORT },
246 { "unaffected", t_UNAFFECTED },
247 { "units", t_UNITS },
248 { "until", t_UNTIL },
251 { "variable", t_VARIABLE },
252 { "vmode", t_VMODE },
253 { "vprop", t_VPROP },
254 { "vunit", t_VUNIT },
258 { "while", t_WHILE },
263 { "zz", -1 } // list end
267 static int find_keyword(char *s)
271 if (word.length() > MAX_KEYWORD_LEN)
275 QMap<QCString, int>::Iterator it = keyMap.find(word);
282 // update current line
283 static void lineCount()
285 for (const char* c=vhdlScanYYtext ; *c ; ++c )
287 yyLineNr += (*c == '\n') ;
292 static void startCodeBlock(int index){
293 int ll=strComment.length();
294 iCodeLen=inputVhdlString.findRev(strComment.data())+ll;
295 // fprintf(stderr,"\n startin code..%d %d %d\n",iCodeLen,num_chars,ll);
298 int len=strComment.length();
299 QCString name=strComment.right(len-index);//
300 name=VhdlDocGen::getIndexWord(name.data(),1);
302 gBlock.name="misc"+ VhdlDocGen::getRecordNumber();
305 strComment=strComment.left(index);
306 gBlock.startLine=yyLineNr+1;
307 gBlock.bodyLine=yyLineNr+1;
308 VhdlDocGen::prepareComment(strComment);
309 gBlock.brief+=strComment;
311 static void makeInlineDoc(int endCode)
313 int len=endCode-iCodeLen;
314 QCString par=inputVhdlString.mid(iCodeLen,len);
316 gBlock.inbodyDocs=par;
317 gBlock.section=Entry::VARIABLE_SEC;
318 gBlock.spec=VhdlDocGen::MISCELLANEOUS;
319 gBlock.fileName = yyFileName;
320 gBlock.endBodyLine=yyLineNr-1;
321 gBlock.lang=SrcLangExt_VHDL;
322 Entry *temp=new Entry(gBlock);
324 Entry* compound=getVhdlCompound();
328 compound->addSubEntry(temp);
332 temp->type="misc"; // global code like library ieee...
333 current_root->addSubEntry(temp);
335 strComment.resize(0);
341 static bool isConstraintFile(const QCString &fileName,const QCString &ext)
343 return fileName.right(ext.length())==ext;
346 //static void resetScanner(const char* s,MyParserVhdl* parse);
349 #define YY_INPUT(buf,result,max_size) result=vhdlScanYYread(buf,max_size);
352 static int vhdlScanYYread(char *buf,int max_size)
355 while ( c < max_size && inputVhdlString.at(inputPosition) )
357 *buf = inputVhdlString.at(inputPosition++) ;
365 upper_case_letter [A-Z]
367 special_character [\#\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\_\|]
368 space_character [ \t]
369 format_effector [\t\v\r\l\f]
371 lower_case_letter [a-z]
372 other_special_character [\!\$\@\?\[\\\]\^\`\{\}\~]
374 graphic_character ({basic_graphic_character}|{lower_case_letter}|{other_special_character})
375 basic_graphic_character ({upper_case_letter}|{digit}|{special_character}|{space_character})
376 letter ({upper_case_letter}|{lower_case_letter})
377 letter_or_digit ({letter}|{digit})
378 decimal_literal {integer}(\.{integer})?({exponent})?
379 integer {digit}(_?{digit})*
380 exponent ([eE][-+]?{integer})
382 based_integer {extended_digit}(_?{extended_digit})*
383 extended_digit ({digit}|[a-fA-F])
385 extended_character [\\]{graphic_character}*[\\]
387 base_specifier {digit}*(B|b|D|O|o|X|x|"UB"|"UO"|"UX"|"SB"|"SO"|"SX")
389 vhdl2008tooldir `{graphic_character}+
398 %x EndVhdl2008Comment
401 {space_character} { /* nothing */ }
402 \& { return(t_Ampersand); }
403 \' { return(t_Apostrophe); }
404 \( { return(t_LeftParen); }
405 \) { return(t_RightParen); }
406 "**" { return(t_DoubleStar); }
407 \* { return(t_Star); }
408 \+ { return(t_Plus); }
409 \, { return(t_Comma); }
410 \- { return(t_Minus); }
411 ":=" { return(t_VarAsgn); }
412 \: { return(t_Colon); }
413 \; { return(t_Semicolon); }
414 "<=" { return(t_LESym); }
415 ">=" { return(t_GESym); }
416 \< { return(t_LTSym); }
417 \> { return(t_GTSym); }
418 \= { return(t_EQSym); }
419 \/= { return(t_NESym); }
420 "=>" { return(t_Arrow); }
421 "<>" { return(t_Box); }
422 "<<" { return(t_SLSL); }
423 ">>" { return(t_SRSR); }
424 "??" { return(t_QQ); }
425 "?>=" { return(t_QGT); }
426 "?<=" { return(t_QLT); }
427 "?>" { return(t_QG); }
428 "?<" { return(t_QL); }
429 "?=" { return(t_QEQU); }
430 "?/=" { return(t_QNEQU); }
432 \| { return(t_Bar); }
433 \. { return(t_Dot); }
434 \/ { return(t_Slash); }
436 \^ { return(t_Neg); }
437 \[ { return(t_LEFTBR); }
438 \] { return(t_RIGHTBR); }
441 {letter}(_?{letter_or_digit})*|{extended_character} {
442 int itoken=find_keyword(vhdlScanYYtext);
444 // fprintf(stderr,"\n <<<< search tok: %s %d %d>>>\n",vhdlScanYYtext,itoken,yyLineNr);
446 // tokens in vhdlparser.hpp 258..412
447 if (itoken>200 && itoken<500 && prevToken!=t_END)
449 // printf("\n <<<< insert tok: %s %d %d>>>\n",vhdlScanYYtext,itoken,yyLineNr);
450 lineIndex[itoken]=yyLineNr;
454 if (( itoken==t_ARCHITECTURE ) ||
455 ( itoken==t_ENTITY) ||
456 ( itoken==t_PACKAGE ) ||
457 ( itoken==t_LIBRARY ) ||
459 ( itoken==t_CONFIGURATION ) ||
460 ( itoken==t_CONTEXT ) )
462 lineIndex[itoken]=yyLineNr;
467 yycont->qstr=vhdlScanYYtext;
468 yycont->yyLineNr=yyLineNr;
471 yycont->iLine=yyLineNr;
480 ({decimal_literal})|({base}#{based_integer}(\.{based_integer})?#({exponent})?)|({base}:{based_integer}(\.{based_integer})?:({exponent})?) {
481 yycont->qstr=vhdlScanYYtext;
482 return ( t_ABSTRLIST );
485 '({graphic_character}|\"|\%)' {
486 QCString q(vhdlScanYYtext);
487 yycont->qstr=vhdlScanYYtext;
489 if (q=="'('") // std_logic'('1') ?
492 if (isalpha(c) || isdigit(c))
496 return(t_Apostrophe);
500 return ( t_CHARLIST );
503 return ( t_CHARLIST );
506 (\"({graphic_character}|(\"\")|\%)*\")|(\%({graphic_character}|(\%\%)|\")*\%) {
507 yycont->qstr=vhdlScanYYtext;
508 yycont->iLine=yyLineNr;
512 {base_specifier}(\"{extended_digit}(_?{extended_digit})*\"|\%{extended_digit}(_?{extended_digit})*\%) {
513 yycont->qstr=vhdlScanYYtext;
514 yycont->iLine=yyLineNr;
519 yycont->qstr=vhdlScanYYtext;
520 yycont->iLine=yyLineNr;
526 yycont->yyLineNr=yyLineNr;
531 QCString qcs(vhdlScanYYtext);
533 if (qcs.stripPrefix("--!"))
538 . { /* unknown characters */ }
541 <*>{BR}*"--!"[^{}\n][^\n]*\n/{B}*"--!" { // multi line comment
542 if (iDocLine==-1) iDocLine=yyLineNr;
543 QCString qc(vhdlScanYYtext);
544 int len=qc.contains('\n')+yyLineNr-1;
545 if (YY_START!=Comment) // Start of the comment block
547 startComment=yyLineNr;
548 g_lastCommentContext=YY_START;
551 if(!checkMultiComment(qc,len))
553 strComment+=vhdlScanYYtext;
559 <Comment>^{B}*"--!"[^\n]* {
560 if (iDocLine==-1) iDocLine=yyLineNr;
561 strComment+=vhdlScanYYtext;
562 int index=strComment.find("\\code");
565 startCodeBlock(index);
573 // found end of comment block
575 int index =strComment.find("\\code");
578 startCodeBlock(index);
581 VhdlDocGen::prepareComment(strComment);
584 if (index==-1 && !doxComment)
586 handleCommentBlock(strComment,FALSE);
588 strComment.resize(0);;
589 unput(*vhdlScanYYtext);
591 BEGIN(g_lastCommentContext);
594 <*>"--!"[^\n]* { // one line comment
595 if (iDocLine==-1) iDocLine=yyLineNr;
596 QCString qcs(vhdlScanYYtext);
598 bool isEndCode=qcs.contains("\\endcode");
600 int index = qcs.find("\\code");
603 int end=inputVhdlString.find(qcs.data(),iCodeLen);
610 startCodeBlock(index);
611 strComment.resize(0);
614 //printf("--> handleCommentBlock line %d\n",yyLineNr);
615 if (!isEndCode && index==-1)
617 int j=qcs.find("--!");
618 qcs=qcs.right(qcs.length()-3-j);
620 if(!checkMultiComment(qcs,yyLineNr))
622 handleCommentBlock(qcs,TRUE);
628 strComment+=vhdlScanYYtext;
629 if (yy_hold_char=='!') // found comment starting with "/*!"
633 BEGIN(Vhdl2008Comment);
636 <Vhdl2008Comment>[^*]*[*]+ {
637 QCString tt(vhdlScanYYtext);
639 yyLineNr+=tt.contains('\n');
641 // delete * from comments
646 if (yytext[len-1]=='*' && tt.contains('\n'))
649 VhdlDocGen::deleteAllChars(ss,' ');
650 VhdlDocGen::deleteAllChars(ss,'\t');
651 if (ss.data() && ss.at(ss.length()-2)=='\n')
658 // fprintf(stderr,"\n << %s >>",tt.data());
664 BEGIN(EndVhdl2008Comment);
668 BEGIN(Vhdl2008Comment);
672 <EndVhdl2008Comment>"*/" {
675 strComment.stripPrefix("/*!");
676 strComment= strComment.left( strComment.length()-1);
677 handleCommentBlock( strComment,TRUE);
680 strComment.resize(0);
687 static void parserInit()
690 lineIndex=(int*)malloc(500*sizeof(int));
697 while ((oop=tab_mc[p++]).kval!=-1)
699 QCString q(&oop.nom[0]);
700 keyMap.insert(q,oop.kval);
705 void vhdlscanFreeScanner()
707 #if defined(YY_FLEX_SUBMINOR_VERSION)
710 vhdlScanYYlex_destroy();
715 void VHDLLanguageScanner::resetCodeParserState()
719 bool VHDLLanguageScanner::needsPreprocessing(const QCString & /*extension*/)
724 void VHDLLanguageScanner::parsePrototype(const char *text)
731 //int VhdlParser::doLex()
733 // int token=vhdlScanYYlex();
734 // //fprintf(stderr,"\ntoken: %d at line: %d",token,yyLineNr);
738 void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,Entry *root)
740 yyFileName=QCString(fileName);
742 bool xilinx_ucf=isConstraintFile(yyFileName,".ucf");
743 bool altera_qsf=isConstraintFile(yyFileName,".qsf");
745 // support XILINX(ucf) and ALTERA (qsf) file
749 VhdlDocGen::parseUCF(fileBuf,root,yyFileName,FALSE);
754 VhdlDocGen::parseUCF(fileBuf,root,yyFileName,TRUE);
759 yycont=getVhdlCont();
761 yycont->fileName=fileName;
763 QCString pPuffer(" ");
766 inputFile.setName(fileName);
769 vhdlScanYYrestart( vhdlScanYYin );
774 inputVhdlString=fileBuf;
777 groupEnterFile(fileName,yyLineNr);
779 Entry* curr=getCurrentVhdlEntry(); // delete last current
787 void VHDLLanguageScanner::parseCode(CodeOutputInterface &codeOutIntf,
788 const char *scopeName,
789 const QCString &input,
791 const char *exampleName,
796 MemberDef *memberDef,
797 bool showLineNumbers,
798 Definition *searchCtx
801 ::parseVhdlCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName,
802 fileDef,startLine,endLine,inlineFragment,memberDef,
803 showLineNumbers,searchCtx);
807 * adds the library|use statements to the next class (entity|package|architecture|package body
817 static void mapLibPackage(const Entry* ce)
824 //const QList<Entry> *epp=ce->children();
825 EntryListIterator eli(*ce->children());
826 EntryListIterator eli1=eli;
827 for (;(rt=eli.current()),eli1=eli;++eli)
829 if (rt->spec==VhdlDocGen::LIBRARY || rt->spec==VhdlDocGen::USE)
830 // top level library or use statement
833 if(!addLibUseClause(rt->name))
840 for (;(temp=eli1.current());++eli1) // find next entity
842 if (temp->spec==VhdlDocGen::ENTITY ||
843 temp->spec==VhdlDocGen::PACKAGE ||
844 temp->spec==VhdlDocGen::ARCHITECTURE ||
845 temp->spec==VhdlDocGen::PACKAGE_BODY)
847 Entry *ee=new Entry(*rt); //append a copy to entries sublist
848 temp->addSubEntry(ee);
850 rt->spec=-1; //nullify entry
856 if (lastComp && rt->spec!=-1)
858 Entry *ee=new Entry(*rt); //append a copy to entries sublist
859 lastComp->addSubEntry(ee);
861 rt->spec=-1; //nullify entry
866 if (!found) // nothing left to do
873 static bool addLibUseClause(const QCString &type)
875 static bool show=Config_getBool("SHOW_INCLUDE_FILES");
876 static bool showIEEESTD=Config_getBool("FORCE_LOCAL_INCLUDES");
878 if (!show) // all libraries and included packages will not be shown
883 if (!showIEEESTD) // all standard packages and libraries will not be shown
885 if (type.lower().stripPrefix("ieee")) return FALSE;
886 if (type.lower().stripPrefix("std")) return FALSE;
891 static void handleCommentBlock(const QCString &doc,bool brief)
896 if (doc.isEmpty()) return;
898 bool needsEntry=FALSE;
899 Protection protection=Public;
900 int lineNr = iDocLine;
902 Entry* current=getCurrentVhdlEntry();
904 if (oldEntry==current)
906 //printf("\n find pending message < %s > at line: %d \n ",doc.data(),iDocLine);
908 str_doc.iDocLine=iDocLine;
910 str_doc.pending=TRUE;
918 current->briefLine = iDocLine;
922 current->docLine = iDocLine;
925 // printf("parseCommentBlock file<%s>\n [%s]\n",yyFileName.data(),doc.data());
926 while (parseCommentBlock(
931 lineNr, // line of block start
941 //printf("parseCommentBlock position=%d [%s]\n",position,doc.data()+position);
942 if (needsEntry) newVhdlEntry();
949 current->name=varName;
950 current->section=Entry::VARIABLEDOC_SEC;
952 strComment.resize(0);
958 strComment.resize(0);
961 // returns the vhdl parsed types at line xxx
962 QList<Entry>* getEntryAtLine(const Entry* ce,int line)
964 EntryListIterator eli(*ce->children());
966 for (;(rt=eli.current());++eli)
968 if (rt->bodyLine==line)
970 lineEntry.insert(0,rt);
973 getEntryAtLine(rt,line);
978 // token index in vhdlparser.hpp 258..416
979 int getParsedLine(int object)
981 //assert(object>254 && object <416);
982 return lineIndex [object];
985 void isVhdlDocPending()
987 if (!str_doc.pending)
989 str_doc.pending=FALSE;
990 oldEntry=0; // prevents endless recursion
991 iDocLine=str_doc.iDocLine;
992 handleCommentBlock(str_doc.doc,str_doc.brief);
996 static bool checkMultiComment(QCString& qcs,int line)
998 QList<Entry> *pTemp=getEntryAtLine(current_root,line);
1000 if (pTemp->isEmpty()) return false;
1002 //int ii=pTemp->count();
1003 qcs.stripPrefix("--!");
1004 while (!pTemp->isEmpty())
1006 Entry *e=(Entry*)pTemp->first();
1010 pTemp->removeFirst();
1011 //ii=pTemp->count();