1 /******************************************************************************
3 * Parser for syntax hightlighting and references for Fortran90 F subset
5 * Copyright (C) by Anke Visser
6 * based on the work of Dimitri van Heesch.
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation under the terms of the GNU General Public License is hereby
10 * granted. No representations are made about the suitability of this software
11 * for any purpose. It is provided "as is" without express or implied warranty.
12 * See the GNU General Public License for more details.
14 * Documents produced by Doxygen are derivative works derived from the
15 * input used in their production; they are not affected by this license.
20 @todo - continutation lines not always recognized
21 - merging of use-statements with same module name and different only-names
22 - rename part of use-statement
23 - links to interface functions
24 - references to variables
38 #include <qstringlist.h>
42 #include "outputlist.h"
44 #include "membername.h"
45 #include "searchindex.h"
48 #define YY_NEVER_INTERACTIVE 1
49 #define YY_NO_TOP_STATE 1
52 //--------------------------------------------------------------------------------
55 data of an use-statement
60 QCString module; // just for debug
61 QStringList onlyNames; /* entries of the ONLY-part */
65 module name -> list of ONLY/remote entries
66 (module name = name of the module, which can be accessed via use-directive)
68 class UseSDict : public SDict<UseEntry>
71 UseSDict() : SDict<UseEntry>(17) {}
75 Contains names of used modules and names of local variables.
80 QStringList useNames; //!< contains names of used modules
81 QDict<void> localVars; //!< contains names of local variables
83 Scope() : localVars(7, FALSE /*caseSensitive*/) {}
86 /*===================================================================*/
91 static QCString docBlock; //!< contents of all lines of a documentation block
92 static QCString currentModule=0; //!< name of the current enclosing module
93 static UseSDict *useMembers= new UseSDict; //!< info about used modules
94 static UseEntry *useEntry = 0; //!< current use statement info
95 static QList<Scope> scopeStack;
96 // static QStringList *currentUseNames= new QStringList; //! contains names of used modules of current program unit
97 static QCString str=""; //!> contents of fortran string
99 static CodeOutputInterface * g_code;
101 // TODO: is this still needed? if so, make it work
102 static QCString g_parmType;
103 static QCString g_parmName;
105 static const char * g_inputString; //!< the code fragment as text
106 static int g_inputPosition; //!< read offset during parsing
107 static int g_inputLines; //!< number of line in the code fragment
108 static int g_yyLineNr; //!< current line number
109 static bool g_needsTermination;
110 static Definition *g_searchCtx;
111 static bool g_isFixedForm;
113 static bool g_insideBody; //!< inside subprog/program body? => create links
114 static const char * g_currentFontClass;
116 static bool g_exampleBlock;
117 static QCString g_exampleName;
118 static QCString g_exampleFile;
120 static FileDef * g_sourceFileDef;
121 static Definition * g_currentDefinition;
122 static MemberDef * g_currentMemberDef;
123 static bool g_includeCodeFragment;
125 static char stringStartSymbol; // single or double quote
126 // count in variable declaration to filter out
127 // declared from referenced names
128 static int bracketCount = 0;
130 // simplified way to know if this is fixed form
131 // duplicate in fortranscanner.l
132 static bool recognizeFixedForm(const char* contents)
154 if(column==1) return TRUE;
158 if(column>1 && column<7) return FALSE;
163 if(column==7) return TRUE;
170 static void endFontClass()
172 if (g_currentFontClass)
174 g_code->endFontClass();
175 g_currentFontClass=0;
179 static void startFontClass(const char *s)
182 g_code->startFontClass(s);
183 g_currentFontClass=s;
186 static void setCurrentDoc(const QCString &anchor)
188 if (Doxygen::searchIndex)
192 Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE);
196 Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE);
201 static void addToSearchIndex(const char *text)
203 if (Doxygen::searchIndex)
205 Doxygen::searchIndex->addWord(text,FALSE);
209 /*! start a new line of code, inserting a line number if g_sourceFileDef
210 * is TRUE. If a definition starts at the current line, then the line
211 * number is linked to the documentation of that definition.
213 static void startCodeLine()
217 //QCString lineNumber,lineAnchor;
218 //lineNumber.sprintf("%05d",g_yyLineNr);
219 //lineAnchor.sprintf("l%05d",g_yyLineNr);
221 Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr);
222 //printf("startCodeLine %d d=%s\n", g_yyLineNr,d ? d->name().data() : "<null>");
223 if (!g_includeCodeFragment && d)
225 g_currentDefinition = d;
226 g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr);
227 g_insideBody = FALSE;
228 g_parmType.resize(0);
229 g_parmName.resize(0);
231 lineAnchor.sprintf("l%05d",g_yyLineNr);
232 if (g_currentMemberDef)
234 g_code->writeLineNumber(g_currentMemberDef->getReference(),
235 g_currentMemberDef->getOutputFileBase(),
236 g_currentMemberDef->anchor(),g_yyLineNr);
237 setCurrentDoc(lineAnchor);
239 else if (d->isLinkableInProject())
241 g_code->writeLineNumber(d->getReference(),
242 d->getOutputFileBase(),
244 setCurrentDoc(lineAnchor);
249 g_code->writeLineNumber(0,0,0,g_yyLineNr);
252 g_code->startCodeLine(g_sourceFileDef);
253 if (g_currentFontClass)
255 g_code->startFontClass(g_currentFontClass);
260 static void endFontClass();
261 static void endCodeLine()
264 g_code->endCodeLine();
267 /*! write a code fragment `text' that may span multiple lines, inserting
268 * line numbers for each line.
270 static void codifyLines(char *text)
272 //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text);
276 const char * tmp_currentFontClass = g_currentFontClass;
280 while ((c=*p++) && c!='\n') { }
287 if (g_yyLineNr<g_inputLines)
291 if (tmp_currentFontClass)
293 startFontClass(tmp_currentFontClass);
304 static void codifyLines(QCString str)
306 char *tmp= (char *) malloc(str.length()+1);
312 /*! writes a link to a fragment \a text that may span multiple lines, inserting
313 * line numbers for each line. If \a text contains newlines, the link will be
314 * split into multiple links with the same destination, one for each line.
316 static void writeMultiLineCodeLink(CodeOutputInterface &ol,
317 const char *ref,const char *file,
318 const char *anchor,const char *text)
321 char *p=(char *)text;
326 while ((c=*p++) && c!='\n') { }
331 //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
332 ol.writeCodeLink(ref,file,anchor,sp,0);
334 if (g_yyLineNr<g_inputLines)
341 //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
342 ol.writeCodeLink(ref,file,anchor,sp,0);
349 generates dictionay entries that are used if REFERENCED_BY_RELATION ... options are set
350 (e.g. the "referenced by ..." list after the function documentation)
353 static void addDocCrossReference(MemberDef *src, MemberDef *dst)
355 if (dst->isTypedef() || dst->isEnumerate()) return; // don't add types
356 //printf("======= addDocCrossReference src=%s,dst=%s\n",src->name().data(),dst->name().data());
357 if ((Config_getBool("REFERENCED_BY_RELATION") || Config_getBool("CALLER_GRAPH")) &&
360 dst->addSourceReferencedBy(src);
362 if ((Config_getBool("REFERENCES_RELATION") || Config_getBool("CALL_GRAPH")) && (src->isFunction()))
364 src->addSourceReferences(dst);
368 //-------------------------------------------------------------------------------
370 searches for definition of a type
371 @param tname the name of the type
372 @param moduleName name of enclosing module or null, if global entry
373 @param cd the entry, if found or null
374 @param useDict dictionary of data of USE-statement
375 @returns true, if type is found
377 static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName,
378 ClassDef *&cd, UseSDict *usedict=0)
380 if (tname.isEmpty()) return FALSE; /* empty name => nothing to link */
382 //cout << "=== search for type: " << tname << endl;
385 if ((cd=Doxygen::classSDict->find(tname)))
387 //cout << "=== type found in global module" << endl;
390 else if (moduleName && (cd= Doxygen::classSDict->find(moduleName+"::"+tname)))
392 //cout << "=== type found in local module" << endl;
398 for (UseSDict::Iterator di(*usedict); (use=di.current()); ++di)
400 if ((cd= Doxygen::classSDict->find(use->module+"::"+tname)))
402 //cout << "=== type found in used module" << endl;
412 searches for definition of function memberName
413 @param memberName the name of the function/variable
414 @param moduleName name of enclosing module or null, if global entry
415 @param md the entry, if found or null
416 @param usedict array of data of USE-statement
417 @returns true, if found
419 static bool getFortranDefs(const QCString &memberName, const QCString &moduleName,
420 MemberDef *&md, UseSDict *usedict=0)
422 if (memberName.isEmpty()) return FALSE; /* empty name => nothing to link */
424 // look in local variables
425 for (Scope *scope=scopeStack.last(); scope!=NULL; scope=scopeStack.prev())
427 if(scope->localVars.find(memberName))
431 // search for function
432 MemberName *mn = Doxygen::functionNameSDict->find(memberName);
435 mn = Doxygen::memberNameSDict->find(memberName);
438 if (mn) // name is known
440 MemberListIterator mli(*mn);
441 for (mli.toFirst();(md=mli.current());++mli) // all found functions with given name
443 FileDef *fd=md->getFileDef();
444 GroupDef *gd=md->getGroupDef();
446 //cout << "found link with same name: " << fd->fileName() << " " << memberName;
447 //if (md->getNamespaceDef() != 0) cout << " in namespace " << md->getNamespaceDef()->name();cout << endl;
449 if ((gd && gd->isLinkable()) || (fd && fd->isLinkable()))
451 NamespaceDef *nspace= md->getNamespaceDef();
454 { // found function in global scope
457 else if (moduleName == nspace->name())
458 { // found in local scope
462 { // else search in used modules
463 QCString moduleName= nspace->name();
464 UseEntry *ue= usedict->find(moduleName);
467 // check if only-list exists and if current entry exists is this list
468 QStringList &only= ue->onlyNames;
471 //cout << " found in module " << moduleName << " entry " << memberName << endl;
472 return TRUE; // whole module used
476 for ( QStringList::Iterator it = only.begin(); it != only.end(); ++it)
478 //cout << " search in only: " << moduleName << ":: " << memberName << "==" << (*it)<< endl;
479 if (memberName == (*it).utf8())
481 return TRUE; // found in ONLY-part of use list
494 gets the link to a generic procedure which depends not on the name, but on the parameter list
497 static bool getGenericProcedureLink(const ClassDef *cd,
498 const char *memberText,
499 CodeOutputInterface &ol)
507 static bool getLink(UseSDict *usedict, // dictonary with used modules
508 const char *memberText, // exact member text
509 CodeOutputInterface &ol,
513 QCString memberName= removeRedundantWhiteSpace(memberText);
515 if (getFortranDefs(memberName, currentModule, md, usedict) && md->isLinkable())
517 //if (md->isVariable()) return FALSE; // variables aren't handled yet
519 Definition *d = md->getOuterScope()==Doxygen::globalScope ?
520 md->getBodyDef() : md->getOuterScope();
521 if (md->getGroupDef()) d = md->getGroupDef();
522 if (d && d->isLinkable())
524 if (g_currentDefinition && g_currentMemberDef && md!=g_currentMemberDef && g_insideBody)
526 addDocCrossReference(g_currentMemberDef,md);
528 ol.linkableSymbol(g_yyLineNr,md->name(),md,
529 g_currentMemberDef ? g_currentMemberDef : g_currentDefinition);
530 writeMultiLineCodeLink(ol,md->getReference(),
531 md->getOutputFileBase(),
533 text ? text : memberText);
534 addToSearchIndex(text ? text : memberText);
542 static void generateLink(CodeOutputInterface &ol, char *lname)
545 QCString tmp = lname;
546 tmp = removeRedundantWhiteSpace(tmp.lower());
548 // check if lowercase lname is a linkable type or interface
549 if ( (getFortranTypeDefs(tmp, currentModule, cd, useMembers)) && cd->isLinkable() )
551 if ( (cd->compoundType() == ClassDef::Class) && // was Entry::INTERFACE_SEC) &&
552 (getGenericProcedureLink(cd, tmp, ol)) )
554 //cout << "=== generic procedure resolved" << endl;
557 { // write type or interface link
558 ol.linkableSymbol(g_yyLineNr, tmp, cd, g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
559 writeMultiLineCodeLink(ol,cd->getReference(),cd->getOutputFileBase(),cd->anchor(),tmp);
560 addToSearchIndex(tmp.data());
563 // check for function/variable
564 else if (getLink(useMembers, tmp, ol, tmp))
566 //cout << "=== found link for lowercase " << lname << endl;
570 // nothing found, just write out the word
571 ol.linkableSymbol(g_yyLineNr, tmp, 0, g_currentMemberDef?g_currentMemberDef:g_currentDefinition);
572 //startFontClass("charliteral"); //test
574 //endFontClass(); //test
575 addToSearchIndex(tmp.data());
579 /*! counts the number of lines in the input */
580 static int countLines()
582 const char *p=g_inputString;
588 if (c=='\n') count++;
590 if (p>g_inputString && *(p-1)!='\n')
591 { // last line does not end with a \n, so we add an extra
592 // line and explicitly terminate the line after parsing.
594 g_needsTermination=TRUE;
599 //----------------------------------------------------------------------------
601 static void startScope()
603 // fprintf(stderr, "===> startScope %s",yytext);
604 Scope *scope = new Scope;
605 scopeStack.append(scope);
609 static void endScope()
611 // fprintf(stderr,"===> endScope %s",yytext);
612 if (scopeStack.isEmpty())
614 //fprintf(stderr,"WARNING: fortrancode.l: stack empty!\n");
618 Scope *scope = scopeStack.getLast();
619 scopeStack.removeLast();
620 for ( QStringList::Iterator it = scope->useNames.begin(); it != scope->useNames.end(); ++it)
622 useMembers->remove((*it).utf8());
627 static void addUse(const QCString &moduleName)
629 if (!scopeStack.isEmpty())
630 scopeStack.last()->useNames.append(moduleName);
633 static void addLocalVar(const QCString &varName)
635 if (!scopeStack.isEmpty())
636 scopeStack.last()->localVars.insert(varName, (void*)1);
639 //----------------------------------------------------------------------------
641 /* -----------------------------------------------------------------*/
643 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
645 static int yyread(char *buf,int max_size)
648 while( c < max_size && g_inputString[g_inputPosition] )
650 *buf = g_inputString[g_inputPosition++] ;
659 ID [a-z_A-Z]+{IDSYM}*
660 SUBPROG (subroutine|function)
665 ARGS_L0 ("("[^)]*")")
666 ARGS_L1a [^()]*"("[^)]*")"[^)]*
667 ARGS_L1 ("("{ARGS_L1a}*")")
668 ARGS_L2 "("({ARGS_L0}|[^()]|{ARGS_L1a}|{ARGS_L1})*")"
669 ARGS {BS}({ARGS_L0}|{ARGS_L1}|{ARGS_L2})
671 NUM_TYPE (complex|integer|logical|real)
672 LOG_OPER (\.and\.|\.eq\.|\.eqv\.|\.ge\.|\.gt\.|\.le\.|\.lt\.|\.ne\.|\.neqv\.|\.or\.|\.not\.)
674 CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS}))
675 TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS_}COMPLEX|DOUBLE{BS_}PRECISION|{CHAR})
677 INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")"
678 ATTR_SPEC (IMPLICIT|ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PRIVATE|PUBLIC|SAVE|TARGET|RECURSIVE|PURE|ELEMENTAL)
679 ACCESS_SPEC (PRIVATE|PUBLIC)
680 /* Assume that attribute statements are almost the same as attributes. */
681 ATTR_STMT {ATTR_SPEC}|DIMENSION
682 FLOW (DO|SELECT|CASE|WHERE|IF|THEN|ELSE|WHILE|FORALL|ELSEWHERE|ELSEIF|RETURN|CONTINUE|EXIT)
683 COMMANDS (FORMAT|CONTAINS|MODULE{BS_}PROCEDURE|WRITE|READ|ALLOCATE|ALLOCATED|ASSOCIATED|DEALLOCATE|SIZE|INQUIRE|OPEN|CLOSE|DATA|COMMON)
685 PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTAL)?
711 /*==================================================================*/
713 /*-------- ignore ------------------------------------------------------------*/
715 <Start>{IGNORE}/{BS}"("? { // do not search keywords, intrinsics... TODO: complete list
718 /*-------- inner construct ---------------------------------------------------*/
720 <Start>{COMMANDS}/[,( \t\n].* { // highlight
721 /* font class is defined e.g. in doxygen.css */
722 startFontClass("keyword");
726 <Start>{FLOW}/[,( \t\n].* {
727 /* font class is defined e.g. in doxygen.css */
728 startFontClass("keywordflow");
732 <Start>"end"({BS}{FLOW})?/[ \t\n] { // list is a bit long as not all have possible end
733 startFontClass("keywordflow");
738 <Start>"implicit"{BS}"none" {
739 startFontClass("keywordtype");
743 /*-------- use statement -------------------------------------------*/
745 startFontClass("keywordtype");
748 yy_push_state(YY_START);
752 QCString tmp = yytext;
755 generateLink(*g_code, yytext);
758 /* append module name to use dict */
759 useEntry = new UseEntry();
760 //useEntry->module = yytext;
761 //useMembers->append(yytext, useEntry);
763 useEntry->module = tmp;
764 useMembers->append(tmp, useEntry);
767 <Use>,{BS}"ONLY" { // TODO: rename
768 startFontClass("keywordtype");
771 yy_push_state(YY_START);
774 <UseOnly>{BS},{BS} { codifyLines(yytext); }
775 <UseOnly>{BS}&{BS}"\n" { codifyLines(yytext); }
778 generateLink(*g_code, yytext);
780 useEntry->onlyNames.append(yytext);
787 /*-------- fortran module -----------------------------------------*/
788 <Start>("block"{BS}"data"|"program"|"module"|"type"|"interface")/{BS_}|({COMMA}{ACCESS_SPEC})|\n { //
790 startFontClass("keyword");
793 yy_push_state(YY_START);
795 if (!stricmp(yytext,"module")) currentModule="module";
798 if (currentModule == "module")
800 currentModule=yytext;
801 currentModule = currentModule.lower();
803 generateLink(*g_code,yytext);
806 <ClassName>\n { // interface may be without name
810 <Start>"end"({BS_}"module").* { // just reset currentModule, rest is done in following rule
814 /*-------- subprog definition -------------------------------------*/
815 <Start>({PREFIX}{BS_})?{TYPE_SPEC}{BS_}({PREFIX}{BS_})?{BS}/{SUBPROG}{BS_} { // TYPE_SPEC is for old function style function result
816 startFontClass("keyword");
820 <Start>({PREFIX}{BS_})?{SUBPROG}{BS_} { // Fortran subroutine or function found
821 startFontClass("keyword");
824 yy_push_state(YY_START);
827 <Subprog>{ID} { // subroutine/function name
828 // fprintf(stderr, "===> start subprogram %s\n", yytext);
830 generateLink(*g_code,yytext);
832 <Subprog>"(".* { // ignore rest of line
835 <Subprog,Subprogend>"\n" { codifyLines(yytext);
838 <Start>^{BS}"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"type"|"interface"){BS} { // Fortran subroutine or function ends
839 //cout << "===> end function " << yytext << endl;
841 startFontClass("keyword");
844 yy_push_state(YY_START);
847 <Subprogend>{ID}/{BS}(\n|!) {
848 generateLink(*g_code,yytext);
851 <Start>^{BS}"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"type"|"interface"){BS}/(\n|!) { // Fortran subroutine or function ends
852 //cout << "===> end function " << yytext << endl;
854 startFontClass("keyword");
858 /*-------- variable declaration ----------------------------------*/
859 <Start>"type"{BS}"(" {
860 yy_push_state(YY_START);
862 startFontClass("keywordtype");
863 g_code->codify(yytext);
866 <TypeDecl>{ID} { // link type
868 generateLink(*g_code,yytext);
873 startFontClass("keywordtype");
874 g_code->codify(yytext);
877 <Start>{TYPE_SPEC}/[,:( ] {
878 yy_push_state(YY_START);
880 startFontClass("keywordtype");
881 g_code->codify(yytext);
885 startFontClass("keywordtype");
886 g_code->codify(yytext);
889 <Declaration>({TYPE_SPEC}|{ATTR_SPEC})/[,:( ] { //| variable deklaration
890 startFontClass("keywordtype");
891 g_code->codify(yytext);
894 <Declaration>{ID} { // local var
895 if (g_currentMemberDef && !g_currentMemberDef->isFunction())
897 g_code->codify(yytext);
902 generateLink(*g_code, yytext);
905 <Declaration>[(] { // start of array specification
907 g_code->codify(yytext);
910 <Declaration>[)] { // end array specification
912 g_code->codify(yytext);
915 <Declaration>"&" { // continuation line
916 g_code->codify(yytext);
917 yy_push_state(YY_START);
920 <DeclContLine>"\n" { // declaration not yet finished
925 <Declaration>"\n" { // end declaration line
931 /*-------- subprog calls -----------------------------------------*/
935 yy_push_state(YY_START);
938 <SubCall>{ID} { // subroutine call
940 generateLink(*g_code, yytext);
944 <Start>{ID}{BS}/"(" { // function call
946 generateLink(*g_code, yytext);
950 /*-------- comments ---------------------------------------------------*/
951 <Start>\n?{BS}"!>"|"!<" { // start comment line or comment block
952 yy_push_state(YY_START);
956 <Declaration>{BS}"!<" { // start comment line or comment block
957 yy_push_state(YY_START);
962 <DocBlock>.* { // contents of current comment line
965 <DocBlock>"\n"{BS}("!>"|"!<"|"!!") { //| comment block (next line is also comment line)
968 <DocBlock>"\n" { // comment block ends at the end of this line
970 // remove special comment (default config)
971 if (Config_getBool("STRIP_CODE_COMMENTS"))
973 g_yyLineNr+=((QCString)docBlock).contains('\n');
975 if (g_yyLineNr<g_inputLines)
980 else // do not remove comment
982 startFontClass("comment");
983 codifyLines(docBlock);
989 <*>"!"[^><\n].*|"!"$ { // normal comment
990 if(YY_START == String) REJECT; // ignore in strings
991 startFontClass("comment");
996 <*>^[Cc*].* { // normal comment
997 if(! g_isFixedForm) REJECT;
999 startFontClass("comment");
1000 codifyLines(yytext);
1004 /*------ preprocessor --------------------------------------------*/
1005 <Start>"#".*\n { startFontClass("preprocessor");
1006 codifyLines(yytext);
1009 /*------ variable references? -------------------------------------*/
1011 <Start>"%"{BS}{ID} { // ignore references to elements
1012 g_code->codify(yytext);
1016 generateLink(*g_code, yytext);
1019 /*------ strings --------------------------------------------------*/
1020 <*>"\\\\" { str+=yytext; /* ignore \\ */}
1021 <*>"\\\""|\\\' { str+=yytext; /* ignore \" */}
1023 <String>\n { // string with \n inside
1025 startFontClass("stringliteral");
1030 <String>\"|\' { // string ends with next quote without previous backspace
1031 if(yytext[0]!=stringStartSymbol) REJECT; // single vs double quote
1033 startFontClass("stringliteral");
1038 <String>. {str+=yytext;}
1040 <*>\"|\' { /* string starts */
1041 /* if(YY_START == StrIgnore) REJECT; // ignore in simple comments */
1042 yy_push_state(YY_START);
1043 stringStartSymbol=yytext[0]; // single or double quote
1047 /*-----------------------------------------------------------------------------*/
1050 codifyLines(yytext);
1053 g_code->codify(yytext);
1055 <*>{LOG_OPER} { // Fortran logical comparison keywords
1056 g_code->codify(yytext);
1060 /*@ ----------------------------------------------------------------------------
1063 /*===================================================================*/
1066 void resetFortranCodeParserState() {}
1068 void parseFortranCode(CodeOutputInterface &od,const char *className,const QCString &s,
1069 bool exBlock, const char *exName,FileDef *fd,
1070 int startLine,int endLine,bool inlineFragment,
1071 MemberDef *memberDef,bool,Definition *searchCtx)
1073 //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd);
1079 if (s.isEmpty()) return;
1082 g_inputPosition = 0;
1083 g_isFixedForm = recognizeFixedForm((const char*)s);
1084 g_currentFontClass = 0;
1085 g_needsTermination = FALSE;
1086 g_searchCtx = searchCtx;
1088 g_inputLines = endLine+1;
1090 g_inputLines = countLines();
1093 g_yyLineNr = startLine;
1097 g_exampleBlock = exBlock;
1098 g_exampleName = exName;
1099 g_sourceFileDef = fd;
1100 if (exBlock && fd==0)
1102 // create a dummy filedef for the example
1103 g_sourceFileDef = new FileDef("",exName);
1105 if (g_sourceFileDef)
1107 setCurrentDoc("l00001");
1109 g_currentDefinition = 0;
1110 g_currentMemberDef = 0;
1111 if (!g_exampleName.isEmpty())
1113 g_exampleFile = convertNameToFile(g_exampleName+"-example");
1115 g_includeCodeFragment = inlineFragment;
1117 g_parmName.resize(0);
1118 g_parmType.resize(0);
1119 fcodeYYrestart( fcodeYYin );
1122 if (g_needsTermination)
1125 g_code->endCodeLine();
1127 if (exBlock && g_sourceFileDef)
1129 // delete the temporary file definition used for this example
1130 delete g_sourceFileDef;
1136 #if !defined(YY_FLEX_SUBMINOR_VERSION)
1137 extern "C" { // some bogus code to keep the compiler happy
1138 void fcodeYYdummy() { yy_flex_realloc(0,0); }
1140 #elif YY_FLEX_SUBMINOR_VERSION<33
1141 #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!"
1143 extern "C" { // some bogus code to keep the compiler happy
1144 void fcodeYYdummy() { yy_top_state(); }