|
Packit |
1c1d7e |
/******************************************************************************
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* Parser for syntax highlighting and references for Fortran90 F subset
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* Copyright (C) by Anke Visser
|
|
Packit |
1c1d7e |
* based on the work of Dimitri van Heesch.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* Permission to use, copy, modify, and distribute this software and its
|
|
Packit |
1c1d7e |
* documentation under the terms of the GNU General Public License is hereby
|
|
Packit |
1c1d7e |
* granted. No representations are made about the suitability of this software
|
|
Packit |
1c1d7e |
* for any purpose. It is provided "as is" without express or implied warranty.
|
|
Packit |
1c1d7e |
* See the GNU General Public License for more details.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* Documents produced by Doxygen are derivative works derived from the
|
|
Packit |
1c1d7e |
* input used in their production; they are not affected by this license.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/**
|
|
Packit |
1c1d7e |
@todo - continutation lines not always recognized
|
|
Packit |
1c1d7e |
- merging of use-statements with same module name and different only-names
|
|
Packit |
1c1d7e |
- rename part of use-statement
|
|
Packit |
1c1d7e |
- links to interface functions
|
|
Packit |
1c1d7e |
- references to variables
|
|
Packit |
1c1d7e |
**/
|
|
Packit |
1c1d7e |
%option never-interactive
|
|
Packit |
1c1d7e |
%option case-insensitive
|
|
Packit |
1c1d7e |
%option prefix="fortrancodeYY"
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
%{
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*
|
|
Packit |
1c1d7e |
* includes
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
#include <stdio.h>
|
|
Packit |
1c1d7e |
#include <assert.h>
|
|
Packit |
1c1d7e |
#include <ctype.h>
|
|
Packit |
1c1d7e |
#include <qregexp.h>
|
|
Packit |
1c1d7e |
#include <qdir.h>
|
|
Packit |
1c1d7e |
#include <qstringlist.h>
|
|
Packit |
1c1d7e |
#include "entry.h"
|
|
Packit |
1c1d7e |
#include "doxygen.h"
|
|
Packit |
1c1d7e |
#include "message.h"
|
|
Packit |
1c1d7e |
#include "outputlist.h"
|
|
Packit |
1c1d7e |
#include "util.h"
|
|
Packit |
1c1d7e |
#include "membername.h"
|
|
Packit |
1c1d7e |
#include "searchindex.h"
|
|
Packit |
1c1d7e |
#include "defargs.h"
|
|
Packit |
1c1d7e |
#include "memberlist.h"
|
|
Packit |
1c1d7e |
#include "config.h"
|
|
Packit |
1c1d7e |
#include "groupdef.h"
|
|
Packit |
1c1d7e |
#include "classlist.h"
|
|
Packit |
1c1d7e |
#include "filedef.h"
|
|
Packit |
1c1d7e |
#include "namespacedef.h"
|
|
Packit |
1c1d7e |
#include "tooltip.h"
|
|
Packit |
1c1d7e |
#include "fortrancode.h"
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// Toggle for some debugging info
|
|
Packit |
1c1d7e |
//#define DBG_CTX(x) fprintf x
|
|
Packit |
1c1d7e |
#define DBG_CTX(x) do { } while(0)
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#define YY_NO_TOP_STATE 1
|
|
Packit |
1c1d7e |
#define YY_NO_INPUT 1
|
|
Packit |
1c1d7e |
#define YY_NO_UNISTD_H 1
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*
|
|
Packit |
1c1d7e |
* For fixed formatted code position 6 is of importance (continuation character).
|
|
Packit |
1c1d7e |
* The following variables and macros keep track of the column number
|
|
Packit |
1c1d7e |
* YY_USER_ACTION is always called for each scan action
|
|
Packit |
1c1d7e |
* YY_FTN_RESET is used to handle end of lines and reset the column counter
|
|
Packit |
1c1d7e |
* YY_FTN_REJECT resets the column counters when a pattern is rejected and thus rescanned.
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
int yy_old_start = 0;
|
|
Packit |
1c1d7e |
int yy_my_start = 0;
|
|
Packit |
1c1d7e |
int yy_end = 1;
|
|
Packit |
1c1d7e |
#define YY_USER_ACTION {yy_old_start = yy_my_start; yy_my_start = yy_end; yy_end += yyleng;}
|
|
Packit |
1c1d7e |
#define YY_FTN_RESET {yy_old_start = 0; yy_my_start = 0; yy_end = 1;}
|
|
Packit |
1c1d7e |
#define YY_FTN_REJECT {yy_end = yy_my_start; yy_my_start = yy_old_start; REJECT;}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//--------------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/**
|
|
Packit |
1c1d7e |
data of an use-statement
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
class UseEntry
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
public:
|
|
Packit |
1c1d7e |
QCString module; // just for debug
|
|
Packit |
1c1d7e |
QStringList onlyNames; /* entries of the ONLY-part */
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/**
|
|
Packit |
1c1d7e |
module name -> list of ONLY/remote entries
|
|
Packit |
1c1d7e |
(module name = name of the module, which can be accessed via use-directive)
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
class UseSDict : public SDict<UseEntry>
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
public:
|
|
Packit |
1c1d7e |
UseSDict() : SDict<UseEntry>(17) {}
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/**
|
|
Packit |
1c1d7e |
Contains names of used modules and names of local variables.
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
class Scope
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
public:
|
|
Packit |
1c1d7e |
QStringList useNames; //!< contains names of used modules
|
|
Packit |
1c1d7e |
QDict<void> localVars; //!< contains names of local variables
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Scope() : localVars(7, FALSE /*caseSensitive*/) {}
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*===================================================================*/
|
|
Packit |
1c1d7e |
/*
|
|
Packit |
1c1d7e |
* statics
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static QCString docBlock; //!< contents of all lines of a documentation block
|
|
Packit |
1c1d7e |
static QCString currentModule=0; //!< name of the current enclosing module
|
|
Packit |
1c1d7e |
static QCString currentClass=0; //!< name of the current enclosing class
|
|
Packit |
1c1d7e |
static UseSDict *useMembers= new UseSDict; //!< info about used modules
|
|
Packit |
1c1d7e |
static UseEntry *useEntry = 0; //!< current use statement info
|
|
Packit |
1c1d7e |
static QList<Scope> scopeStack;
|
|
Packit |
1c1d7e |
// static QStringList *currentUseNames= new QStringList; //! contains names of used modules of current program unit
|
|
Packit |
1c1d7e |
static QCString str=""; //!> contents of fortran string
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static CodeOutputInterface * g_code;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// TODO: is this still needed? if so, make it work
|
|
Packit |
1c1d7e |
static QCString g_parmType;
|
|
Packit |
1c1d7e |
static QCString g_parmName;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static const char * g_inputString; //!< the code fragment as text
|
|
Packit |
1c1d7e |
static int g_inputPosition; //!< read offset during parsing
|
|
Packit |
1c1d7e |
static int g_inputLines; //!< number of line in the code fragment
|
|
Packit |
1c1d7e |
static int g_yyLineNr; //!< current line number
|
|
Packit |
1c1d7e |
static int g_contLineNr; //!< current, local, line number for continuation determination
|
|
Packit |
1c1d7e |
static int *g_hasContLine = NULL; //!< signals whether or not a line has a continuation line (fixed source form)
|
|
Packit |
1c1d7e |
static bool g_needsTermination;
|
|
Packit |
1c1d7e |
static Definition *g_searchCtx;
|
|
Packit |
1c1d7e |
static bool g_collectXRefs;
|
|
Packit |
1c1d7e |
static bool g_isFixedForm;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static bool g_insideBody; //!< inside subprog/program body? => create links
|
|
Packit |
1c1d7e |
static const char * g_currentFontClass;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static bool g_exampleBlock;
|
|
Packit |
1c1d7e |
static QCString g_exampleName;
|
|
Packit |
1c1d7e |
static QCString g_exampleFile;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static FileDef * g_sourceFileDef;
|
|
Packit |
1c1d7e |
static Definition * g_currentDefinition;
|
|
Packit |
1c1d7e |
static MemberDef * g_currentMemberDef;
|
|
Packit |
1c1d7e |
static bool g_includeCodeFragment;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static char stringStartSymbol; // single or double quote
|
|
Packit |
1c1d7e |
// count in variable declaration to filter out
|
|
Packit |
1c1d7e |
// declared from referenced names
|
|
Packit |
1c1d7e |
static int bracketCount = 0;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static bool g_endComment;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void endFontClass()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (g_currentFontClass)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_code->endFontClass();
|
|
Packit |
1c1d7e |
g_currentFontClass=0;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void startFontClass(const char *s)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// if font class is already set don't stop and start it.
|
|
Packit |
1c1d7e |
// strcmp does not like null pointers as input.
|
|
Packit |
1c1d7e |
if (!g_currentFontClass || !s || strcmp(g_currentFontClass,s))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
g_code->startFontClass(s);
|
|
Packit |
1c1d7e |
g_currentFontClass=s;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void setCurrentDoc(const QCString &anchor)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (Doxygen::searchIndex)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (g_searchCtx)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void addToSearchIndex(const char *text)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (Doxygen::searchIndex)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
Doxygen::searchIndex->addWord(text,FALSE);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! start a new line of code, inserting a line number if g_sourceFileDef
|
|
Packit |
1c1d7e |
* is TRUE. If a definition starts at the current line, then the line
|
|
Packit |
1c1d7e |
* number is linked to the documentation of that definition.
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
static void startCodeLine()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (g_sourceFileDef)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//QCString lineNumber,lineAnchor;
|
|
Packit |
1c1d7e |
//lineNumber.sprintf("%05d",g_yyLineNr);
|
|
Packit |
1c1d7e |
//lineAnchor.sprintf("l%05d",g_yyLineNr);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr);
|
|
Packit |
1c1d7e |
//printf("startCodeLine %d d=%s\n", g_yyLineNr,d ? d->name().data() : "<null>");
|
|
Packit |
1c1d7e |
if (!g_includeCodeFragment && d)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_currentDefinition = d;
|
|
Packit |
1c1d7e |
g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr);
|
|
Packit |
1c1d7e |
g_insideBody = FALSE;
|
|
Packit |
1c1d7e |
g_endComment = FALSE;
|
|
Packit |
1c1d7e |
g_parmType.resize(0);
|
|
Packit |
1c1d7e |
g_parmName.resize(0);
|
|
Packit |
1c1d7e |
QCString lineAnchor;
|
|
Packit |
1c1d7e |
lineAnchor.sprintf("l%05d",g_yyLineNr);
|
|
Packit |
1c1d7e |
if (g_currentMemberDef)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_code->writeLineNumber(g_currentMemberDef->getReference(),
|
|
Packit |
1c1d7e |
g_currentMemberDef->getOutputFileBase(),
|
|
Packit |
1c1d7e |
g_currentMemberDef->anchor(),g_yyLineNr);
|
|
Packit |
1c1d7e |
setCurrentDoc(lineAnchor);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (d->isLinkableInProject())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_code->writeLineNumber(d->getReference(),
|
|
Packit |
1c1d7e |
d->getOutputFileBase(),
|
|
Packit |
1c1d7e |
0,g_yyLineNr);
|
|
Packit |
1c1d7e |
setCurrentDoc(lineAnchor);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_code->writeLineNumber(0,0,0,g_yyLineNr);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
g_code->startCodeLine(g_sourceFileDef);
|
|
Packit |
1c1d7e |
if (g_currentFontClass)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_code->startFontClass(g_currentFontClass);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void endFontClass();
|
|
Packit |
1c1d7e |
static void endCodeLine()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
g_code->endCodeLine();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! write a code fragment `text' that may span multiple lines, inserting
|
|
Packit |
1c1d7e |
* line numbers for each line.
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
static void codifyLines(char *text)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text);
|
|
Packit |
1c1d7e |
char *p=text,*sp=p;
|
|
Packit |
1c1d7e |
char c;
|
|
Packit |
1c1d7e |
bool done=FALSE;
|
|
Packit |
1c1d7e |
const char * tmp_currentFontClass = g_currentFontClass;
|
|
Packit |
1c1d7e |
while (!done)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
sp=p;
|
|
Packit |
1c1d7e |
while ((c=*p++) && c!='\n') { }
|
|
Packit |
1c1d7e |
if (c=='\n')
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_yyLineNr++;
|
|
Packit |
1c1d7e |
*(p-1)='\0';
|
|
Packit |
1c1d7e |
g_code->codify(sp);
|
|
Packit |
1c1d7e |
endCodeLine();
|
|
Packit |
1c1d7e |
if (g_yyLineNr
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
startCodeLine();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (tmp_currentFontClass)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
startFontClass(tmp_currentFontClass);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_code->codify(sp);
|
|
Packit |
1c1d7e |
done=TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void codifyLines(QCString str)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
char *tmp= (char *) malloc(str.length()+1);
|
|
Packit |
1c1d7e |
strcpy(tmp, str);
|
|
Packit |
1c1d7e |
codifyLines(tmp);
|
|
Packit |
1c1d7e |
free(tmp);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! writes a link to a fragment \a text that may span multiple lines, inserting
|
|
Packit |
1c1d7e |
* line numbers for each line. If \a text contains newlines, the link will be
|
|
Packit |
1c1d7e |
* split into multiple links with the same destination, one for each line.
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
static void writeMultiLineCodeLink(CodeOutputInterface &ol,
|
|
Packit |
1c1d7e |
Definition *d,const char *text)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS);
|
|
Packit |
1c1d7e |
TooltipManager::instance()->addTooltip(d);
|
|
Packit |
1c1d7e |
QCString ref = d->getReference();
|
|
Packit |
1c1d7e |
QCString file = d->getOutputFileBase();
|
|
Packit |
1c1d7e |
QCString anchor = d->anchor();
|
|
Packit |
1c1d7e |
QCString tooltip;
|
|
Packit |
1c1d7e |
if (!sourceTooltips) // fall back to simple "title" tooltips
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
tooltip = d->briefDescriptionAsTooltip();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
bool done=FALSE;
|
|
Packit |
1c1d7e |
char *p=(char *)text;
|
|
Packit |
1c1d7e |
while (!done)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
char *sp=p;
|
|
Packit |
1c1d7e |
char c;
|
|
Packit |
1c1d7e |
while ((c=*p++) && c!='\n') { }
|
|
Packit |
1c1d7e |
if (c=='\n')
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_yyLineNr++;
|
|
Packit |
1c1d7e |
*(p-1)='\0';
|
|
Packit |
1c1d7e |
//printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
|
|
Packit |
1c1d7e |
ol.writeCodeLink(ref,file,anchor,sp,tooltip);
|
|
Packit |
1c1d7e |
endCodeLine();
|
|
Packit |
1c1d7e |
if (g_yyLineNr
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
startCodeLine();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
|
|
Packit |
1c1d7e |
ol.writeCodeLink(ref,file,anchor,sp,tooltip);
|
|
Packit |
1c1d7e |
done=TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
//-------------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
/**
|
|
Packit |
1c1d7e |
searches for definition of a module (Namespace)
|
|
Packit |
1c1d7e |
@param mname the name of the module
|
|
Packit |
1c1d7e |
@param cd the entry, if found or null
|
|
Packit |
1c1d7e |
@returns true, if module is found
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
static bool getFortranNamespaceDefs(const QCString &mname,
|
|
Packit |
1c1d7e |
NamespaceDef *&cd)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (mname.isEmpty()) return FALSE; /* empty name => nothing to link */
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// search for module
|
|
Packit |
1c1d7e |
if ((cd=Doxygen::namespaceSDict->find(mname))) return TRUE;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
return FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
//-------------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
/**
|
|
Packit |
1c1d7e |
searches for definition of a type
|
|
Packit |
1c1d7e |
@param tname the name of the type
|
|
Packit |
1c1d7e |
@param moduleName name of enclosing module or null, if global entry
|
|
Packit |
1c1d7e |
@param cd the entry, if found or null
|
|
Packit |
1c1d7e |
@param useDict dictionary of data of USE-statement
|
|
Packit |
1c1d7e |
@returns true, if type is found
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName,
|
|
Packit |
1c1d7e |
ClassDef *&cd, UseSDict *usedict=0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (tname.isEmpty()) return FALSE; /* empty name => nothing to link */
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//cout << "=== search for type: " << tname << endl;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// search for type
|
|
Packit |
1c1d7e |
if ((cd=Doxygen::classSDict->find(tname)))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//cout << "=== type found in global module" << endl;
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (moduleName && (cd= Doxygen::classSDict->find(moduleName+"::"+tname)))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//cout << "=== type found in local module" << endl;
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
UseEntry *use;
|
|
Packit |
1c1d7e |
for (UseSDict::Iterator di(*usedict); (use=di.current()); ++di)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if ((cd= Doxygen::classSDict->find(use->module+"::"+tname)))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//cout << "=== type found in used module" << endl;
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
return FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/**
|
|
Packit |
1c1d7e |
searches for definition of function memberName
|
|
Packit |
1c1d7e |
@param memberName the name of the function/variable
|
|
Packit |
1c1d7e |
@param moduleName name of enclosing module or null, if global entry
|
|
Packit |
1c1d7e |
@param md the entry, if found or null
|
|
Packit |
1c1d7e |
@param usedict array of data of USE-statement
|
|
Packit |
1c1d7e |
@returns true, if found
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
static bool getFortranDefs(const QCString &memberName, const QCString &moduleName,
|
|
Packit |
1c1d7e |
MemberDef *&md, UseSDict *usedict=0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (memberName.isEmpty()) return FALSE; /* empty name => nothing to link */
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// look in local variables
|
|
Packit |
1c1d7e |
QListIterator<Scope> it(scopeStack);
|
|
Packit |
1c1d7e |
Scope *scope;
|
|
Packit |
1c1d7e |
for (it.toLast();(scope=it.current());--it)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (scope->localVars.find(memberName))
|
|
Packit |
1c1d7e |
return FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// search for function
|
|
Packit |
1c1d7e |
MemberName *mn = Doxygen::functionNameSDict->find(memberName);
|
|
Packit |
1c1d7e |
if (!mn)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
mn = Doxygen::memberNameSDict->find(memberName);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (mn) // name is known
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
MemberNameIterator mli(*mn);
|
|
Packit |
1c1d7e |
for (mli.toFirst();(md=mli.current());++mli) // all found functions with given name
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
FileDef *fd=md->getFileDef();
|
|
Packit |
1c1d7e |
GroupDef *gd=md->getGroupDef();
|
|
Packit |
1c1d7e |
ClassDef *cd=md->getClassDef();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//cout << "found link with same name: " << fd->fileName() << " " << memberName;
|
|
Packit |
1c1d7e |
//if (md->getNamespaceDef() != 0) cout << " in namespace " << md->getNamespaceDef()->name();cout << endl;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if ((gd && gd->isLinkable()) || (fd && fd->isLinkable()))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
NamespaceDef *nspace= md->getNamespaceDef();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (nspace == 0)
|
|
Packit |
1c1d7e |
{ // found function in global scope
|
|
Packit |
1c1d7e |
if(cd == 0) { // Skip if bound to type
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (moduleName == nspace->name())
|
|
Packit |
1c1d7e |
{ // found in local scope
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{ // else search in used modules
|
|
Packit |
1c1d7e |
QCString moduleName= nspace->name();
|
|
Packit |
1c1d7e |
UseEntry *ue= usedict->find(moduleName);
|
|
Packit |
1c1d7e |
if (ue)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// check if only-list exists and if current entry exists is this list
|
|
Packit |
1c1d7e |
QStringList &only= ue->onlyNames;
|
|
Packit |
1c1d7e |
if (only.isEmpty())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//cout << " found in module " << moduleName << " entry " << memberName << endl;
|
|
Packit |
1c1d7e |
return TRUE; // whole module used
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
for ( QStringList::Iterator it = only.begin(); it != only.end(); ++it)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//cout << " search in only: " << moduleName << ":: " << memberName << "==" << (*it)<< endl;
|
|
Packit |
1c1d7e |
if (memberName == (*it).utf8())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
return TRUE; // found in ONLY-part of use list
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
} // if linkable
|
|
Packit |
1c1d7e |
} // for
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/**
|
|
Packit |
1c1d7e |
gets the link to a generic procedure which depends not on the name, but on the parameter list
|
|
Packit |
1c1d7e |
@todo implementation
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
static bool getGenericProcedureLink(const ClassDef *cd,
|
|
Packit |
1c1d7e |
const char *memberText,
|
|
Packit |
1c1d7e |
CodeOutputInterface &ol)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
(void)cd;
|
|
Packit |
1c1d7e |
(void)memberText;
|
|
Packit |
1c1d7e |
(void)ol;
|
|
Packit |
1c1d7e |
return FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static bool getLink(UseSDict *usedict, // dictonary with used modules
|
|
Packit |
1c1d7e |
const char *memberText, // exact member text
|
|
Packit |
1c1d7e |
CodeOutputInterface &ol,
|
|
Packit |
1c1d7e |
const char *text)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
MemberDef *md=0;
|
|
Packit |
1c1d7e |
QCString memberName= removeRedundantWhiteSpace(memberText);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (getFortranDefs(memberName, currentModule, md, usedict) && md->isLinkable())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (md->isVariable() && (md->getLanguage()!=SrcLangExt_Fortran)) return FALSE; // Non Fortran variables aren't handled yet,
|
|
Packit |
1c1d7e |
// see also linkifyText in util.cpp
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Definition *d = md->getOuterScope()==Doxygen::globalScope ?
|
|
Packit |
1c1d7e |
md->getBodyDef() : md->getOuterScope();
|
|
Packit |
1c1d7e |
if (md->getGroupDef()) d = md->getGroupDef();
|
|
Packit |
1c1d7e |
if (d && d->isLinkable())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (g_currentDefinition && g_currentMemberDef &&
|
|
Packit |
1c1d7e |
md!=g_currentMemberDef && g_insideBody && g_collectXRefs)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
addDocCrossReference(g_currentMemberDef,md);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
writeMultiLineCodeLink(ol,md,text ? text : memberText);
|
|
Packit |
1c1d7e |
addToSearchIndex(text ? text : memberText);
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void generateLink(CodeOutputInterface &ol, char *lname)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
ClassDef *cd=0;
|
|
Packit |
1c1d7e |
NamespaceDef *nsd=0;
|
|
Packit |
1c1d7e |
QCString tmp = lname;
|
|
Packit |
1c1d7e |
tmp = removeRedundantWhiteSpace(tmp.lower());
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// check if lowercase lname is a linkable type or interface
|
|
Packit |
1c1d7e |
if ( (getFortranTypeDefs(tmp, currentModule, cd, useMembers)) && cd->isLinkable() )
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if ( (cd->compoundType() == ClassDef::Class) && // was Entry::INTERFACE_SEC) &&
|
|
Packit |
1c1d7e |
(getGenericProcedureLink(cd, tmp, ol)) )
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//cout << "=== generic procedure resolved" << endl;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{ // write type or interface link
|
|
Packit |
1c1d7e |
writeMultiLineCodeLink(ol,cd,tmp);
|
|
Packit |
1c1d7e |
addToSearchIndex(tmp.data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
// check for module
|
|
Packit |
1c1d7e |
else if ( (getFortranNamespaceDefs(tmp, nsd)) && nsd->isLinkable() )
|
|
Packit |
1c1d7e |
{ // write module link
|
|
Packit |
1c1d7e |
writeMultiLineCodeLink(ol,nsd,tmp);
|
|
Packit |
1c1d7e |
addToSearchIndex(tmp.data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
// check for function/variable
|
|
Packit |
1c1d7e |
else if (getLink(useMembers, tmp, ol, tmp))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//cout << "=== found link for lowercase " << lname << endl;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// nothing found, just write out the word
|
|
Packit |
1c1d7e |
//startFontClass("charliteral"); //test
|
|
Packit |
1c1d7e |
codifyLines(tmp);
|
|
Packit |
1c1d7e |
//endFontClass(); //test
|
|
Packit |
1c1d7e |
addToSearchIndex(tmp.data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! counts the number of lines in the input */
|
|
Packit |
1c1d7e |
static int countLines()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
const char *p=g_inputString;
|
|
Packit |
1c1d7e |
char c;
|
|
Packit |
1c1d7e |
int count=1;
|
|
Packit |
1c1d7e |
while ((c=*p))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
p++ ;
|
|
Packit |
1c1d7e |
if (c=='\n') count++;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (p>g_inputString && *(p-1)!='\n')
|
|
Packit |
1c1d7e |
{ // last line does not end with a \n, so we add an extra
|
|
Packit |
1c1d7e |
// line and explicitly terminate the line after parsing.
|
|
Packit |
1c1d7e |
count++,
|
|
Packit |
1c1d7e |
g_needsTermination=TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return count;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
/** start scope */
|
|
Packit |
1c1d7e |
static void startScope()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
DBG_CTX((stderr, "===> startScope %s",yytext));
|
|
Packit |
1c1d7e |
Scope *scope = new Scope;
|
|
Packit |
1c1d7e |
scopeStack.append(scope);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/** end scope */
|
|
Packit |
1c1d7e |
static void endScope()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
DBG_CTX((stderr,"===> endScope %s",yytext));
|
|
Packit |
1c1d7e |
if (scopeStack.isEmpty())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
DBG_CTX((stderr,"WARNING: fortrancode.l: stack empty!\n"));
|
|
Packit |
1c1d7e |
return;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Scope *scope = scopeStack.getLast();
|
|
Packit |
1c1d7e |
scopeStack.removeLast();
|
|
Packit |
1c1d7e |
for ( QStringList::Iterator it = scope->useNames.begin(); it != scope->useNames.end(); ++it)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
useMembers->remove((*it).utf8());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
delete scope;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void addUse(const QCString &moduleName)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!scopeStack.isEmpty())
|
|
Packit |
1c1d7e |
scopeStack.getLast()->useNames.append(moduleName);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void addLocalVar(const QCString &varName)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!scopeStack.isEmpty())
|
|
Packit |
1c1d7e |
scopeStack.getLast()->localVars.insert(varName, (void*)1);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/* -----------------------------------------------------------------*/
|
|
Packit |
1c1d7e |
#undef YY_INPUT
|
|
Packit |
1c1d7e |
#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static int yyread(char *buf,int max_size)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
int c=0;
|
|
Packit |
1c1d7e |
while( c < max_size && g_inputString[g_inputPosition] )
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
*buf = g_inputString[g_inputPosition++] ;
|
|
Packit |
1c1d7e |
c++; buf++;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return c;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
%}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
IDSYM [a-z_A-Z0-9]
|
|
Packit |
1c1d7e |
ID [a-z_A-Z]+{IDSYM}*
|
|
Packit |
1c1d7e |
SUBPROG (subroutine|function)
|
|
Packit |
1c1d7e |
B [ \t]
|
|
Packit |
1c1d7e |
BS [ \t]*
|
|
Packit |
1c1d7e |
BS_ [ \t]+
|
|
Packit |
1c1d7e |
COMMA {BS},{BS}
|
|
Packit |
1c1d7e |
ARGS_L0 ("("[^)]*")")
|
|
Packit |
1c1d7e |
ARGS_L1a [^()]*"("[^)]*")"[^)]*
|
|
Packit |
1c1d7e |
ARGS_L1 ("("{ARGS_L1a}*")")
|
|
Packit |
1c1d7e |
ARGS_L2 "("({ARGS_L0}|[^()]|{ARGS_L1a}|{ARGS_L1})*")"
|
|
Packit |
1c1d7e |
ARGS {BS}({ARGS_L0}|{ARGS_L1}|{ARGS_L2})
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
NUM_TYPE (complex|integer|logical|real)
|
|
Packit |
1c1d7e |
LOG_OPER (\.and\.|\.eq\.|\.eqv\.|\.ge\.|\.gt\.|\.le\.|\.lt\.|\.ne\.|\.neqv\.|\.or\.|\.not\.)
|
|
Packit |
1c1d7e |
KIND {ARGS}
|
|
Packit |
1c1d7e |
CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS}))
|
|
Packit |
1c1d7e |
TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|{CHAR}|TYPE|CLASS|PROCEDURE)
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")"
|
|
Packit |
1c1d7e |
ATTR_SPEC (IMPLICIT|ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PROTECTED|PRIVATE|PUBLIC|SAVE|TARGET|RECURSIVE|PURE|IMPURE|ELEMENTAL|VALUE|NOPASS|DEFERRED|CONTIGUOUS|VOLATILE)
|
|
Packit |
1c1d7e |
ACCESS_SPEC (PROTECTED|PRIVATE|PUBLIC)
|
|
Packit |
1c1d7e |
/* Assume that attribute statements are almost the same as attributes. */
|
|
Packit |
1c1d7e |
ATTR_STMT {ATTR_SPEC}|DIMENSION
|
|
Packit |
1c1d7e |
FLOW (DO|SELECT|CASE|SELECT{BS}(CASE|TYPE)|WHERE|IF|THEN|ELSE|WHILE|FORALL|ELSEWHERE|ELSEIF|RETURN|CONTINUE|EXIT|GO{BS}TO)
|
|
Packit |
1c1d7e |
COMMANDS (FORMAT|CONTAINS|MODULE{BS_}PROCEDURE|WRITE|READ|ALLOCATE|ALLOCATED|ASSOCIATED|PRESENT|DEALLOCATE|NULLIFY|SIZE|INQUIRE|OPEN|CLOSE|FLUSH|DATA|COMMON)
|
|
Packit |
1c1d7e |
IGNORE (CALL)
|
|
Packit |
1c1d7e |
PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|IMPURE|PURE|ELEMENTAL)?
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/* | */
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
%option noyywrap
|
|
Packit |
1c1d7e |
%option stack
|
|
Packit |
1c1d7e |
%option caseless
|
|
Packit |
1c1d7e |
/*%option debug*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
%x Start
|
|
Packit |
1c1d7e |
%x SubCall
|
|
Packit |
1c1d7e |
%x FuncDef
|
|
Packit |
1c1d7e |
%x ClassName
|
|
Packit |
1c1d7e |
%x ClassVar
|
|
Packit |
1c1d7e |
%x Subprog
|
|
Packit |
1c1d7e |
%x DocBlock
|
|
Packit |
1c1d7e |
%x Use
|
|
Packit |
1c1d7e |
%x UseOnly
|
|
Packit |
1c1d7e |
%x Import
|
|
Packit |
1c1d7e |
%x Declaration
|
|
Packit |
1c1d7e |
%x DeclarationBinding
|
|
Packit |
1c1d7e |
%x DeclContLine
|
|
Packit |
1c1d7e |
%x Parameterlist
|
|
Packit |
1c1d7e |
%x String
|
|
Packit |
1c1d7e |
%x Subprogend
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
%%
|
|
Packit |
1c1d7e |
/*==================================================================*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*-------- ignore ------------------------------------------------------------*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Start>{IGNORE}/{BS}"(" { // do not search keywords, intrinsics... TODO: complete list
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
/*-------- inner construct ---------------------------------------------------*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Start>{COMMANDS}/{BS}[,( \t\n] { // highlight
|
|
Packit |
1c1d7e |
/* font class is defined e.g. in doxygen.css */
|
|
Packit |
1c1d7e |
startFontClass("keyword");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>{FLOW}/{BS}[,( \t\n] {
|
|
Packit |
1c1d7e |
if (g_isFixedForm)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if ((yy_my_start == 1) && ((yytext[0] == 'c') || (yytext[0] == 'C'))) YY_FTN_REJECT;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
/* font class is defined e.g. in doxygen.css */
|
|
Packit |
1c1d7e |
startFontClass("keywordflow");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>{BS}(CASE|CLASS|TYPE){BS_}(IS|DEFAULT) {
|
|
Packit |
1c1d7e |
startFontClass("keywordflow");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>{BS}"end"({BS}{FLOW})/[ \t\n] { // list is a bit long as not all have possible end
|
|
Packit |
1c1d7e |
startFontClass("keywordflow");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>"implicit"{BS}("none"|{TYPE_SPEC}) {
|
|
Packit |
1c1d7e |
startFontClass("keywordtype");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>^{BS}"namelist"/[//] { // Namelist specification
|
|
Packit |
1c1d7e |
startFontClass("keywordtype");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
/*-------- use statement -------------------------------------------*/
|
|
Packit |
1c1d7e |
<Start>"use"{BS_} {
|
|
Packit |
1c1d7e |
startFontClass("keywordtype");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(Use);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Use>"ONLY" { // TODO: rename
|
|
Packit |
1c1d7e |
startFontClass("keywordtype");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(UseOnly);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Use>{ID} {
|
|
Packit |
1c1d7e |
QCString tmp = yytext;
|
|
Packit |
1c1d7e |
tmp = tmp.lower();
|
|
Packit |
1c1d7e |
g_insideBody=TRUE;
|
|
Packit |
1c1d7e |
generateLink(*g_code, yytext);
|
|
Packit |
1c1d7e |
g_insideBody=FALSE;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/* append module name to use dict */
|
|
Packit |
1c1d7e |
useEntry = new UseEntry();
|
|
Packit |
1c1d7e |
//useEntry->module = yytext;
|
|
Packit |
1c1d7e |
//useMembers->append(yytext, useEntry);
|
|
Packit |
1c1d7e |
//addUse(yytext);
|
|
Packit |
1c1d7e |
useEntry->module = tmp;
|
|
Packit |
1c1d7e |
useMembers->append(tmp, useEntry);
|
|
Packit |
1c1d7e |
addUse(tmp);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Use,UseOnly,Import>{BS},{BS} { codifyLines(yytext); }
|
|
Packit |
1c1d7e |
<UseOnly,Import>{BS}&{BS}"\n" { codifyLines(yytext);
|
|
Packit |
1c1d7e |
g_contLineNr++;
|
|
Packit |
1c1d7e |
YY_FTN_RESET}
|
|
Packit |
1c1d7e |
<UseOnly>{ID} {
|
|
Packit |
1c1d7e |
QCString tmp = yytext;
|
|
Packit |
1c1d7e |
tmp = tmp.lower();
|
|
Packit |
1c1d7e |
useEntry->onlyNames.append(tmp);
|
|
Packit |
1c1d7e |
g_insideBody=TRUE;
|
|
Packit |
1c1d7e |
generateLink(*g_code, yytext);
|
|
Packit |
1c1d7e |
g_insideBody=FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Use,UseOnly,Import>"\n" {
|
|
Packit |
1c1d7e |
unput(*yytext);
|
|
Packit |
1c1d7e |
yy_pop_state();YY_FTN_RESET
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>"import"{BS_} {
|
|
Packit |
1c1d7e |
startFontClass("keywordtype");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(Import);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Import>{ID} {
|
|
Packit |
1c1d7e |
g_insideBody=TRUE;
|
|
Packit |
1c1d7e |
generateLink(*g_code, yytext);
|
|
Packit |
1c1d7e |
g_insideBody=FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
/*-------- fortran module -----------------------------------------*/
|
|
Packit |
1c1d7e |
<Start>("block"{BS}"data"|"program"|"module"|"interface")/{BS_}|({COMMA}{ACCESS_SPEC})|\n { //
|
|
Packit |
1c1d7e |
startScope();
|
|
Packit |
1c1d7e |
startFontClass("keyword");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(ClassName);
|
|
Packit |
1c1d7e |
if (!qstricmp(yytext,"module")) currentModule="module";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>("type")/{BS_}|({COMMA}({ACCESS_SPEC}|ABSTRACT|EXTENDS))|\n { //
|
|
Packit |
1c1d7e |
startScope();
|
|
Packit |
1c1d7e |
startFontClass("keyword");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(ClassName);
|
|
Packit |
1c1d7e |
currentClass="class";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<ClassName>{ID} {
|
|
Packit |
1c1d7e |
if (currentModule == "module")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
currentModule=yytext;
|
|
Packit |
1c1d7e |
currentModule = currentModule.lower();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
generateLink(*g_code,yytext);
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<ClassName>({ACCESS_SPEC}|ABSTRACT|EXTENDS)/[,:( ] { //| variable deklaration
|
|
Packit |
1c1d7e |
startFontClass("keyword");
|
|
Packit |
1c1d7e |
g_code->codify(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<ClassName>\n { // interface may be without name
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
YY_FTN_REJECT;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>^{BS}"end"({BS_}"type").* { // just reset currentClass, rest is done in following rule
|
|
Packit |
1c1d7e |
currentClass=0;
|
|
Packit |
1c1d7e |
YY_FTN_REJECT;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>^{BS}"end"({BS_}"module").* { // just reset currentModule, rest is done in following rule
|
|
Packit |
1c1d7e |
currentModule=0;
|
|
Packit |
1c1d7e |
YY_FTN_REJECT;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
/*-------- subprog definition -------------------------------------*/
|
|
Packit |
1c1d7e |
<Start>({PREFIX}{BS_})?{TYPE_SPEC}{BS_}({PREFIX}{BS_})?{BS}/{SUBPROG}{BS_} { // TYPE_SPEC is for old function style function result
|
|
Packit |
1c1d7e |
startFontClass("keyword");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>({PREFIX}{BS_})?{SUBPROG}{BS_} { // Fortran subroutine or function found
|
|
Packit |
1c1d7e |
startFontClass("keyword");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(Subprog);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Subprog>{ID} { // subroutine/function name
|
|
Packit |
1c1d7e |
DBG_CTX((stderr, "===> start subprogram %s\n", yytext));
|
|
Packit |
1c1d7e |
startScope();
|
|
Packit |
1c1d7e |
generateLink(*g_code,yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Subprog>"result"/{BS}"("[^)]*")" {
|
|
Packit |
1c1d7e |
startFontClass("keyword");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Subprog>"("[^)]*")" { // ignore rest of line
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Subprog,Subprogend>"\n" { codifyLines(yytext);
|
|
Packit |
1c1d7e |
g_contLineNr++;
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
YY_FTN_RESET
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>^{BS}"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"type"|"interface")?{BS} { // Fortran subroutine or function ends
|
|
Packit |
1c1d7e |
//cout << "===> end function " << yytext << endl;
|
|
Packit |
1c1d7e |
endScope();
|
|
Packit |
1c1d7e |
startFontClass("keyword");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(Subprogend);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Subprogend>{ID}/{BS}(\n|!) {
|
|
Packit |
1c1d7e |
generateLink(*g_code,yytext);
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>^{BS}"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"type"|"interface"){BS}/(\n|!) { // Fortran subroutine or function ends
|
|
Packit |
1c1d7e |
//cout << "===> end function " << yytext << endl;
|
|
Packit |
1c1d7e |
endScope();
|
|
Packit |
1c1d7e |
startFontClass("keyword");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
/*-------- variable declaration ----------------------------------*/
|
|
Packit |
1c1d7e |
<Start>{TYPE_SPEC}/[,:( ] {
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(Declaration);
|
|
Packit |
1c1d7e |
startFontClass("keywordtype");
|
|
Packit |
1c1d7e |
g_code->codify(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>{ATTR_SPEC} {
|
|
Packit |
1c1d7e |
startFontClass("keywordtype");
|
|
Packit |
1c1d7e |
g_code->codify(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Declaration>({TYPE_SPEC}|{ATTR_SPEC})/[,:( ] { //| variable deklaration
|
|
Packit |
1c1d7e |
startFontClass("keywordtype");
|
|
Packit |
1c1d7e |
g_code->codify(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Declaration>{ID} { // local var
|
|
Packit |
1c1d7e |
if (g_isFixedForm && yy_my_start == 1)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
startFontClass("comment");
|
|
Packit |
1c1d7e |
g_code->codify(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (g_currentMemberDef && ((g_currentMemberDef->isFunction() && (g_currentMemberDef->typeString() != QCString("subroutine"))) ||
|
|
Packit |
1c1d7e |
g_currentMemberDef->isVariable()))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
generateLink(*g_code, yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_code->codify(yytext);
|
|
Packit |
1c1d7e |
addLocalVar(yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Declaration>{BS}("=>"|"="){BS} { // Procedure binding
|
|
Packit |
1c1d7e |
BEGIN(DeclarationBinding);
|
|
Packit |
1c1d7e |
g_code->codify(yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<DeclarationBinding>{ID} { // Type bound procedure link
|
|
Packit |
1c1d7e |
generateLink(*g_code, yytext);
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Declaration>[(] { // start of array specification
|
|
Packit |
1c1d7e |
bracketCount++;
|
|
Packit |
1c1d7e |
g_code->codify(yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Declaration>[)] { // end array specification
|
|
Packit |
1c1d7e |
bracketCount--;
|
|
Packit |
1c1d7e |
g_code->codify(yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Declaration,DeclarationBinding>"&" { // continuation line
|
|
Packit |
1c1d7e |
g_code->codify(yytext);
|
|
Packit |
1c1d7e |
if (!g_isFixedForm)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(DeclContLine);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<DeclContLine>"\n" { // declaration not yet finished
|
|
Packit |
1c1d7e |
g_contLineNr++;
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
bracketCount = 0;
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
YY_FTN_RESET
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Declaration,DeclarationBinding>"\n" { // end declaration line (?)
|
|
Packit |
1c1d7e |
if (g_endComment)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_endComment=FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
bracketCount = 0;
|
|
Packit |
1c1d7e |
g_contLineNr++;
|
|
Packit |
1c1d7e |
if (!(g_hasContLine && g_hasContLine[g_contLineNr - 1]))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
YY_FTN_RESET
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*-------- subprog calls -----------------------------------------*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Start>"call"{BS_} {
|
|
Packit |
1c1d7e |
startFontClass("keyword");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(SubCall);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<SubCall>{ID} { // subroutine call
|
|
Packit |
1c1d7e |
g_insideBody=TRUE;
|
|
Packit |
1c1d7e |
generateLink(*g_code, yytext);
|
|
Packit |
1c1d7e |
g_insideBody=FALSE;
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>{ID}{BS}/"(" { // function call
|
|
Packit |
1c1d7e |
if (g_isFixedForm && yy_my_start == 6)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// fixed form continuation line
|
|
Packit |
1c1d7e |
YY_FTN_REJECT;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_insideBody=TRUE;
|
|
Packit |
1c1d7e |
generateLink(*g_code, yytext);
|
|
Packit |
1c1d7e |
g_insideBody=FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*-------- comments ---------------------------------------------------*/
|
|
Packit |
1c1d7e |
<Start,Declaration,DeclarationBinding>\n?{BS}"!>"|"!<" { // start comment line or comment block
|
|
Packit |
1c1d7e |
if (yytext[0] == '\n')
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_contLineNr++;
|
|
Packit |
1c1d7e |
yy_old_start = 0;
|
|
Packit |
1c1d7e |
yy_my_start = 1;
|
|
Packit |
1c1d7e |
yy_end = yyleng;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
// Actually we should see if ! on position 6, can be continuation
|
|
Packit |
1c1d7e |
// but the chance is very unlikely, so no effort to solve it here
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(DocBlock);
|
|
Packit |
1c1d7e |
docBlock=yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Declaration,DeclarationBinding>{BS}"!<" { // start comment line or comment block
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(DocBlock);
|
|
Packit |
1c1d7e |
docBlock=yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<DocBlock>.* { // contents of current comment line
|
|
Packit |
1c1d7e |
docBlock+=yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<DocBlock>"\n"{BS}("!>"|"!<"|"!!") { // comment block (next line is also comment line)
|
|
Packit |
1c1d7e |
g_contLineNr++;
|
|
Packit |
1c1d7e |
yy_old_start = 0;
|
|
Packit |
1c1d7e |
yy_my_start = 1;
|
|
Packit |
1c1d7e |
yy_end = yyleng;
|
|
Packit |
1c1d7e |
// Actually we should see if ! on position 6, can be continuation
|
|
Packit |
1c1d7e |
// but the chance is very unlikely, so no effort to solve it here
|
|
Packit |
1c1d7e |
docBlock+=yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<DocBlock>"\n" { // comment block ends at the end of this line
|
|
Packit |
1c1d7e |
// remove special comment (default config)
|
|
Packit |
1c1d7e |
g_contLineNr++;
|
|
Packit |
1c1d7e |
if (Config_getBool(STRIP_CODE_COMMENTS))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_yyLineNr+=((QCString)docBlock).contains('\n');
|
|
Packit |
1c1d7e |
g_yyLineNr+=1;
|
|
Packit |
1c1d7e |
endCodeLine();
|
|
Packit |
1c1d7e |
if (g_yyLineNr
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
startCodeLine();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
g_endComment=TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else // do not remove comment
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
startFontClass("comment");
|
|
Packit |
1c1d7e |
codifyLines(docBlock);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
unput(*yytext);
|
|
Packit |
1c1d7e |
g_contLineNr--;
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
YY_FTN_RESET
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<*>"!"[^><\n].*|"!"$ { // normal comment
|
|
Packit |
1c1d7e |
if(YY_START == String) YY_FTN_REJECT; // ignore in strings
|
|
Packit |
1c1d7e |
if (g_isFixedForm && yy_my_start == 6) YY_FTN_REJECT;
|
|
Packit |
1c1d7e |
startFontClass("comment");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<*>^[Cc*].* { // normal comment
|
|
Packit |
1c1d7e |
if(! g_isFixedForm) YY_FTN_REJECT;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
startFontClass("comment");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<*>"assignment"/{BS}"("{BS}"="{BS}")" {
|
|
Packit |
1c1d7e |
startFontClass("keyword");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<*>"operator"/{BS}"("[^)]*")" {
|
|
Packit |
1c1d7e |
startFontClass("keyword");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*------ preprocessor --------------------------------------------*/
|
|
Packit |
1c1d7e |
<Start>"#".*\n {
|
|
Packit |
1c1d7e |
if (g_isFixedForm && yy_my_start == 6) YY_FTN_REJECT;
|
|
Packit |
1c1d7e |
g_contLineNr++;
|
|
Packit |
1c1d7e |
startFontClass("preprocessor");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
YY_FTN_RESET
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
/*------ variable references? -------------------------------------*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Start>"%"{BS}{ID} { // ignore references to elements
|
|
Packit |
1c1d7e |
g_code->codify(yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>{ID} {
|
|
Packit |
1c1d7e |
g_insideBody=TRUE;
|
|
Packit |
1c1d7e |
generateLink(*g_code, yytext);
|
|
Packit |
1c1d7e |
g_insideBody=FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
/*------ strings --------------------------------------------------*/
|
|
Packit |
1c1d7e |
<*>"\\\\" { str+=yytext; /* ignore \\ */}
|
|
Packit |
1c1d7e |
<*>"\\\""|\\\' { str+=yytext; /* ignore \" */}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<String>\n { // string with \n inside
|
|
Packit |
1c1d7e |
g_contLineNr++;
|
|
Packit |
1c1d7e |
str+=yytext;
|
|
Packit |
1c1d7e |
startFontClass("stringliteral");
|
|
Packit |
1c1d7e |
codifyLines(str);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
str = "";
|
|
Packit |
1c1d7e |
YY_FTN_RESET
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<String>\"|\' { // string ends with next quote without previous backspace
|
|
Packit |
1c1d7e |
if(yytext[0]!=stringStartSymbol) YY_FTN_REJECT; // single vs double quote
|
|
Packit |
1c1d7e |
str+=yytext;
|
|
Packit |
1c1d7e |
startFontClass("stringliteral");
|
|
Packit |
1c1d7e |
codifyLines(str);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<String>. {str+=yytext;}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<*>\"|\' { /* string starts */
|
|
Packit |
1c1d7e |
/* if(YY_START == StrIgnore) YY_FTN_REJECT; // ignore in simple comments */
|
|
Packit |
1c1d7e |
if (g_isFixedForm && yy_my_start == 6) YY_FTN_REJECT;
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
stringStartSymbol=yytext[0]; // single or double quote
|
|
Packit |
1c1d7e |
BEGIN(String);
|
|
Packit |
1c1d7e |
str=yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
/*-----------------------------------------------------------------------------*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<*>\n {
|
|
Packit |
1c1d7e |
if (g_endComment)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_endComment=FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
g_contLineNr++;
|
|
Packit |
1c1d7e |
YY_FTN_RESET
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<*>^{BS}"type"{BS}"=" { g_code->codify(yytext); }
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<*>. {
|
|
Packit |
1c1d7e |
if (g_isFixedForm && yy_my_start > fixedCommentAfter)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
//BEGIN(DocBlock);
|
|
Packit |
1c1d7e |
//docBlock=yytext;
|
|
Packit |
1c1d7e |
startFontClass("comment");
|
|
Packit |
1c1d7e |
codifyLines(yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_code->codify(yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<*>{LOG_OPER} { // Fortran logical comparison keywords
|
|
Packit |
1c1d7e |
g_code->codify(yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<*><<EOF>> {
|
|
Packit |
1c1d7e |
if (YY_START == DocBlock) {
|
|
Packit |
1c1d7e |
if (!Config_getBool(STRIP_CODE_COMMENTS))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
startFontClass("comment");
|
|
Packit |
1c1d7e |
codifyLines(docBlock);
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
yyterminate();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
%%
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*@ ----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*===================================================================*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
void resetFortranCodeParserState() {}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
bool recognizeFixedForm(const char* contents, FortranFormat format); /* prototype, implementation in fortranscanner.l */
|
|
Packit |
1c1d7e |
const char* prepassFixedForm(const char* contents, int *hasContLine); /* prototype, implementation in fortranscanner.l */
|
|
Packit |
1c1d7e |
static void checkContLines(const char *s)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
int numLines = 0;
|
|
Packit |
1c1d7e |
int curLine = 0;
|
|
Packit |
1c1d7e |
int i = 0;
|
|
Packit |
1c1d7e |
const char *p = s;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
numLines = 2; // one for element 0, one in case no \n at end
|
|
Packit |
1c1d7e |
while (*p)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (*p == '\n') numLines++;
|
|
Packit |
1c1d7e |
p++;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
g_hasContLine = (int *) malloc((numLines) * sizeof(int));
|
|
Packit |
1c1d7e |
for (i = 0; i < numLines; i++)
|
|
Packit |
1c1d7e |
g_hasContLine[i] = 0;
|
|
Packit |
1c1d7e |
p = prepassFixedForm(s, g_hasContLine);
|
|
Packit |
1c1d7e |
g_hasContLine[0] = 0;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
void parseFortranCode(CodeOutputInterface &od,const char *className,const QCString &s,
|
|
Packit |
1c1d7e |
bool exBlock, const char *exName,FileDef *fd,
|
|
Packit |
1c1d7e |
int startLine,int endLine,bool inlineFragment,
|
|
Packit |
1c1d7e |
MemberDef *memberDef,bool,Definition *searchCtx,
|
|
Packit |
1c1d7e |
bool collectXRefs, FortranFormat format)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// used parameters
|
|
Packit |
1c1d7e |
(void)memberDef;
|
|
Packit |
1c1d7e |
(void)className;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (s.isEmpty()) return;
|
|
Packit |
1c1d7e |
printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL);
|
|
Packit |
1c1d7e |
TooltipManager::instance()->clearTooltips();
|
|
Packit |
1c1d7e |
g_code = &od;
|
|
Packit |
1c1d7e |
g_inputString = s;
|
|
Packit |
1c1d7e |
g_inputPosition = 0;
|
|
Packit |
1c1d7e |
g_isFixedForm = recognizeFixedForm((const char*)s,format);
|
|
Packit |
1c1d7e |
g_contLineNr = 1;
|
|
Packit |
1c1d7e |
g_hasContLine = NULL;
|
|
Packit |
1c1d7e |
if (g_isFixedForm)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
checkContLines(g_inputString);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
g_currentFontClass = 0;
|
|
Packit |
1c1d7e |
g_needsTermination = FALSE;
|
|
Packit |
1c1d7e |
g_searchCtx = searchCtx;
|
|
Packit |
1c1d7e |
g_collectXRefs = collectXRefs;
|
|
Packit |
1c1d7e |
if (startLine!=-1)
|
|
Packit |
1c1d7e |
g_yyLineNr = startLine;
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
g_yyLineNr = 1;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (endLine!=-1)
|
|
Packit |
1c1d7e |
g_inputLines = endLine+1;
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
g_inputLines = g_yyLineNr + countLines() - 1;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
g_exampleBlock = exBlock;
|
|
Packit |
1c1d7e |
g_exampleName = exName;
|
|
Packit |
1c1d7e |
g_sourceFileDef = fd;
|
|
Packit |
1c1d7e |
if (exBlock && fd==0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// create a dummy filedef for the example
|
|
Packit |
1c1d7e |
g_sourceFileDef = new FileDef("",exName);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (g_sourceFileDef)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
setCurrentDoc("l00001");
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
g_currentDefinition = 0;
|
|
Packit |
1c1d7e |
g_currentMemberDef = 0;
|
|
Packit |
1c1d7e |
if (!g_exampleName.isEmpty())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_exampleFile = convertNameToFile(g_exampleName+"-example");
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
g_includeCodeFragment = inlineFragment;
|
|
Packit |
1c1d7e |
startCodeLine();
|
|
Packit |
1c1d7e |
g_parmName.resize(0);
|
|
Packit |
1c1d7e |
g_parmType.resize(0);
|
|
Packit |
1c1d7e |
fortrancodeYYrestart( fortrancodeYYin );
|
|
Packit |
1c1d7e |
BEGIN( Start );
|
|
Packit |
1c1d7e |
fortrancodeYYlex();
|
|
Packit |
1c1d7e |
if (g_needsTermination)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
endFontClass();
|
|
Packit |
1c1d7e |
g_code->endCodeLine();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (fd)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
TooltipManager::instance()->writeTooltips(*g_code);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (exBlock && g_sourceFileDef)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// delete the temporary file definition used for this example
|
|
Packit |
1c1d7e |
delete g_sourceFileDef;
|
|
Packit |
1c1d7e |
g_sourceFileDef=0;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (g_hasContLine) free(g_hasContLine);
|
|
Packit |
1c1d7e |
g_hasContLine = NULL;
|
|
Packit |
1c1d7e |
printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL);
|
|
Packit |
1c1d7e |
return;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#if !defined(YY_FLEX_SUBMINOR_VERSION)
|
|
Packit |
1c1d7e |
extern "C" { // some bogus code to keep the compiler happy
|
|
Packit |
1c1d7e |
void fortrancodeYYdummy() { yy_flex_realloc(0,0); }
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
#elif YY_FLEX_MAJOR_VERSION<=2 && YY_FLEX_MINOR_VERSION<=5 && YY_FLEX_SUBMINOR_VERSION<33
|
|
Packit |
1c1d7e |
#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!"
|
|
Packit |
1c1d7e |
#else
|
|
Packit |
1c1d7e |
extern "C" { // some bogus code to keep the compiler happy
|
|
Packit |
1c1d7e |
void fortrancodeYYdummy() { yy_top_state(); }
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
#endif
|
|
Packit |
1c1d7e |
|