Contribution of a new version of ORB and CXX DITA plug-in bug 1461 bug 1621 bug 1962
/*****************************************************************************
*
*
*
* Copyright (C) 1997-2008 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
%{
/*
* includes
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include "qtbc.h"
#include <qarray.h>
#include <qstack.h>
#include <qregexp.h>
#include <unistd.h>
#include <qfile.h>
#include "scanner.h"
#include "entry.h"
#include "message.h"
#include "config.h"
#include "doxygen.h"
#include "util.h"
#include "defargs.h"
#include "language.h"
#include "commentscan.h"
#include "code.h"
#define YY_NEVER_INTERACTIVE 1
/* -----------------------------------------------------------------
*
* statics
*/
static ParserInterface *g_thisParser;
static const char * inputString;
static int inputPosition;
static QFile inputFile;
static int lastContext;
static int lastCContext;
static int lastDocContext;
static int lastCPPContext;
static int lastSkipSharpContext;
static int lastSkipRoundContext;
static int lastStringContext;
static int lastCurlyContext;
static int lastRoundContext;
static int lastSquareContext;
static int lastInitializerContext;
static int lastClassTemplSpecContext;
static int lastPreLineCtrlContext;
static int lastSkipVerbStringContext;
static int lastCommentInArgContext;
static int lastCSConstraint;
static Protection protection;
static Protection baseProt;
static int sharpCount = 0 ;
static int roundCount = 0 ;
static int curlyCount = 0 ;
static int squareCount = 0 ;
static int padCount = 0 ;
static QCString slString;
static Entry* current_root = 0 ;
static Entry* global_root = 0 ;
static Entry* current = 0 ;
static Entry* previous = 0 ;
static Entry* tempEntry = 0 ;
static Entry* firstTypedefEntry = 0 ;
static Entry* memspecEntry = 0 ;
static int yyLineNr = 1 ;
static int anonCount = 0 ;
static int anonNSCount = 0 ;
static QCString yyFileName;
static MethodTypes mtype;
static bool gstat;
static bool removeSlashes;
static Specifier virt;
static Specifier baseVirt;
static QCString msType,msName,msArgs;
static bool isTypedef;
static int tmpDocType;
static QCString sectionLabel;
static QCString sectionTitle;
static QCString funcPtrType;
static QCString templateStr;
static QCString aliasName;
static QCString baseName;
static QCString* specName;
static QCString formulaText;
static QCString formulaEnd;
static bool useOverrideCommands = FALSE;
static bool insideIDL = FALSE; //!< processing IDL code?
static bool insideJava = FALSE; //!< processing Java code?
static bool insideCS = FALSE; //!< processing C# code?
static bool insideD = FALSE; //!< processing D code?
static bool insidePHP = FALSE; //!< processing PHP code?
static bool insideObjC = FALSE; //!< processing Objective C code?
static bool insideCli = FALSE; //!< processing C++/CLI code?
static bool insideJS = FALSE; //!< processing JavaScript code?
static bool insideCppQuote = FALSE;
static bool insideProtocolList = FALSE;
static int argRoundCount;
static int argSharpCount;
static int currentArgumentContext;
static int lastCopyArgStringContext;
static int lastCopyArgContext;
static QCString *copyArgString;
static QCString fullArgString;
static ArgumentList *currentArgumentList;
static char lastCopyArgChar;
static QCString *pCopyQuotedString;
static QCString *pCopyRoundString;
static QCString *pCopyCurlyString;
static QGString *pCopyCurlyGString;
static QGString *pCopyRoundGString;
static QGString *pCopyQuotedGString;
static QGString *pSkipVerbString;
static QStack<Grouping> autoGroupStack;
static bool insideFormula;
static bool insideTryBlock=FALSE;
static bool insideCode;
static bool needsSemi;
static int depthIf;
static int initBracketCount;
static QCString memberGroupRelates;
static QCString memberGroupInside;
static QCString xrefItemKey;
static QCString xrefItemTitle;
static QCString xrefListTitle;
static QCString g_skipBlockName;
static QCString oldStyleArgType;
static QCString docBackup;
static QCString briefBackup;
static bool g_inputFromFile;
static int docBlockContext;
static QCString docBlock;
static QCString docBlockName;
static bool docBlockInBody;
static bool docBlockAutoBrief;
static char docBlockTerm;
static QCString idlAttr;
static QCString idlProp;
static bool g_lexInit = FALSE;
static bool externC;
//-----------------------------------------------------------------------------
// forward declarations
//static void handleGroupStartCommand(const char *header);
//static void handleGroupEndCommand();
//-----------------------------------------------------------------------------
static void initParser()
{
sectionLabel.resize(0);
sectionTitle.resize(0);
baseName.resize(0);
formulaText.resize(0);
protection = Public;
baseProt = Public;
sharpCount = 0;
roundCount = 0;
curlyCount = 0;
mtype = Method;
gstat = FALSE;
virt = Normal;
baseVirt = Normal;
isTypedef = FALSE;
autoGroupStack.clear();
insideTryBlock = FALSE;
autoGroupStack.setAutoDelete(TRUE);
insideFormula = FALSE;
insideCode=FALSE;
insideCli=Config_getBool("CPP_CLI_SUPPORT");
previous = 0;
}
static void initEntry()
{
if (insideJava)
{
protection = (current_root->spec & Entry::Interface) ? Public : Package;
}
current->protection = protection ;
current->mtype = mtype;
current->virt = virt;
current->stat = gstat;
current->objc = insideObjC;
//if (!autoGroupStack.isEmpty())
//{
// //printf("Appending group %s\n",autoGroupStack.top()->groupname.data());
// current->groups->append(new Grouping(*autoGroupStack.top()));
//}
initGroupInfo(current);
isTypedef=FALSE;
}
//-----------------------------------------------------------------------------
///// remove any automatic grouping and add new one (if given)
//static void setCurrentGroup( QCString *newgroup, Grouping::GroupPri_t pri )
//{
// /* remove auto group name from current entry and discard it */
// Grouping *g = current->groups->first();
// int i=0;
// while (g)
// {
// if (g->pri <= Grouping::GROUPING_AUTO_DEF)
// {
// current->groups->remove(i);
// i--;
// }
// g=current->groups->next();
// i++;
// }
//
// /* use new group name instead? */
// if ( newgroup )
// {
// current->groups->append(new Grouping(*newgroup, pri));
// }
//}
//
//static int newMemberGroupId()
//{
// static int curGroupId=0;
// return curGroupId++;
//}
//
// forward declarations
//static void startGroupInDoc();
//static void endGroup();
//-----------------------------------------------------------------------------
static void lineCount()
{
for( const char* c = yytext ; *c ; ++c )
yyLineNr += (*c == '\n') ;
}
static void addType( Entry* current )
{
uint tl=current->type.length();
if( tl>0 && !current->name.isEmpty() && current->type.at(tl-1)!='.')
{
current->type += ' ' ;
}
current->type += current->name ;
current->name.resize(0) ;
tl=current->type.length();
if( tl>0 && !current->args.isEmpty() && current->type.at(tl-1)!='.')
{
current->type += ' ' ;
}
current->type += current->args ;
current->args.resize(0) ;
current->argList->clear();
}
static QCString stripQuotes(const char *s)
{
QCString name;
if (s==0 || *s==0) return name;
name=s;
if (name.at(0)=='"' && name.at(name.length()-1)=='"')
{
name=name.mid(1,name.length()-2);
}
return name;
}
//-----------------------------------------------------------------
static void startCommentBlock(bool);
static void handleCommentBlock(const QCString &doc,bool brief);
static void handleParametersCommentBlocks(ArgumentList *al);
//-----------------------------------------------------------------
static bool nameIsOperator(QCString &name)
{
int i=name.find("operator");
if (i==-1) return FALSE;
if (i==0 && !isId(name.at(8))) return TRUE; // case operator ::X
if (i>0 && !isId(name.at(i-1)) && !isId(name.at(i+8))) return TRUE; // case X::operator
return FALSE; // case TEXToperatorTEXT
}
//-----------------------------------------------------------------------------
static void setContext()
{
QCString fileName = yyFileName;
SrcLangExt langExt = getLanguageFromFileName(fileName);
insideIDL = langExt==SrcLangExt_IDL;
insideJava = langExt==SrcLangExt_Java;
insideCS = langExt==SrcLangExt_CSharp;
insideD = langExt==SrcLangExt_D;
insidePHP = langExt==SrcLangExt_PHP;
insideObjC = langExt==SrcLangExt_ObjC;
insideJS = langExt==SrcLangExt_JS;
if ( insidePHP )
{
useOverrideCommands = TRUE;
}
//printf("setContext(%s) insideIDL=%d insideJava=%d insideCS=%d "
// "insideD=%d insidePHP=%d insideObjC=%d\n",
// yyFileName.data(),insideIDL,insideJava,insideCS,insideD,insidePHP,insideObjC
// );
}
//-----------------------------------------------------------------------------
static void prependScope()
{
if (current_root->section & Entry::SCOPE_MASK)
{
//printf("--- prependScope %s to %s\n",current_root->name.data(),current->name.data());
current->name.prepend(current_root->name+"::");
if (current_root->tArgLists)
{
if (current->tArgLists==0)
{
current->tArgLists = new QList<ArgumentList>;
current->tArgLists->setAutoDelete(TRUE);
}
//printf("prependScope #=%d #current=%d\n",current_root->tArgLists->count(),current->tArgLists->count());
QListIterator<ArgumentList> talsi(*current_root->tArgLists);
ArgumentList *srcAl=0;
for (talsi.toLast();(srcAl=talsi.current());--talsi)
{
ArgumentList *dstAl = new ArgumentList;
QListIterator<Argument> tali(*srcAl);
Argument *a;
for (;(a=tali.current());++tali)
{
dstAl->append(new Argument(*a));
//printf("appending argument %s %s\n",a->type.data(),a->name.data());
}
current->tArgLists->insert(0,dstAl);
}
}
}
}
//-----------------------------------------------------------------------------
/*! Returns TRUE iff the current entry could be a K&R style C function */
static bool checkForKnRstyleC()
{
if (((QCString)yyFileName).right(2).lower()!=".c") return FALSE; // must be a C file
if (!current->argList) return FALSE; // must have arguments
ArgumentListIterator ali(*current->argList);
Argument *a;
for (ali.toFirst();(a=ali.current());++ali)
{
// in K&R style argument do not have a type, but doxygen expects a type
// so it will think the argument has no name
if (a->type.isEmpty() || !a->name.isEmpty()) return FALSE;
}
return TRUE;
}
//-----------------------------------------------------------------------------
static void splitKnRArg(QCString &oldStyleArgPtr,QCString &oldStyleArgName)
{
int si = current->args.length();
if (oldStyleArgType.isEmpty()) // new argument
{
static QRegExp re("([^)]*)");
int bi1 = current->args.findRev(re);
int bi2 = bi1!=-1 ? current->args.findRev(re,bi1-1) : -1;
char c;
if (bi1!=-1 && bi2!=-1) // found something like "int (*func)(int arg)"
{
int s=bi2+1;
oldStyleArgType = current->args.left(s);
int i=s;
while (i<si && ((c=current->args.at(i))=='*' || isspace((uchar)c))) i++;
oldStyleArgType += current->args.mid(s,i-s);
s=i;
while (i<si && isId(current->args.at(i))) i++;
oldStyleArgName = current->args.mid(s,i-s);
oldStyleArgType+=current->args.mid(i);
}
else if (bi1!=-1) // redundant braces like in "int (*var)"
{
int s=bi1;
oldStyleArgType = current->args.left(s);
s++;
int i=s+1;
while (i<si && ((c=current->args.at(i))=='*' || isspace((uchar)c))) i++;
oldStyleArgType += current->args.mid(s,i-s);
s=i;
while (i<si && isId(current->args.at(i))) i++;
oldStyleArgName = current->args.mid(s,i-s);
}
else // normal "int *var"
{
int l=si,i=l-1,j;
char c;
// look for start of name in "type *name"
while (i>=0 && isId(current->args.at(i))) i--;
j=i+1;
// look for start of *'s
while (i>=0 && ((c=current->args.at(i))=='*' || isspace((uchar)c))) i--;
i++;
if (i!=l)
{
oldStyleArgType=current->args.left(i);
oldStyleArgPtr=current->args.mid(i,j-i);
oldStyleArgName=current->args.mid(j).stripWhiteSpace();
}
else
{
oldStyleArgName=current->args.copy().stripWhiteSpace();
}
}
}
else // continuation like *arg2 in "int *args,*arg2"
{
int l=si,j=0;
char c;
while (j<l && ((c=current->args.at(j))=='*' || isspace((uchar)c))) j++;
if (j>0)
{
oldStyleArgPtr=current->args.left(j);
oldStyleArgName=current->args.mid(j).stripWhiteSpace();
}
else
{
oldStyleArgName=current->args.copy().stripWhiteSpace();
}
}
//fprintf(stderr,"type=%s ptr=%s name=%s\n",oldStyleArgType.data(),oldStyleArgPtr.data(),oldStyleArgName.data());
}
//-----------------------------------------------------------------------------
/*! Update the argument \a name with additional \a type info. For K&R style
* function the type is found \e after the argument list, so this routine
* in needed to fix up.
*/
static void addKnRArgInfo(const QCString &type,const QCString &name,
const QCString &brief,const QCString &docs)
{
if (current->argList==0) return;
ArgumentListIterator ali(*current->argList);
Argument *a;
for (ali.toFirst();(a=ali.current());++ali)
{
if (a->type==name)
{
a->type=type.stripWhiteSpace();
if (a->type.left(9)=="register ") // strip keyword
{
a->type=a->type.mid(9);
}
a->name=name.stripWhiteSpace();
if (!brief.isEmpty() && !docs.isEmpty())
{
a->docs=brief+"\n\n"+docs;
}
else if (!brief.isEmpty())
{
a->docs=brief;
}
else
{
a->docs=docs;
}
}
}
}
//-----------------------------------------------------------------------------
void fixArgumentListForJavaScript(ArgumentList *al)
{
if (al==0) return;
ArgumentListIterator ali(*al);
Argument *a;
for (ali.toFirst();(a=ali.current());++ali)
{
if (!a->type.isEmpty() && a->name.isEmpty())
{ // a->type is actually the (typeless) parameter name, so move it
a->name=a->type;
a->type.resize(0);
}
}
}
/* ----------------------------------------------------------------- */
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
static int yyread(char *buf,int max_size)
{
int c=0;
if (g_inputFromFile)
{
c = inputFile.readBlock(buf,max_size);
if (c==-1) yy_fatal_error("input in flex scanner failed");
}
else
{
while( c < max_size && inputString[inputPosition] )
{
*buf = inputString[inputPosition++] ;
//printf("%d (%c)\n",*buf,*buf);
c++; buf++;
}
}
return c;
}
%}
/* start command character */
CMD ("\\"|"@")
SECTIONCMD {CMD}("image"|"author"|"internal"|"version"|"date"|"deprecated"|"param"|"exception"|"return"[s]?|"retval"|"bug"|"warning"|"par"|"sa"|"see"|"pre"|"post"|"invariant"|"note"|"remark"[s]?|"todo"|"test"|"xrefitem"|"ingroup"|"callgraph"|"callergraph"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"{"|"verbatim"|"dotfile"|"dot"|"defgroup"|"addtogroup"|"weakgroup"|"class"|"namespace"|"union"|"struct"|"fn"|"var"|"details"|"typedef"|"def"|"overload")|("<"{PRE}">")
BN [ \t\n\r]
BL [ \t\r]*"\n"
B [ \t]
BS ^(({B}*"//")?)(({B}*"*"+)?){B}*
FILESCHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+]
FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+]
FILE ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]+"\"")
ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
SCOPENAME "$"?(({ID}?{BN}*"::"{BN}*)*)(((~|!){BN}*)?{ID})
TSCOPE {ID}("<"[a-z_A-Z0-9 \t\*\&,]*">")?
FTSCOPE {ID}("<"[a-z_A-Z0-9\*\&,]*">")?
CSSCOPENAME (({ID}?{BN}*"."{BN}*)*)((~{BN}*)?{ID})
PRE [pP][rR][eE]
CODE [cC][oO][dD][eE]
CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^' \\\n]{1,4}"'"))
PHPKW ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
IDLATTR ("["[^\]]*"]"){BN}*
TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
%option noyywrap
/* language parsing states */
%x Define
%x DefineEnd
%x CompoundName
%x ClassVar
%x CSConstraintName
%x CSConstraintType
%x ClassCategory
%x ClassTemplSpec
%x CliPropertyType
%x CliPropertyIndex
%x CliOverride
%x Bases
%x BasesProt
%x NextSemi
%x BitFields
%x FindMembers
%x FindMembersPHP
%x FindMemberName
%x FindFields
%x FindFieldArg
%x Function
%x FuncRound
%x ExcpRound
%x ExcpList
%x FuncQual
%x Operator
%x Array
%x ReadBody
%x ReadNSBody
%x ReadBodyIntf
%x Using
%x UsingDirective
%x SkipCurly
%x SkipCurlyCpp
%x SkipCurlyEndDoc
%x SkipString
%x SkipPHPString
%x SkipInits
%x SkipCPP
%x SkipCPPBlock
%x SkipComment
%x SkipCxxComment
%x SkipCurlyBlock
%x SkipRoundBlock
%x Sharp
%x SkipSharp
%x SkipRound
%x SkipSquare
%x SkipRemainder
%x TypedefName
%x TryFunctionBlock
%x TryFunctionBlockEnd
%x Comment
%x PackageName
%x JavaImport
%x CSAccessorDecl
%x CSGeneric
%x PreLineCtrl
%x DefinePHP
%x DefinePHPEnd
%x OldStyleArgs
%x SkipVerbString
%x ObjCMethod
%x ObjCReturnType
%x ObjCParams
%x ObjCParamType
%x ObjCProtocolList
%x ObjCPropAttr
%x ObjCSkipStatement
%x QtPropType
%x QtPropName
%x QtPropAttr
%x QtPropRead
%x QtPropWrite
%x ReadInitializer
%x GetCallType
%x CppQuote
%x EndCppQuote
%x MemberSpec
%x MemberSpecSkip
%x EndTemplate
%x FuncPtr
%x FuncPtrOperator
%x EndFuncPtr
%x ReadFuncArgType
%x ReadTempArgs
%x IDLUnionCase
%x NSAliasName
%x NSAliasArg
%x CopyString
%x CopyPHPString
%x CopyGString
%x CopyPHPGString
%x CopyRound
%x CopyCurly
%x GCopyRound
%x GCopyCurly
%x SkipUnionSwitch
%x Specialization
%x FuncPtrInit
%x FuncFunc
%x FuncFuncEnd
%x FuncFuncType
%x FuncFuncArray
%x CopyArgString
%x CopyArgPHPString
%x CopyArgRound
%x CopyArgSharp
%x CopyArgComment
%x CopyArgCommentLine
%x CopyArgVerbatim
%x IDLAttribute
%x IDLProp
%x IDLPropName
/** Prototype scanner states */
%x Prototype
%x PrototypePtr
%x PrototypeQual
%x PrototypeExc
%x PrototypeSkipLine
/** comment parsing states */
%x DocLine
%x DocBlock
%x DocCopyBlock
%%
<NextSemi>"{" {
curlyCount=0;
needsSemi = TRUE;
BEGIN(SkipCurlyBlock);
}
<NextSemi>"(" {
roundCount=0;
BEGIN(SkipRoundBlock);
}
<SkipRoundBlock>"(" {
++roundCount;
}
<SkipRoundBlock>")" {
if (roundCount )
--roundCount ;
else
BEGIN( NextSemi ) ;
}
<SkipCurlyBlock>"{" {
++curlyCount ;
}
<SkipCurlyBlock>"}" {
if( curlyCount )
{
--curlyCount ;
}
else if (needsSemi)
{
BEGIN( NextSemi );
}
else
{
BEGIN( FindMembers );
}
}
<NextSemi>\' {
if (insidePHP)
{
lastStringContext=NextSemi;
BEGIN(SkipPHPString);
}
}
<NextSemi>{CHARLIT} { if (insidePHP) REJECT; }
<NextSemi>\" {
lastStringContext=NextSemi;
BEGIN(SkipString);
}
<NextSemi>[;,] {
unput(*yytext);
BEGIN( FindMembers );
}
<BitFields>[;,] {
unput(*yytext);
BEGIN( FindMembers );
}
<FindMembers>"<?php" { // PHP code with unsupported extension?
insidePHP = TRUE;
}
<FindMembersPHP>"<?"("php"?) { // PHP code start
BEGIN( FindMembers );
}
<FindMembersPHP>"<script"{BN}+"language"{BN}*"="{BN}*['"]?"php"['"]?{BN}*">" { // PHP code start
lineCount() ;
BEGIN( FindMembers );
}
<FindMembersPHP>[^\n<]+ { // Non-PHP code text, ignore
}
<FindMembersPHP>\n { // Non-PHP code text, ignore
yyLineNr++;
}
<FindMembersPHP>. { // Non-PHP code text, ignore
}
<FindMembers>"?>"|"</script>" { // PHP code end
if (insidePHP)
BEGIN( FindMembersPHP );
else
REJECT;
}
<FindMembers>{PHPKW} { if (insidePHP)
BEGIN( NextSemi );
else
REJECT;
}
<FindMembers>"%{"[^\n]* { // Mozilla XPIDL lang-specific block
if (!insideIDL)
REJECT;
}
<FindMembers>"%}" { // Mozilla XPIDL lang-specific block end
if (!insideIDL)
REJECT;
}
<FindMembers>{B}*("properties"){BN}*":"{BN}* { // IDL or Borland C++ builder property
current->mtype = mtype = Property;
current->protection = protection = Public ;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
lineCount() ;
}
<FindMembers>{B}*"k_dcop"{BN}*":"{BN}* { current->mtype = mtype = DCOP;
current->protection = protection = Public ;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
lineCount() ;
}
<FindMembers>{B}*("signals"|"Q_SIGNALS"){BN}*":"{BN}* { current->mtype = mtype = Signal;
current->protection = protection = Public ;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
lineCount() ;
}
<FindMembers>{B}*"public"{BN}*("slots"|"Q_SLOTS"){BN}*":"{BN}* {
current->protection = protection = Public ;
current->mtype = mtype = Slot;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
lineCount();
}
<FindMembers>{B}*"protected"{BN}*("slots"|"Q_SLOTS"){BN}*":"{BN}* {
current->protection = protection = Protected ;
current->mtype = mtype = Slot;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
lineCount();
}
<FindMembers>{B}*"private"{BN}*("slots"|"Q_SLOTS"){BN}*":"{BN}* {
current->protection = protection = Private ;
current->mtype = mtype = Slot;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
lineCount();
}
<FindMembers>{B}*("public"|"methods"|"__published"){BN}*":"{BN}* {
current->protection = protection = Public ;
current->mtype = mtype = Method;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
lineCount() ;
}
<FindMembers>{B}*"internal"{BN}*":"{BN}* { // for now treat C++/CLI's internal as package...
if (insideCli)
{
current->protection = protection = Package ;
current->mtype = mtype = Method;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
lineCount() ;
}
else
{
REJECT;
}
}
<FindMembers>{B}*"protected"{BN}*":"{BN}* {
current->protection = protection = Protected ;
current->mtype = mtype = Method;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
lineCount() ;
}
<FindMembers>{B}*"private"{BN}*":"{BN}* {
current->protection = protection = Private ;
current->mtype = mtype = Method;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
lineCount() ;
}
<FindMembers>{B}*"event"{BN}+ {
if (insideCli)
{
// C++/CLI event
lineCount() ;
current->mtype = mtype = Event;
current->bodyLine = yyLineNr;
curlyCount=0;
BEGIN( CliPropertyType );
}
else if (insideCS)
{
lineCount() ;
current->mtype = Event;
current->bodyLine = yyLineNr;
}
else
{
REJECT;
}
}
<FindMembers>{B}*"property"{BN}+ {
if (insideCli)
{
// C++/CLI property
lineCount() ;
current->mtype = mtype = Property;
current->bodyLine = yyLineNr;
curlyCount=0;
BEGIN( CliPropertyType );
}
else
{
REJECT;
}
}
<CliPropertyType>{ID} {
addType( current );
current->name = yytext;
}
<CliPropertyType>"[" { // C++/CLI indexed property
current->name += yytext;
BEGIN( CliPropertyIndex );
}
<CliPropertyType>"{" {
curlyCount=0;
//printf("event: '%s' '%s'\n",current->type.data(),current->name.data());
BEGIN( CSAccessorDecl );
}
<CliPropertyType>";" {
unput(*yytext);
BEGIN( FindMembers );
}
<CliPropertyType>\n {
yyLineNr++;
}
<CliPropertyType>{B}* {
}
<CliPropertyType>. {
addType( current );
current->type += yytext;
}
<CliPropertyIndex>"]" {
BEGIN( CliPropertyType );
current->name+=yytext;
}
<CliPropertyIndex>. {
current->name+=yytext;
}
<FindMembers>{B}*"property"{BN}+ {
if (!current->type.isEmpty())
{
REJECT;
}
else
{
current->mtype = mtype = Property;
lineCount();
}
}
<FindMembers>{B}*"@private"{BN}+ {
current->protection = protection = Private ;
current->mtype = mtype = Method;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
lineCount() ;
}
<FindMembers>{B}*"@protected"{BN}+ {
current->protection = protection = Protected ;
current->mtype = mtype = Method;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
lineCount() ;
}
<FindMembers>{B}*"@public"{BN}+ {
current->protection = protection = Public ;
current->mtype = mtype = Method;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
lineCount() ;
}
<FindMembers>[\-+]{BN}* {
if (!insideObjC)
{
REJECT;
}
else
{
lineCount();
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
current->section = Entry::FUNCTION_SEC;
current->protection = protection = Public ;
current->objc = TRUE;
current->virt = Virtual;
current->stat=yytext[0]=='+';
current->mtype = mtype = Method;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
BEGIN( ObjCMethod );
}
}
<ObjCMethod>"(" { // start of method's return type
BEGIN( ObjCReturnType );
}
<ObjCMethod>{ID} { // found method name
if (current->type.isEmpty())
{
current->type = "id";
}
current->name = yytext;
}
<ObjCMethod>":"{B}* { // start of parameter list
current->name += ':';
Argument *a = new Argument;
current->argList->append(a);
BEGIN( ObjCParams );
}
<ObjCReturnType>[^)]* { // TODO: check if nested braches are possible.
current->type = yytext;
}
<ObjCReturnType>")" {
BEGIN( ObjCMethod );
}
<ObjCParams>({ID})?":" { // Keyword of parameter
QCString keyw = yytext;
keyw=keyw.left(keyw.length()-1); // strip :
if (keyw.isEmpty())
{
current->name += " :";
}
else
{
current->name += keyw+":";
}
if (current->argList->getLast()->type.isEmpty())
{
current->argList->getLast()->type="id";
}
Argument *a = new Argument;
a->attrib=(QCString)"["+keyw+"]";
current->argList->append(a);
}
<ObjCParams>{ID}{BN}* { // name of parameter
lineCount();
current->argList->getLast()->name=QCString(yytext).stripWhiteSpace();
}
<ObjCParams>","{BN}*"..." { // name of parameter
lineCount();
// do we want the comma as part of the name?
//current->name += ",";
Argument *a = new Argument;
a->attrib="[,]";
a->type="...";
current->argList->append(a);
}
/*
<ObjCParams>":" {
current->name += ':';
}
*/
<ObjCParams>"(" {
BEGIN( ObjCParamType );
}
<ObjCParamType>[^)]* {
current->argList->getLast()->type=QCString(yytext).stripWhiteSpace();
}
<ObjCParamType>")"/{B}* {
BEGIN( ObjCParams );
}
<ObjCMethod,ObjCParams>";" { // end of method declaration
if (current->argList->getLast() && current->argList->getLast()->type.isEmpty())
{
current->argList->getLast()->type="id";
}
current->args = argListToString(current->argList);
//printf("argList=%s\n",current->args.data());
unput(';');
BEGIN( Function );
}
<ObjCMethod,ObjCParams>(";"{BN}+)?"{" { // start of a method body
lineCount();
//printf("Type=%s Name=%s args=%s\n",
// current->type.data(),current->name.data(),argListToString(current->argList).data()
// );
if (current->argList->getLast() && current->argList->getLast()->type.isEmpty())
{
current->argList->getLast()->type="id";
}
current->args = argListToString(current->argList);
unput('{');
BEGIN( Function );
}
<FindMembers>{BN}{1,80} {
lineCount();
}
<FindMembers>"@"({ID}".")*{ID}{BN}*"(" {
if (insideJava) // Java annotation
{
lineCount();
lastSkipRoundContext = YY_START;
roundCount=1;
BEGIN( SkipRound );
}
else if (strncmp(yytext,"@property",9)==0) // ObjC 2.0 property
{
current->mtype = mtype = Property;
current->spec|=Entry::Readable | Entry::Writable | Entry::Assign;
current->protection = Public ;
unput('(');
BEGIN( ObjCPropAttr );
}
else
{
REJECT;
}
}
<ObjCPropAttr>"getter="{ID} {
current->read = yytext+7;
}
<ObjCPropAttr>"setter="{ID} {
current->write = yytext+7;
}
<ObjCPropAttr>"readonly" {
current->spec&=~Entry::Writable;
}
<ObjCPropAttr>"readwrite" { // default
}
<ObjCPropAttr>"assign" { // default
}
<ObjCPropAttr>"retain" {
current->spec&=~Entry::Assign;
current->spec|=Entry::Retain;
}
<ObjCPropAttr>"copy" {
current->spec&=~Entry::Assign;
current->spec|=Entry::Copy;
}
<ObjCPropAttr>"nonatmic" {
current->spec|=Entry::NonAtomic;
}
<ObjCPropAttr>")" {
BEGIN(FindMembers);
}
<FindMembers>"@"{ID} {
if (insideJava) // Java annotation
{
// skip annotation
}
else if (strcmp(yytext,"@property")==0) // ObjC 2.0 property
{
current->mtype = mtype = Property;
current->spec|=Entry::Writable | Entry::Readable | Entry::Assign;
current->protection = Public ;
}
else if (strcmp(yytext,"@synthesize")==0)
{
BEGIN( ObjCSkipStatement );
}
else if (strcmp(yytext,"@dynamic")==0)
{
BEGIN( ObjCSkipStatement );
}
else
{
REJECT;
}
}
<ObjCSkipStatement>";" {
BEGIN(FindMembers);
}
<PackageName>{ID}("."{ID})* {
isTypedef=FALSE;
current->name = yytext;
current->name = substitute(current->name,".","::");
current->section = Entry::NAMESPACE_SEC;
current->type = "namespace" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
lineCount();
curlyCount=0;
current_root->addSubEntry(current);
current_root = current ;
current = new Entry ;
initEntry();
BEGIN( FindMembers ) ;
}
<PackageName>";" {
BEGIN(FindMembers);
}
<FindMembers>{B}*"initonly"{BN}+ {
current->type += " initonly ";
if (insideCli) current->spec |= Entry::Initonly;
lineCount();
}
<FindMembers>{B}*"static"{BN}+ { current->type += " static ";
current->stat = TRUE;
lineCount();
}
<FindMembers>{B}*"extern"{BN}+ {
current->stat = FALSE;
current->explicitExternal = TRUE;
lineCount();
}
<FindMembers>{B}*"virtual"{BN}+ { current->type += " virtual ";
current->virt = Virtual;
lineCount();
}
<FindMembers>{B}*"abstract"{BN}+ {
if (!insidePHP)
{
current->type += " abstract ";
current->virt = Pure;
}
else
{
current->spec|=Entry::Abstract;
}
lineCount();
}
<FindMembers>{B}*"inline"{BN}+ { current->spec|=Entry::Inline;
lineCount();
}
<FindMembers>{B}*"mutable"{BN}+ { current->spec|=Entry::Mutable;
lineCount();
}
<FindMembers>{B}*"explicit"{BN}+ { current->spec|=Entry::Explicit;
lineCount();
}
<FindMembers>{B}*"@required"{BN}+ { // Objective C 2.0 protocol required section
current->spec=(current->spec & ~Entry::Optional) | Entry::Required;
lineCount();
}
<FindMembers>{B}*"@optional"{BN}+ { // Objective C 2.0 protocol optional section
current->spec=(current->spec & ~Entry::Required) | Entry::Optional;
lineCount();
}
/*
<FindMembers>{B}*"import"{BN}+ { // IDL import keyword
BEGIN( NextSemi );
}
*/
<FindMembers>{B}*"typename"{BN}+ { lineCount(); }
<FindMembers>{B}*"namespace"{BN}*/[^a-z_A-Z0-9] {
isTypedef=FALSE;
current->section = Entry::NAMESPACE_SEC;
current->type = "namespace" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
lineCount();
BEGIN( CompoundName );
}
<FindMembers>{B}*"module"{BN}+ {
lineCount();
if (insideIDL)
{
isTypedef=FALSE;
current->section = Entry::NAMESPACE_SEC;
current->type = "module" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
BEGIN( CompoundName );
}
else if (insideD)
{
lineCount();
BEGIN(PackageName);
}
else
{
addType( current ) ;
current->name = QCString(yytext).stripWhiteSpace();
}
}
<FindMembers>{B}*"library"{BN}+ {
lineCount();
if (insideIDL)
{
isTypedef=FALSE;
current->section = Entry::NAMESPACE_SEC;
current->type = "library" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
BEGIN( CompoundName );
}
else
{
addType( current ) ;
current->name = QCString(yytext).stripWhiteSpace();
}
}
<FindMembers>{B}*((("disp")?"interface")|"valuetype"){BN}+ { // M$/Corba IDL/Java interface
lineCount();
if (insideIDL || insideJava || insideCS || insideD || insidePHP)
{
isTypedef=FALSE;
current->section = Entry::CLASS_SEC;
current->spec = Entry::Interface;
addType( current ) ;
current->type += " interface" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
BEGIN( CompoundName );
}
else
{
addType( current ) ;
current->name = QCString(yytext).stripWhiteSpace();
}
}
<FindMembers>{B}*"@implementation"{BN}+ { // Objective-C class implementation
lineCount();
isTypedef=FALSE;
current->section = Entry::OBJCIMPL_SEC;
current->objc = insideObjC = TRUE;
current->protection = protection = Public ;
addType( current ) ;
current->type += " implementation" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
BEGIN( CompoundName );
}
<FindMembers>{B}*"@interface"{BN}+ { // Objective-C class interface, or Java attribute
lineCount();
isTypedef=FALSE;
current->section = Entry::CLASS_SEC;
current->spec = Entry::Interface;
current->objc = insideObjC = !insideJava;
current->protection = protection = Public ;
addType( current ) ;
current->type += " interface" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
BEGIN( CompoundName );
}
<FindMembers>{B}*"@protocol"{BN}+ { // Objective-C protocol definition
lineCount();
isTypedef=FALSE;
current->section = Entry::CLASS_SEC;
current->spec = Entry::Protocol;
current->objc = insideObjC = TRUE;
current->protection = protection = Public ;
addType( current ) ;
current->type += " protocol" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
BEGIN( CompoundName );
}
<FindMembers>{B}*"exception"{BN}+ { // Corba IDL exception
isTypedef=FALSE;
current->section = Entry::CLASS_SEC;
current->spec = Entry::Exception;
addType( current ) ;
current->type += " exception" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
lineCount();
BEGIN( CompoundName );
}
<FindMembers>"@class" | // for Objective C class declarations
<FindMembers>{B}*{TYPEDEFPREFIX}"class{" |
<FindMembers>{B}*{TYPEDEFPREFIX}"class"{BN}+ {
isTypedef=((QCString)yytext).find("typedef")!=-1;
current->section = Entry::CLASS_SEC;
addType( current ) ;
current->type += " class" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
current->objc = insideObjC = yytext[0]=='@';
lineCount() ;
if (yytext[yyleng-1]=='{') unput('{');
if (insidePHP && current->spec&Entry::Abstract)
{
// convert Abstract to AbstractClass
current->spec=(current->spec&~Entry::Abstract)|Entry::AbstractClass;
}
BEGIN( CompoundName ) ;
}
<FindMembers>{B}*"value class{" | // C++/CLI extension
<FindMembers>{B}*"value class"{BN}+ {
isTypedef=FALSE;
current->section = Entry::CLASS_SEC;
current->spec = Entry::Value;
addType( current ) ;
current->type += " value class" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
lineCount() ;
if (yytext[yyleng-1]=='{') unput('{');
BEGIN( CompoundName ) ;
}
<FindMembers>{B}*"ref class{" | // C++/CLI extension
<FindMembers>{B}*"ref class"{BN}+ {
isTypedef=FALSE;
current->section = Entry::CLASS_SEC;
current->spec = Entry::Ref;
addType( current ) ;
current->type += " ref class" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
lineCount() ;
if (yytext[yyleng-1]=='{') unput('{');
BEGIN( CompoundName ) ;
}
<FindMembers>{B}*"interface class{" | // C++/CLI extension
<FindMembers>{B}*"interface class"{BN}+ {
isTypedef=FALSE;
current->section = Entry::CLASS_SEC;
current->spec = Entry::Interface;
addType( current ) ;
current->type += " interface class" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
lineCount() ;
if (yytext[yyleng-1]=='{') unput('{');
BEGIN( CompoundName ) ;
}
<FindMembers>{B}*"coclass"{BN}+ {
if (insideIDL)
{
isTypedef=FALSE;
current->section = Entry::CLASS_SEC;
addType( current ) ;
current->type += " coclass" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
lineCount() ;
BEGIN( CompoundName ) ;
}
else
{
addType(current);
current->name = yytext;
current->name = current->name.stripWhiteSpace();
lineCount();
}
}
<FindMembers>{B}*{TYPEDEFPREFIX}"struct{" |
<FindMembers>{B}*{TYPEDEFPREFIX}"struct"/{BN}+ {
isTypedef=((QCString)yytext).find("typedef")!=-1;
current->section = Entry::CLASS_SEC ;
current->spec = Entry::Struct;
// bug 582676: can be a struct nested in an interface so keep insideObjC state
//current->objc = insideObjC = FALSE;
addType( current ) ;
current->type += " struct" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
lineCount() ;
if (yytext[yyleng-1]=='{') unput('{');
BEGIN( CompoundName ) ;
}
<FindMembers>{B}*"value struct{" | // C++/CLI extension
<FindMembers>{B}*"value struct"{BN}+ {
isTypedef=FALSE;
current->section = Entry::CLASS_SEC;
current->spec = Entry::Struct | Entry::Value;
addType( current ) ;
current->type += " value struct" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
lineCount() ;
if (yytext[yyleng-1]=='{') unput('{');
BEGIN( CompoundName ) ;
}
<FindMembers>{B}*"ref struct{" | // C++/CLI extension
<FindMembers>{B}*"ref struct"{BN}+ {
isTypedef=FALSE;
current->section = Entry::CLASS_SEC;
current->spec = Entry::Struct | Entry::Ref;
addType( current ) ;
current->type += " ref struct" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
lineCount() ;
if (yytext[yyleng-1]=='{') unput('{');
BEGIN( CompoundName ) ;
}
<FindMembers>{B}*"interface struct{" | // C++/CLI extension
<FindMembers>{B}*"interface struct"{BN}+ {
isTypedef=FALSE;
current->section = Entry::CLASS_SEC;
current->spec = Entry::Struct | Entry::Interface;
addType( current ) ;
current->type += " interface struct";
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
lineCount() ;
if (yytext[yyleng-1]=='{') unput('{');
BEGIN( CompoundName ) ;
}
<FindMembers>{B}*{TYPEDEFPREFIX}"union{" |
<FindMembers>{B}*{TYPEDEFPREFIX}"union"{BN}+ {
isTypedef=((QCString)yytext).find("typedef")!=-1;
current->section = Entry::CLASS_SEC;
current->spec = Entry::Union;
// bug 582676: can be a struct nested in an interface so keep insideObjC state
//current->objc = insideObjC = FALSE;
addType( current ) ;
current->type += " union" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
lineCount() ;
if (yytext[yyleng-1]=='{') unput('{');
BEGIN( CompoundName ) ;
}
<FindMembers>{B}*{TYPEDEFPREFIX}{IDLATTR}?"enum"({BN}+("class"|"struct"))?"{" |
<FindMembers>{B}*{TYPEDEFPREFIX}{IDLATTR}?"enum"({BN}+("class"|"struct"))?{BN}+ { // for IDL: typedef [something] enum
isTypedef=((QCString)yytext).find("typedef")!=-1;
current->section = Entry::ENUM_SEC ;
addType( current ) ;
current->type += " enum" ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->bodyLine = yyLineNr;
lineCount() ;
if (yytext[yyleng-1]=='{') unput('{');
BEGIN( CompoundName ) ;
}
<Operator>"("{BN}*")"({BN}*"<"[^>]*">"){BN}*/"(" { // A::operator()<int>(int arg)
lineCount();
current->name += "()";
BEGIN( FindMembers );
}
<Operator>"("{BN}*")"{BN}*/"(" {
lineCount();
current->name += yytext ;
current->name = current->name.simplifyWhiteSpace();
BEGIN( FindMembers ) ;
}
<Operator>";" { // can occur when importing members
unput(';');
BEGIN( FindMembers ) ;
}
<Operator>[^(] {
lineCount();
current->name += *yytext ;
}
<Operator>"<>" { /* skip guided templ specifiers */ }
<Operator>"(" {
current->name = current->name.simplifyWhiteSpace();
unput(*yytext);
BEGIN( FindMembers ) ;
}
<FindMembers>("template"|"generic")({BN}*)"<"/[>]? { // generic is a C++/CLI extension
lineCount();
if (current->tArgLists==0)
{
current->tArgLists = new QList<ArgumentList>;
current->tArgLists->setAutoDelete(TRUE);
}
ArgumentList *al = new ArgumentList;
current->spec |= (yytext[0]=='g') ? Entry::Generic : Entry::Template;
current->tArgLists->append(al);
currentArgumentList = al;
templateStr="<";
fullArgString = templateStr;
copyArgString = &templateStr;
currentArgumentContext = FindMembers;
BEGIN( ReadTempArgs );
}
<FindMembers>"namespace"{BN}+/{ID}{BN}*"=" { // namespace alias
lineCount();
BEGIN( NSAliasName );
}
<NSAliasName>{ID} {
aliasName = yytext;
BEGIN( NSAliasArg );
}
<NSAliasArg>({ID}"::")*{ID} {
//printf("Inserting namespace alias %s::%s->%s\n",current_root->name.data(),aliasName.data(),yytext);
//if (current_root->name.isEmpty())
//{
// TODO: namespace aliases are now treated as global entities
// while they should be aware of the scope they are in
Doxygen::namespaceAliasDict.insert(aliasName,new QCString(yytext));
//}
//else
//{
// Doxygen::namespaceAliasDict.insert(current_root->name+"::"+aliasName,
// new QCString(current_root->name+"::"+yytext));
//}
}
<NSAliasArg>";" {
BEGIN( FindMembers );
}
<JavaImport>({ID}{BN}*"."{BN}*)+"*" { // package import => add as a using directive
lineCount();
QCString scope=yytext;
current->name=removeRedundantWhiteSpace(substitute(scope.left(scope.length()-2),".","::"));
current->fileName = yyFileName;
current->section=Entry::USINGDIR_SEC;
current_root->addSubEntry(current);
current = new Entry ;
initEntry();
BEGIN(Using);
}
<JavaImport>({ID}{BN}*"."{BN}*)+{ID} { // class import => add as a using declaration
lineCount();
QCString scope=yytext;
current->name=removeRedundantWhiteSpace(substitute(scope,".","::"));
current->fileName = yyFileName;
if (insideD)
{
current->section=Entry::USINGDIR_SEC;
}
else
{
//printf("import name = %s -> %s\n",yytext,current->name.data());
current->section=Entry::USINGDECL_SEC;
}
current_root->addSubEntry(current);
current = new Entry ;
initEntry();
BEGIN(Using);
}
<FindMembers>"using"{BN}+ {
current->startLine=yyLineNr;
lineCount();
BEGIN(Using);
}
<Using>"namespace"{BN}+ { lineCount(); BEGIN(UsingDirective); }
<Using>{ID}{BN}*({BN}*("::"|"."){BN}*{ID})* {
lineCount();
current->name=yytext;
current->fileName = yyFileName;
current->section=Entry::USINGDECL_SEC;
current_root->addSubEntry(current);
current = new Entry ;
if (insideCS) /* Hack: in C# a using declaration and
directive have the same syntax, so we
also add it as a using directive here
*/
{
current->name=yytext;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->section=Entry::USINGDIR_SEC;
current_root->addSubEntry(current);
current = new Entry ;
}
initEntry();
BEGIN(Using);
}
<UsingDirective>{SCOPENAME} { current->name=removeRedundantWhiteSpace(yytext);
current->fileName = yyFileName;
current->section=Entry::USINGDIR_SEC;
current_root->addSubEntry(current);
current = new Entry ;
initEntry();
BEGIN(Using);
}
<Using>";" { BEGIN(FindMembers); }
<FindMembers>{SCOPENAME}{BN}*"<>" { // guided template decl
QCString n=yytext;
addType( current );
current->name=n.left(n.length()-2);
}
<FindMembers>{SCOPENAME}{BN}*/"<" { // Note: this could be a return type!
sharpCount=0;
lineCount();
addType( current );
current->name=yytext;
current->name=current->name.stripWhiteSpace();
//current->scopeSpec.resize(0);
// currentTemplateSpec = ¤t->scopeSpec;
if (nameIsOperator(current->name))
BEGIN( Operator );
else
BEGIN( EndTemplate );
}
<FindMemberName>{SCOPENAME}{BN}*/"<" {
sharpCount=0;
roundCount=0;
lineCount();
current->name+=((QCString)yytext).stripWhiteSpace();
//current->memberSpec.resize(0);
// currentTemplateSpec = ¤t->memberSpec;
if (nameIsOperator(current->name))
BEGIN( Operator );
else
BEGIN( EndTemplate );
}
<ClassTemplSpec,EndTemplate>"<<" {
current->name+=yytext;
// *currentTemplateSpec+=yytext;
}
<EndTemplate>"<" {
current->name+='<';
// *currentTemplateSpec+='<';
sharpCount++;
}
<ClassTemplSpec,EndTemplate>">>" {
if (insideJava || insideCS || insideCli || roundCount==0)
{
unput('>');
unput(' ');
unput('>');
}
else
{
current->name+=yytext;
}
// *currentTemplateSpec+=yytext;
}
<EndTemplate>">" {
current->name+='>';
// *currentTemplateSpec+='>';
if (--sharpCount<=0)
{
//printf("Found %s\n",current->name.data());
BEGIN(FindMembers);
}
}
<EndTemplate>">"{BN}*"(" {
lineCount();
current->name+='>';
// *currentTemplateSpec+='>';
if (--sharpCount<=0)
{
current->args = "(";
currentArgumentContext = FuncQual;
fullArgString = current->args.copy();
copyArgString = ¤t->args;
//printf("Found %s\n",current->name.data());
BEGIN( ReadFuncArgType ) ;
}
}
<EndTemplate>">"{BN}*/"("({BN}*{ID}{BN}*"::")*({BN}*"*"{BN}*)+ { // function pointer returning a template instance
lineCount();
current->name+='>';
BEGIN(FindMembers);
}
<EndTemplate>">"{BN}*/"::" {
lineCount();
current->name+='>';
// *currentTemplateSpec+='>';
if (--sharpCount<=0)
{
BEGIN(FindMemberName);
}
}
<ClassTemplSpec,EndTemplate>"(" { current->name+=*yytext;
roundCount++;
}
<ClassTemplSpec,EndTemplate>")" { current->name+=*yytext;
if (roundCount>0) roundCount--;
}
<EndTemplate>. {
current->name+=*yytext;
// *currentTemplateSpec+=*yytext;
}
<FindMembers>"define"{BN}*"("{BN}*["'] {
if (insidePHP)
{
current->bodyLine = yyLineNr;
BEGIN( DefinePHP );
}
else
REJECT;
}
<FindMembers>"Q_OBJECT" { // Qt object macro
}
<FindMembers>"Q_PROPERTY" { // Qt property declaration
current->protection = protection = Public ;
current->mtype = mtype = Property;
current->type.resize(0);
BEGIN(QtPropType);
}
<QtPropType>"(" { // start of property arguments
}
<QtPropAttr>")" { // end of property arguments
unput(';');
BEGIN(FindMembers);
}
<QtPropType>"const"|"volatile" {
current->type+=yytext;
}
<QtPropType>{B}+ {
current->type+=yytext;
}
<QtPropType>({FTSCOPE}"::")*{FTSCOPE} {
current->type+=yytext;
BEGIN(QtPropName);
}
<QtPropName>{ID} {
current->name=yytext;
BEGIN(QtPropAttr);
}
<QtPropAttr>"READ" {
current->spec |= Entry::Readable;
BEGIN(QtPropRead);
}
<QtPropAttr>"WRITE" {
current->spec |= Entry::Writable;
BEGIN(QtPropWrite);
}
<QtPropAttr>"RESET"{B}+{ID} { // reset method => not supported yet
}
<QtPropAttr>"SCRIPTABLE"{B}+{ID} { // scriptable property => not supported yet
}
<QtPropAttr>"DESIGNABLE"{B}+{ID} { // designable property => not supported yet
}
<QtPropRead>{ID} {
current->read = yytext;
BEGIN(QtPropAttr);
}
<QtPropWrite>{ID} {
current->write = yytext;
BEGIN(QtPropAttr);
}
<FindMembers>"friend"{BN}+("class"|"union"|"struct"){BN}+ {
current->name=yytext;
BEGIN(FindMembers);
}
<FindMembers,FindMemberName>{SCOPENAME} {
lineCount();
if (insideIDL && yyleng==9 && strcmp(yytext,"cpp_quote")==0)
{
BEGIN(CppQuote);
}
else if ((insideIDL || insideJava || insideD) && yyleng==6 && strcmp(yytext,"import")==0)
{
if (insideIDL)
BEGIN(NextSemi);
else // insideJava or insideD
BEGIN(JavaImport);
}
else if (insideJava && strcmp(yytext,"package")==0)
{
lineCount();
BEGIN(PackageName);
}
else if (insideIDL && strcmp(yytext,"case")==0)
{
BEGIN(IDLUnionCase);
}
else if (insideTryBlock && strcmp(yytext,"catch")==0)
{
insideTryBlock=FALSE;
BEGIN(TryFunctionBlock);
}
else if (insideJS && strcmp(yytext,"var")==0)
{ // javascript variable
current->type="var";
}
else if (insideJS && strcmp(yytext,"function")==0)
{ // javascript function
current->type="function";
}
else
{
if (YY_START==FindMembers)
{
addType( current ) ;
}
bool javaLike = insideJava || insideCS || insideD || insidePHP || insideJS;
if (javaLike && strcmp(yytext,"public")==0)
{
current->protection = Public;
}
else if (javaLike && strcmp(yytext,"protected")==0)
{
current->protection = Protected;
}
else if (javaLike && strcmp(yytext,"private")==0)
{
current->protection = Private;
}
else if (javaLike && strcmp(yytext,"static")==0)
{
if (YY_START==FindMembers)
current->name = yytext;
else
current->name += yytext;
current->stat = TRUE;
}
else
{
if (YY_START==FindMembers)
current->name = yytext;
else
current->name += yytext;
if (current->name.left(7)=="static ")
{
current->stat = TRUE;
current->name= current->name.mid(7);
}
else if (current->name.left(7)=="inline ")
{
if (current->type.isEmpty())
{
current->type="inline";
}
else
{
current->type+="inline ";
}
current->name= current->name.mid(7);
}
else if (current->name.left(6)=="const ")
{
if (current->type.isEmpty())
{
current->type="const";
}
else
{
current->type+="const ";
}
current->name=current->name.mid(6);
}
}
QCString tmp=yytext;
if (nameIsOperator(tmp))
{
BEGIN( Operator );
}
else
{
BEGIN(FindMembers);
}
}
}
<FindMembers>[0-9]{ID} { // some number where we did not expect one
}
<FindMembers>"." {
if (insideJava || insideCS || insideD)
{
current->name+=".";
}
}
<FindMembers>"::" {
current->name+=yytext;
}
<CppQuote>"("{B}*"\"" {
insideCppQuote=TRUE;
BEGIN(FindMembers);
}
<IDLUnionCase>"::"
<IDLUnionCase>":" { BEGIN(FindMembers); }
<IDLUnionCase>\n { yyLineNr++; }
<IDLUnionCase>.
<TryFunctionBlock>\n { yyLineNr++; }
<TryFunctionBlock>"{" {
curlyCount=0;
lastCurlyContext = TryFunctionBlockEnd ;
BEGIN( SkipCurly );
}
<TryFunctionBlock>.
<TryFunctionBlockEnd>"catch" { BEGIN(TryFunctionBlock); }
<TryFunctionBlockEnd>\n { unput(*yytext); // added to fix bug id 601138
BEGIN( FindMembers );
}
<TryFunctionBlockEnd>. { unput(*yytext);
BEGIN( FindMembers );
}
<EndCppQuote>")" {
insideCppQuote=FALSE;
BEGIN(FindMembers);
}
<FindMembers,FindFields>{B}*"#" { if (insidePHP)
REJECT;
lastCPPContext = YY_START;
BEGIN( SkipCPP ) ;
}
<FindMembers,FindFields>{B}*"#"{B}*("cmake")?"define" {
if (insidePHP)
REJECT;
current->bodyLine = yyLineNr;
BEGIN( Define );
}
<FindMembers,ReadBody,ReadNSBody,ReadBodyIntf,SkipCurly,SkipCurlyCpp>{B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */
yyLineNr = atoi(&yytext[1]);
//printf("setting line number to %d\n",yyLineNr);
lastPreLineCtrlContext = YY_START;
current->program+=yytext;
BEGIN( PreLineCtrl );
}
<PreLineCtrl>"\""[^\n\"]*"\"" {
yyFileName = stripQuotes(yytext);
current->program+=yytext;
}
<PreLineCtrl>. {
current->program+=yytext;
}
<PreLineCtrl>\n {
current->program+=yytext;
yyLineNr++;
BEGIN( lastPreLineCtrlContext );
}
<SkipCPP>.
<SkipCPP>\\[\r]*"\n"[\r]* { yyLineNr++ ; }
<SkipCPP>[\r]*\n[\r]* { yyLineNr++ ;
BEGIN( lastCPPContext) ;
}
<Define>{ID}{B}*"(" {
current->name = yytext;
current->name = current->name.left(current->name.length()-1).stripWhiteSpace();
current->args = "(";
current->bodyLine = yyLineNr;
currentArgumentContext = DefineEnd;
fullArgString=current->args.copy();
copyArgString=¤t->args;
BEGIN( ReadFuncArgType ) ;
}
/*
<DefineArg>")" {
//printf("Define with args\n");
current->args += ')';
BEGIN( DefineEnd );
}
<DefineArg>. {
current->args += *yytext;
}
*/
<Define>{ID} {
//printf("Define `%s' without args\n",yytext);
current->bodyLine = yyLineNr;
current->name = yytext;
BEGIN(DefineEnd);
}
<DefineEnd>\n {
//printf("End define\n");
yyLineNr++;
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->type.resize(0);
current->args = current->args.simplifyWhiteSpace();
current->name = current->name.stripWhiteSpace();
current->section = Entry::DEFINE_SEC;
current_root->addSubEntry(current);
current = new Entry ;
initEntry();
BEGIN(FindMembers);
}
<DefinePHPEnd>";" {
//printf("End define\n");
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->type.resize(0);
current->args = current->args.simplifyWhiteSpace();
current->name = current->name.stripWhiteSpace();
current->section = Entry::ENUM_SEC; //HACK!
current_root->addSubEntry(current);
current = new Entry ;
initEntry();
BEGIN(FindMembers);
}
<DefinePHPEnd>.
<DefineEnd>\\[\r]?\n {
yyLineNr++;
}
<DefineEnd>\" {
if (insideIDL && insideCppQuote)
{
BEGIN(EndCppQuote);
}
else
{
lastStringContext=DefineEnd;
BEGIN(SkipString);
}
}
<DefineEnd>.
<DefinePHP>{ID}["']{BN}*","{BN}* {
current->name = yytext;
current->name = current->name.stripWhiteSpace();
current->name = current->name.left(current->name.length()-1).stripWhiteSpace();
current->name = current->name.left(current->name.length()-1);
current->args = "(";
current->bodyLine = yyLineNr;
lastRoundContext = DefinePHPEnd;
pCopyRoundString = ¤t->args;
roundCount = 0;
BEGIN( CopyRound );
}
<FindMembers>[\^%] { // ^ and % are C++/CLI extensions
if (insideCli)
{
addType( current );
current->name = yytext ;
}
else
{
REJECT;
}
}
<FindMembers>[*&]+ {
current->name += yytext ;
addType( current );
}
<FindMembers,MemberSpec,Function,NextSemi,BitFields,ReadInitializer,OldStyleArgs>";"{BN}*("/**"|"//!"|"/*!"|"///")"<" {
lineCount();
if (current->bodyLine==-1)
{
current->bodyLine=yyLineNr;
}
docBlockContext = YY_START;
docBlockInBody = FALSE;
docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF") ) ||
( yytext[yyleng-2]=='!' && Config_getBool("QT_AUTOBRIEF") );
docBlock.resize(0);
docBlockTerm = ';';
if (yytext[yyleng-3]=='/')
{
startCommentBlock(TRUE);
BEGIN( DocLine );
}
else
{
startCommentBlock(FALSE);
BEGIN( DocBlock );
}
}
<MemberSpec,FindFields,FindMembers,NextSemi,BitFields,ReadInitializer,OldStyleArgs>","{BN}*("/**"|"//!"|"/*!"|"///")"<" {
lineCount();
docBlockContext = YY_START;
docBlockInBody = FALSE;
docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF") ) ||
( yytext[yyleng-2]=='!' && Config_getBool("QT_AUTOBRIEF") );
docBlock.resize(0);
docBlockTerm = ',';
if (yytext[yyleng-3]=='/')
{
startCommentBlock(TRUE);
BEGIN( DocLine );
}
else
{
startCommentBlock(FALSE);
BEGIN( DocBlock );
}
}
<DefineEnd,FindFields,FindFieldArg,ReadInitializer,OldStyleArgs>{BN}*("/**"|"//!"|"/*!"|"///")"<" {
lineCount();
if (current->bodyLine==-1)
{
current->bodyLine=yyLineNr;
}
docBlockContext = YY_START;
docBlockInBody = FALSE;
docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF") ) ||
( yytext[yyleng-2]=='!' && Config_getBool("QT_AUTOBRIEF") );
docBlock.resize(0);
docBlockTerm = 0;
if (yytext[yyleng-3]=='/')
{
startCommentBlock(TRUE);
BEGIN( DocLine );
}
else
{
startCommentBlock(FALSE);
BEGIN( DocBlock );
}
}
<FindMembers,FindFields>("//"([!/]?){B}*{CMD}"{")|("/*"([!*]?){B}*{CMD}"{") {
//handleGroupStartCommand(current->name);
if (previous && previous->section==Entry::GROUPDOC_SEC)
{
// link open command to the group defined in the previous entry
openGroup(previous,yyFileName,yyLineNr);
}
else
{
// link open command to the current entry
openGroup(current,yyFileName,yyLineNr);
}
//current = tmp;
initEntry();
if (yytext[1]=='/')
{
if (yytext[2]=='!' || yytext[2]=='/')
{
docBlockContext = YY_START;
docBlockInBody = FALSE;
docBlockAutoBrief = FALSE;
docBlock.resize(0);
docBlockTerm = 0;
startCommentBlock(TRUE);
BEGIN(DocLine);
}
else
{
lastCContext=YY_START;
BEGIN(SkipCxxComment);
}
}
else
{
if (yytext[2]=='!' || yytext[2]=='*')
{
docBlockContext = YY_START;
docBlockInBody = FALSE;
docBlock.resize(0);
docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF") ) ||
( yytext[yyleng-2]=='!' && Config_getBool("QT_AUTOBRIEF") );
docBlockTerm = 0;
startCommentBlock(FALSE);
BEGIN(DocBlock);
}
else
{
lastCContext=YY_START;
BEGIN(SkipComment);
}
}
}
<FindMembers,FindFields,ReadInitializer>"//"([!/]?){B}*{CMD}"}".*|"/*"([!*]?){B}*{CMD}"}".*"*/" {
closeGroup(current,yyFileName,yyLineNr);
}
<FindMembers>"=" { // in PHP code this could also be due to "<?="
current->bodyLine = yyLineNr;
lastInitializerContext = YY_START;
initBracketCount=0;
BEGIN(ReadInitializer);
}
/* Read initializer rules */
<ReadInitializer>"(" {
lastRoundContext=YY_START;
pCopyRoundGString=¤t->initializer;
roundCount=0;
current->initializer+=*yytext;
BEGIN(GCopyRound);
}
<ReadInitializer>"{" {
lastCurlyContext=YY_START;
pCopyCurlyGString=¤t->initializer;
curlyCount=0;
current->initializer+=*yytext;
BEGIN(GCopyCurly);
}
<ReadInitializer>[;,] {
//printf(">> initializer `%s' <<\n",current->initializer.data());
if (*yytext==';' || lastInitializerContext==FindFields)
{
unput(*yytext);
BEGIN(lastInitializerContext);
}
else if (*yytext==',' && initBracketCount==0) // for "int a=0,b=0"
{
unput(*yytext);
BEGIN(lastInitializerContext);
}
else
{
current->initializer+=*yytext;
}
}
<ReadInitializer>\" {
if (insideIDL && insideCppQuote)
{
BEGIN(EndCppQuote);
}
else
{
lastStringContext=YY_START;
current->initializer+=*yytext;
pCopyQuotedGString=¤t->initializer;
BEGIN(CopyGString);
}
}
<ReadInitializer>"->" {
current->initializer+=yytext;
}
<ReadInitializer>"<<" {
current->initializer+=yytext;
}
<ReadInitializer>">>" {
current->initializer+=yytext;
}
<ReadInitializer>[<\[{(] {
initBracketCount++;
current->initializer+=*yytext;
}
<ReadInitializer>[>\]})] {
initBracketCount--;
current->initializer+=*yytext;
}
<ReadInitializer>\' {
if (insidePHP)
{
current->initializer+=yytext;
pCopyQuotedGString = ¤t->initializer;
lastStringContext=YY_START;
BEGIN(CopyPHPGString);
}
else
{
current->initializer+=yytext;
}
}
<ReadInitializer>{CHARLIT} {
if (insidePHP)
{
REJECT;
}
else
{
current->initializer+=yytext;
}
}
<ReadInitializer>\n {
current->initializer+=*yytext;
yyLineNr++;
}
<ReadInitializer>"@\"" {
//printf("insideCS=%d\n",insideCS);
current->initializer+=yytext;
if (!insideCS && !insideObjC)
{
REJECT;
}
else
{
// C#/ObjC verbatim string
lastSkipVerbStringContext=YY_START;
pSkipVerbString=¤t->initializer;
BEGIN(SkipVerbString);
}
}
<SkipVerbString>[^\n"]+ {
*pSkipVerbString+=yytext;
}
<SkipVerbString>"\"\"" { // quote escape
*pSkipVerbString+=yytext;
}
<SkipVerbString>"\"" {
*pSkipVerbString+=*yytext;
BEGIN(lastSkipVerbStringContext);
}
<SkipVerbString>\n {
*pSkipVerbString+=*yytext;
yyLineNr++;
}
<SkipVerbString>. {
*pSkipVerbString+=*yytext;
}
<ReadInitializer>"?>" {
if (insidePHP)
BEGIN( FindMembersPHP );
else
current->initializer+=yytext;
}
<ReadInitializer>. {
current->initializer+=*yytext;
}
/* generic quoted string copy rules */
<CopyString,CopyPHPString>\\. {
*pCopyQuotedString+=yytext;
}
<CopyString>\" {
*pCopyQuotedString+=*yytext;
BEGIN( lastStringContext );
}
<CopyPHPString>\' {
*pCopyQuotedString+=*yytext;
BEGIN( lastStringContext );
}
<CopyString,CopyPHPString>"/*"|"*/"|"//" {
*pCopyQuotedString+=yytext;
}
<CopyString,CopyPHPString>\n {
*pCopyQuotedString+=*yytext;
yyLineNr++;
}
<CopyString,CopyPHPString>. {
*pCopyQuotedString+=*yytext;
}
/* generic quoted growable string copy rules */
<CopyGString,CopyPHPGString>\\. {
*pCopyQuotedGString+=yytext;
}
<CopyGString>\" {
*pCopyQuotedGString+=*yytext;
BEGIN( lastStringContext );
}
<CopyPHPGString>\' {
*pCopyQuotedGString+=*yytext;
BEGIN( lastStringContext );
}
<CopyGString,CopyPHPGString>"/*"|"*/"|"//" {
*pCopyQuotedGString+=yytext;
}
<CopyGString,CopyPHPGString>\n {
*pCopyQuotedGString+=*yytext;
yyLineNr++;
}
<CopyGString,CopyPHPGString>. {
*pCopyQuotedGString+=*yytext;
}
/* generic round bracket list copy rules */
<CopyRound>\" {
*pCopyRoundString+=*yytext;
pCopyQuotedString=pCopyRoundString;
lastStringContext=YY_START;
BEGIN(CopyString);
}
<CopyRound>"(" {
*pCopyRoundString+=*yytext;
roundCount++;
}
<CopyRound>")" {
*pCopyRoundString+=*yytext;
if (--roundCount<0)
BEGIN(lastRoundContext);
}
<CopyRound>\n {
yyLineNr++;
*pCopyRoundString+=*yytext;
}
<CopyRound>\' {
if (insidePHP)
{
current->initializer+=yytext;
pCopyQuotedString = pCopyRoundString;
lastStringContext=YY_START;
BEGIN(CopyPHPString);
}
else
{
*pCopyRoundString+=yytext;
}
}
<CopyRound>{CHARLIT} {
if (insidePHP)
{
REJECT;
}
else
{
*pCopyRoundString+=yytext;
}
}
<CopyRound>[^"'()\n]+ {
*pCopyRoundString+=yytext;
}
<CopyRound>. {
*pCopyRoundString+=*yytext;
}
/* generic round bracket list copy rules for growable strings */
<GCopyRound>\" {
*pCopyRoundGString+=*yytext;
pCopyQuotedGString=pCopyRoundGString;
lastStringContext=YY_START;
BEGIN(CopyGString);
}
<GCopyRound>"(" {
*pCopyRoundGString+=*yytext;
roundCount++;
}
<GCopyRound>")" {
*pCopyRoundGString+=*yytext;
if (--roundCount<0)
BEGIN(lastRoundContext);
}
<GCopyRound>\n {
yyLineNr++;
*pCopyRoundGString+=*yytext;
}
<GCopyRound>\' {
if (insidePHP)
{
current->initializer+=yytext;
pCopyQuotedGString = pCopyRoundGString;
lastStringContext=YY_START;
BEGIN(CopyPHPGString);
}
else
{
*pCopyRoundGString+=yytext;
}
}
<GCopyRound>{CHARLIT} {
if (insidePHP)
{
REJECT;
}
else
{
*pCopyRoundGString+=yytext;
}
}
<GCopyRound>[^"'()\n/]+ {
*pCopyRoundGString+=yytext;
}
<GCopyRound>. {
*pCopyRoundGString+=*yytext;
}
/* generic curly bracket list copy rules */
<CopyCurly>\" {
*pCopyCurlyString+=*yytext;
pCopyQuotedString=pCopyCurlyString;
lastStringContext=YY_START;
BEGIN(CopyString);
}
<CopyCurly>\' {
*pCopyCurlyString+=*yytext;
if (insidePHP)
{
pCopyQuotedString=pCopyCurlyString;
lastStringContext=YY_START;
BEGIN(CopyPHPString);
}
}
<CopyCurly>"{" {
*pCopyCurlyString+=*yytext;
curlyCount++;
}
<CopyCurly>"}" {
*pCopyCurlyString+=*yytext;
if (--curlyCount<0)
BEGIN(lastCurlyContext);
}
<CopyCurly>{CHARLIT} { if (insidePHP)
{
REJECT;
}
else
{
*pCopyCurlyString+=yytext;
}
}
<CopyCurly>[^"'{}\/\n]+ {
*pCopyCurlyString+=yytext;
}
<CopyCurly>"/" { *pCopyCurlyString+=yytext; }
<CopyCurly>\n {
yyLineNr++;
*pCopyCurlyString+=*yytext;
}
<CopyCurly>. {
*pCopyCurlyString+=*yytext;
}
/* generic curly bracket list copy rules for growable strings */
<GCopyCurly>^"#"{B}+[0-9]+{B}+"\""[^\"\n]+"\""{B}+"1"{B}*\n? { // start of included file marker
}
<GCopyCurly>^"#"{B}+[0-9]+{B}+"\""[^\"\n]+"\""{B}+"2"{B}*\n? { // end of included file marker
QCString line = QCString(yytext);
int s = line.find(' ');
int e = line.find('"',s);
yyLineNr = line.mid(s,e-s).toInt();
if (yytext[yyleng-1]=='\n')
{
yyLineNr++;
}
}
<GCopyCurly>\" {
*pCopyCurlyGString+=*yytext;
pCopyQuotedGString=pCopyCurlyGString;
lastStringContext=YY_START;
BEGIN(CopyGString);
}
<GCopyCurly>\' {
*pCopyCurlyGString+=*yytext;
if (insidePHP)
{
pCopyQuotedGString=pCopyCurlyGString;
lastStringContext=YY_START;
BEGIN(CopyPHPGString);
}
}
<GCopyCurly>"{" {
*pCopyCurlyGString+=*yytext;
curlyCount++;
}
<GCopyCurly>"}" {
*pCopyCurlyGString+=*yytext;
if (--curlyCount<0)
BEGIN(lastCurlyContext);
}
<GCopyCurly>{CHARLIT} { if (insidePHP)
{
REJECT;
}
else
{
*pCopyCurlyGString+=yytext;
}
}
<GCopyCurly>[^"'{}\/\n]+ {
*pCopyCurlyGString+=yytext;
}
<GCopyCurly>"/" { *pCopyCurlyGString+=yytext; }
<GCopyCurly>\n {
yyLineNr++;
*pCopyCurlyGString+=*yytext;
}
<GCopyCurly>. {
*pCopyCurlyGString+=*yytext;
}
/* ---------------------- */
<FindMembers>":" {
if (current->type.isEmpty()) // anonymous padding field, e.g. "int :7;"
{
addType(current);
current->name.sprintf("__pad%d__",padCount++);
}
BEGIN(BitFields);
current->bitfields+=":";
}
<BitFields>. {
current->bitfields+=*yytext;
}
<FindMembers>[;,] {
//printf("scanner.l: <FindMembers>[;,] name=%s, endBodyLine=%d\n", current->name.data(), current->endBodyLine);
QCString oldType = current->type.copy();
if (current->bodyLine==-1)
{
current->bodyLine = yyLineNr;
}
if ( insidePHP && current->type.left(3) == "var" )
{
current->type = current->type.mid(3);
}
if (isTypedef && current->type.left(8)!="typedef ")
{
current->type.prepend("typedef ");
}
bool needNewCurrent=FALSE;
if (!current->name.isEmpty() && current->section!=Entry::ENUM_SEC)
{
current->type=current->type.simplifyWhiteSpace();
current->args=removeRedundantWhiteSpace(current->args);
current->name=current->name.stripWhiteSpace();
if (current->section==Entry::CLASS_SEC) // remove spec for "struct Bla bla;"
{
current->spec = 0;
}
current->section = Entry::VARIABLE_SEC ;
current->fileName = yyFileName;
current->startLine = yyLineNr;
//printf("scanner.l: <FindMembers>[;,] file=%s line=%d\n", current->fileName.data(), current->startLine);
current_root->addSubEntry( current ) ;
needNewCurrent=TRUE;
}
if ( *yytext == ',')
{
if (needNewCurrent)
{
current = new Entry(*current);
}
current->name.resize(0);
current->args.resize(0);
current->brief.resize(0);
current->doc.resize(0);
current->initializer.resize(0);
current->bitfields.resize(0);
int i=oldType.length();
while (i>0 && (oldType[i-1]=='*' || oldType[i-1]=='&' || oldType[i-1]==' ')) i--;
current->type = oldType.left(i);
}
else
{
if (needNewCurrent)
{
current = new Entry ;
}
else if (current->groups)
{
current->groups->clear();
}
initEntry();
}
BEGIN( FindMembers ) ;
}
<FindMembers>"[" {
if (!insideCS &&
(current->name.isEmpty() ||
current->name=="typedef"
)
) // IDL function property
{
squareCount=1;
lastSquareContext = YY_START;
idlAttr.resize(0);
idlProp.resize(0);
current->mtype = mtype;
BEGIN( IDLAttribute );
}
else if (insideCS &&
current->name.isEmpty())
{
squareCount=1;
lastSquareContext = YY_START;
// Skip the C# attribute
// for this member
current->args.resize(0);
BEGIN( SkipSquare );
}
else
{
current->args += yytext ;
squareCount=1;
BEGIN( Array ) ;
}
}
<IDLAttribute>"]" {
// end of IDL function attribute
if (--squareCount<=0)
{
lineCount();
if (current->mtype == Property)
BEGIN( IDLPropName );
else
BEGIN( lastSquareContext );
}
}
<IDLAttribute>"propput" {
if (Config_getBool("IDL_PROPERTY_SUPPORT"))
{
current->mtype = Property;
}
current->spec |= Entry::Settable;
}
<IDLAttribute>"propget" {
if (Config_getBool("IDL_PROPERTY_SUPPORT"))
{
current->mtype = Property;
}
current->spec |= Entry::Gettable;
}
<IDLAttribute>. {
}
<IDLPropName>{BN}*{ID}{BN}* {
// return type (probably HRESULT) - skip it
}
<IDLPropName>{ID}{BN}*"(" {
current->name = yytext;
current->name = current->name.left(current->name.length()-1).stripWhiteSpace();
current->startLine = yyLineNr;
BEGIN( IDLProp );
}
<IDLProp>{BN}*"["[^\]]*"]"{BN}* { // attribute of a parameter
idlAttr = yytext;
idlAttr=idlAttr.stripWhiteSpace();
}
<IDLProp>{ID} { // property type
idlProp = yytext;
}
<IDLProp>{BN}*{ID}{BN}*"," { // Rare: Another parameter ([propput] HRESULT Item(int index, [in] Type theRealProperty);)
if (!current->args)
current->args = "(";
else
current->args += ", ";
current->args += idlAttr;
current->args += " ";
current->args += idlProp; // prop was actually type of extra parameter
current->args += " ";
current->args += yytext;
current->args = current->args.left(current->args.length() - 1); // strip comma
idlProp.resize(0);
idlAttr.resize(0);
BEGIN( IDLProp );
}
<IDLProp>{BN}*{ID}{BN}*")"{BN}* {
// the parameter name for the property - just skip.
}
<IDLProp>";" {
current->fileName = yyFileName;
current->type = idlProp;
current->args = current->args.simplifyWhiteSpace();
if (current->args)
current->args += ")";
current->name = current->name.stripWhiteSpace();
current->section = Entry::VARIABLE_SEC;
current_root->addSubEntry(current);
current = new Entry;
initEntry();
BEGIN( FindMembers );
}
<IDLProp>. { // spaces, *, or other stuff
//idlProp+=yytext;
}
<Array>"]" { current->args += *yytext ;
if (--squareCount<=0)
BEGIN( FindMembers ) ;
}
<FuncFuncArray>"]" { current->args += *yytext ;
if (--squareCount<=0)
BEGIN( Function ) ;
}
<Array,FuncFuncArray>"[" { current->args += *yytext ;
squareCount++;
}
<Array,FuncFuncArray>. { current->args += *yytext ; }
<SkipSquare>"[" { squareCount++; }
<SkipSquare>"]" {
if (--squareCount<=0)
BEGIN( lastSquareContext );
}
<SkipSquare>\" {
lastStringContext=YY_START;
BEGIN( SkipString );
}
<SkipSquare>[^\n\[\]\"]+
<FindMembers>"<" { addType( current ) ;
current->type += yytext ;
BEGIN( Sharp ) ;
}
<Sharp>">" { current->type += *yytext ;
if (--sharpCount<=0)
BEGIN( FindMembers ) ;
}
<Sharp>"<" { current->type += *yytext ;
sharpCount++;
}
<Sharp>{BN}+ {
lineCount();
}
<Sharp>. { current->type += *yytext ; }
<FindFields>{ID} {
current->bodyLine = yyLineNr;
current->name = yytext;
}
<FindFields>"(" {
// Java enum initializer
unput('(');
lastInitializerContext = YY_START;
initBracketCount=0;
BEGIN(ReadInitializer);
}
<FindFields>"=" {
lastInitializerContext = YY_START;
initBracketCount=0;
BEGIN(ReadInitializer);
}
<FindFields>";" {
if (insideJava) // last enum field in Java class
{
if (!current->name.isEmpty())
{
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->type = "@"; // enum marker
current->args = current->args.simplifyWhiteSpace();
current->name = current->name.stripWhiteSpace();
current->section = Entry::VARIABLE_SEC;
current_root->addSubEntry(current);
current = new Entry ;
initEntry();
}
// TODO: skip until the end of the scope
BEGIN( SkipRemainder );
}
else
{
REJECT;
}
}
<SkipRemainder>\n {
yyLineNr++;
}
<SkipRemainder>[^\n]*
<FindFields>"," {
//printf("adding `%s' `%s' `%s' to enum `%s' (mGrpId=%d)\n",
// current->type.data(), current->name.data(),
// current->args.data(), current_root->name.data(),current->mGrpId);
if (!current->name.isEmpty())
{
current->fileName = yyFileName;
current->startLine = yyLineNr;
current->type = "@"; // enum marker
current->args = current->args.simplifyWhiteSpace();
current->name = current->name.stripWhiteSpace();
current->section = Entry::VARIABLE_SEC;
// add to the scope of the enum
current_root->addSubEntry(current);
if (!insideCS && !insideJava) // for C# and Java 1.5+ enum values always have to be explicitly qualified
{
current = new Entry(*current);
// add to the scope surrounding the enum (copy!)
current_root->parent()->addSubEntry(current);
}
current = new Entry ;
initEntry();
}
else // probably a redundant ,
{
current->reset();
}
}
<FindFields>"[" { // attribute list in IDL
squareCount=1;
lastSquareContext = YY_START;
BEGIN(SkipSquare);
}
/*
<FindFieldArg>"," { unput(*yytext); BEGIN(FindFields); }
*/
<ReadBody,ReadNSBody,ReadBodyIntf>[^\r\n\#{}"@'/]* { current->program += yytext ; }
<ReadBody,ReadNSBody,ReadBodyIntf>"//".* { current->program += yytext ; }
<ReadBody,ReadNSBody,ReadBodyIntf>"#".* { if (!insidePHP)
REJECT;
// append PHP comment.
current->program += yytext ;
}
<ReadBody,ReadNSBody,ReadBodyIntf>@\" { current->program += yytext ;
pSkipVerbString = ¤t->program;
lastSkipVerbStringContext=YY_START;
BEGIN( SkipVerbString );
}
<ReadBody,ReadNSBody,ReadBodyIntf>\" { current->program += yytext ;
pCopyQuotedGString = ¤t->program;
lastStringContext=YY_START;
BEGIN( CopyGString );
}
<ReadBody,ReadNSBody,ReadBodyIntf>"/*"{B}* { current->program += yytext ;
lastContext = YY_START ;
BEGIN( Comment ) ;
}
<ReadBody,ReadNSBody,ReadBodyIntf>"/*"{BL} { current->program += yytext ;
++yyLineNr ;
lastContext = YY_START ;
BEGIN( Comment ) ;
}
<ReadBody,ReadNSBody,ReadBodyIntf>"'" {
if (!insidePHP)
{
current->program += yytext;
}
else
{ // begin of single quoted string
current->program += yytext;
pCopyQuotedGString = ¤t->program;
lastStringContext=YY_START;
BEGIN(CopyPHPGString);
}
}
<ReadBody,ReadNSBody,ReadBodyIntf>{CHARLIT} {
if (insidePHP)
{
REJECT; // for PHP code single quotes
// are used for strings of arbitrary length
}
else
{
current->program += yytext;
}
}
<ReadBody,ReadNSBody,ReadBodyIntf>"{" { current->program += yytext ;
++curlyCount ;
}
<ReadBodyIntf>"}" {
current->program += yytext ;
--curlyCount ;
}
<ReadBody,ReadNSBody>"}" { //err("ReadBody count=%d\n",curlyCount);
if ( curlyCount>0 )
{
current->program += yytext ;
--curlyCount ;
}
else
{
current->endBodyLine = yyLineNr;
QCString &cn = current->name;
QCString rn = current_root->name.copy();
//printf("cn=`%s' rn=`%s'\n",cn.data(),rn.data());
if (!cn.isEmpty() && !rn.isEmpty())
{
prependScope();
}
if (isTypedef && cn.isEmpty())
{
//printf("Typedef Name\n");
BEGIN( TypedefName );
}
else
{
if (current->section == Entry::ENUM_SEC)
{
current->program+=','; // add field terminator
}
// add compound definition to the tree
current->args=removeRedundantWhiteSpace(current->args);
// was: current->args.simplifyWhiteSpace();
current->type = current->type.simplifyWhiteSpace();
current->name = current->name.stripWhiteSpace();
//printf("adding `%s' `%s' `%s' brief=%s insideObjC=%d %x\n",current->type.data(),current->name.data(),current->args.data(),current->brief.data(),insideObjC,current->section);
if (insideObjC &&
((current->spec&Entry::Interface) || (current->spec==Entry::Category))
) // method definition follows
{
BEGIN( ReadBodyIntf ) ;
}
else
{
current_root->addSubEntry( current ) ;
memspecEntry = current;
current = new Entry(*current);
if (current->section==Entry::NAMESPACE_SEC ||
(current->spec==Entry::Interface) ||
insideJava || insidePHP || insideCS || insideD || insideJS
)
{ // namespaces and interfaces and java classes ends with a closing bracket without semicolon
current->reset();
initEntry();
memspecEntry = 0;
BEGIN( FindMembers ) ;
}
else
{
//current->doc.resize(0);
//current->brief.resize(0);
BEGIN( MemberSpec ) ;
}
}
}
}
}
<ReadBody>"}"{BN}+"typedef"{BN}+ { //err("ReadBody count=%d\n",curlyCount);
lineCount();
if ( curlyCount>0 )
{
current->program += yytext ;
--curlyCount ;
}
else
{
isTypedef = TRUE;
current->endBodyLine = yyLineNr;
QCString &cn = current->name;
QCString rn = current_root->name.copy();
if (!cn.isEmpty() && !rn.isEmpty())
{
prependScope();
}
BEGIN( TypedefName );
}
}
<TypedefName>("const"|"volatile"){BN} { // late "const" or "volatile" keyword
lineCount();
current->type.prepend(yytext);
}
<TypedefName>{ID} {
if (current->section == Entry::ENUM_SEC)
{
current->program+=","; // add field terminator
}
current->name=yytext;
prependScope();
current->args = current->args.simplifyWhiteSpace();
current->type = current->type.simplifyWhiteSpace();
//printf("Adding compound %s %s %s\n",current->type.data(),current->name.data(),current->args.data());
current_root->addSubEntry( current ) ;
if (!firstTypedefEntry)
{
firstTypedefEntry = current;
}
current = new Entry;
initEntry();
isTypedef=TRUE; // to undo reset by initEntry()
BEGIN(MemberSpecSkip);
}
<TypedefName>";" { /* typedef of anonymous type */
current->name.sprintf("@%d",anonCount++);
if (current->section == Entry::ENUM_SEC)
{
current->program+=','; // add field terminator
}
// add compound definition to the tree
current->args = current->args.simplifyWhiteSpace();
current->type = current->type.simplifyWhiteSpace();
current_root->addSubEntry( current ) ;
memspecEntry = current;
current = new Entry(*current);
unput(';');
BEGIN( MemberSpec ) ;
}
<MemberSpec>([*&]*{BN}*)*{ID}{BN}*("["[^\]\n]*"]")* { // the [] part could be improved.
lineCount();
int i=0,l=yyleng,j;
while (i<l && (!isId(yytext[i]))) i++;
msName = QCString(yytext).right(l-i).stripWhiteSpace();
j=msName.find("[");
if (j!=-1)
{
msArgs=msName.right(msName.length()-j);
msName=msName.left(j);
}
msType=QCString(yytext).left(i);
// handle *pName in: typedef { ... } name, *pName;
if (firstTypedefEntry)
{
if (firstTypedefEntry->spec&Entry::Struct)
{
msType.prepend("struct "+firstTypedefEntry->name);
}
else if (firstTypedefEntry->spec&Entry::Union)
{
msType.prepend("union "+firstTypedefEntry->name);
}
else if (firstTypedefEntry->section==Entry::ENUM_SEC)
{
msType.prepend("enum "+firstTypedefEntry->name);
}
else
{
msType.prepend(firstTypedefEntry->name);
}
}
}
<MemberSpec>[,;] {
//printf("current->name=`%s' msName=`%s'\n",current->name.data(),msName.data());
if (msName.isEmpty() && !current->name.isEmpty())
{
// see if the compound does not have a name or is inside another
// annonymous compound. If so we insert a
// special `annonymous' variable.
//Entry *p=current_root;
Entry *p=current;
while (p)
{
// only look for class scopes, not namespace scopes
if ((p->section & Entry::COMPOUND_MASK) && !p->name.isEmpty())
{
//printf("Trying scope `%s'\n",p->name.data());
int i=p->name.findRev("::");
int pi = (i==-1) ? 0 : i+2;
if (p->name.at(pi)=='@')
{
// annonymous compound inside -> insert dummy variable name
//printf("Adding annonymous variable for scope %s\n",p->name.data());
msName.sprintf("@%d",anonCount++);
break;
}
}
//p=p->parent;
if (p==current) p=current_root; else p=p->parent();
}
}
//printf("msName=%s current->name=%s\n",msName.data(),current->name.data());
if (!msName.isEmpty() && msName!=current->name) // skip typedef T {} T;
{
static bool typedefHidesStruct = Config_getBool("TYPEDEF_HIDES_STRUCT");
// case 1: typedef struct _S { ... } S_t;
// -> omit typedef and use S_t as the struct name
if (typedefHidesStruct &&
isTypedef &&
((current->spec&(Entry::Struct|Entry::Union)) ||
current->section==Entry::ENUM_SEC )&&
msType.stripWhiteSpace().isEmpty() &&
memspecEntry)
{
memspecEntry->name=msName;
}
else // case 2: create a typedef field
{
Entry *varEntry=new Entry;
varEntry->protection = current->protection ;
varEntry->mtype = current->mtype;
varEntry->virt = current->virt;
varEntry->stat = current->stat;
varEntry->section = Entry::VARIABLE_SEC;
varEntry->name = msName.stripWhiteSpace();
varEntry->type = current->type.simplifyWhiteSpace()+" ";
varEntry->args = msArgs;
if (isTypedef)
{
varEntry->type.prepend("typedef ");
// //printf("current->name = %s %s\n",current->name.data(),msName.data());
}
if (typedefHidesStruct &&
isTypedef &&
(current->spec&(Entry::Struct|Entry::Union)) &&
memspecEntry
) // case 1: use S_t as type for pS_t in "typedef struct _S {} S_t, *pS_t;"
{
varEntry->type+=memspecEntry->name+msType;
}
else // case 2: use _S as type for for pS_t
{
varEntry->type+=current->name+msType;
}
varEntry->fileName = yyFileName;
varEntry->startLine = yyLineNr;
varEntry->doc = current->doc.copy();
varEntry->brief = current->brief.copy();
varEntry->mGrpId = current->mGrpId;
// deep copy group list
QListIterator<Grouping> gli(*current->groups);
Grouping *g;
for (;(g=gli.current());++gli)
{
varEntry->groups->append(new Grouping(*g));
}
if (current->sli) // copy special list items
{
QListIterator<ListItemInfo> li(*current->sli);
ListItemInfo *lii;
for (li.toFirst();(lii=li.current());++li)
{
varEntry->addSpecialListItem(lii->type,lii->itemId);
}
}
//printf("Add: type=`%s',name=`%s',args=`%s' brief=%s doc=%s\n",
// varEntry->type.data(),varEntry->name.data(),
// varEntry->args.data(),varEntry->brief.data(),varEntry->doc.data());
current_root->addSubEntry(varEntry);
}
}
if (*yytext==';')
{
msType.resize(0);
msName.resize(0);
msArgs.resize(0);
isTypedef=FALSE;
firstTypedefEntry=0;
memspecEntry=0;
current->reset();
initEntry();
BEGIN( FindMembers );
}
else
{
current->doc.resize(0);
current->brief.resize(0);
}
}
<MemberSpec>"=" {
lastInitializerContext=YY_START;
initBracketCount=0;
BEGIN(ReadInitializer);
/* BEGIN(MemberSpecSkip); */
}
/*
<MemberSpecSkip>"{" {
curlyCount=0;
lastCurlyContext = MemberSpecSkip;
previous = current;
BEGIN(SkipCurly);
}
*/
<MemberSpecSkip>"," { BEGIN(MemberSpec); }
<MemberSpecSkip>";" { unput(';'); BEGIN(MemberSpec); }
<ReadBody,ReadNSBody,ReadBodyIntf>{BN}+ { current->program += yytext ;
lineCount() ;
}
<ReadBodyIntf>"@end"/[^a-z_A-Z0-9] { // end of Objective C block
current_root->addSubEntry( current ) ;
current=new Entry;
initEntry();
insideObjC=FALSE;
BEGIN( FindMembers );
}
<ReadBody,ReadNSBody,ReadBodyIntf>. { current->program += yytext ; }
<FindMembers>"("/{BN}*"::"*{BN}*({TSCOPE}{BN}*"::")*{TSCOPE}{BN}*")"{BN}*"(" | /* typedef void (A<int>::func_t)(args...) */
<FindMembers>("("({BN}*"::"*{BN}*{TSCOPE}{BN}*"::")*({BN}*[*&]{BN}*)+)+ { /* typedef void (A::*ptr_t)(args...) or int (*func(int))[] */
if (insidePHP) // reference parameter
{
REJECT
}
else
{
current->bodyLine = yyLineNr;
lineCount();
addType(current);
funcPtrType=yytext;
roundCount=0;
//current->type += yytext;
BEGIN( FuncPtr );
}
}
<FuncPtr>{SCOPENAME} {
current->name = yytext;
if (nameIsOperator(current->name))
{
BEGIN( FuncPtrOperator );
}
else
{
if (current->name=="const" || current->name=="volatile")
{
funcPtrType += current->name;
}
else
{
BEGIN( EndFuncPtr );
}
}
}
<FuncPtr>. {
//printf("Error: FuncPtr `%c' unexpected at line %d of %s\n",*yytext,yyLineNr,yyFileName);
}
<FuncPtrOperator>"("{BN}*")"{BN}*/"(" {
current->name += yytext;
current->name = current->name.simplifyWhiteSpace();
lineCount();
}
<FuncPtrOperator>\n {
yyLineNr++;
current->name += *yytext;
}
<FuncPtrOperator>"(" {
unput(*yytext);
BEGIN( EndFuncPtr );
}
<FuncPtrOperator>. {
current->name += *yytext;
}
<EndFuncPtr>")"{BN}*/";" { // a variable with extra braces
lineCount();
current->type+=funcPtrType.data()+1;
BEGIN(FindMembers);
}
<EndFuncPtr>")"{BN}*/"(" { // a function pointer
lineCount();
current->type+=funcPtrType+")";
BEGIN(FindMembers);
}
<EndFuncPtr>")"{BN}*/"[" { // an array of variables
lineCount();
current->type+=funcPtrType.data();
current->args += ")";
BEGIN(FindMembers);
}
<EndFuncPtr>"(" { // a function returning a function or
// a function returning a pointer to an array
current->args += *yytext ;
//roundCount=0;
//BEGIN( FuncFunc );
current->bodyLine = yyLineNr;
currentArgumentContext = FuncFuncEnd;
fullArgString=current->args.copy();
copyArgString=¤t->args;
BEGIN( ReadFuncArgType ) ;
}
<EndFuncPtr>"["[^\n\]]*"]" {
funcPtrType+=yytext;
}
<EndFuncPtr>")" {
BEGIN(FindMembers);
}
<FuncFunc>"(" {
current->args += *yytext ;
++roundCount;
}
<FuncFunc>")" {
current->args += *yytext ;
if ( roundCount )
--roundCount;
else
{
BEGIN(FuncFuncEnd);
}
}
<FuncFuncEnd>")"{BN}*"(" {
lineCount();
current->type+=funcPtrType+")(";
BEGIN(FuncFuncType);
}
<FuncFuncEnd>")"{BN}*/[;{] {
lineCount();
current->type+=funcPtrType.data()+1;
BEGIN(Function);
}
<FuncFuncEnd>")"{BN}*/"[" { // function returning a pointer to an array
lineCount();
current->type+=funcPtrType;
current->args+=")";
BEGIN(FuncFuncArray);
}
<FuncFuncEnd>. {
current->args += *yytext;
}
<FuncFuncType>"(" {
current->type += *yytext;
roundCount++;
}
<FuncFuncType>")" {
current->type += *yytext;
if (roundCount)
--roundCount;
else
BEGIN(Function);
}
<FuncFuncType>{BN}*","{BN}* { lineCount() ; current->type += ", " ; }
<FuncFuncType>{BN}+ { lineCount() ; current->type += ' ' ; }
<FuncFuncType>. {
current->type += *yytext;
}
<FindMembers>"("/{BN}*{ID}{BN}*"*"{BN}*{ID}*")(" { // for catching typedef void (__stdcall *f)() like definitions
if (current->type.left(7)=="typedef" && current->bodyLine==-1)
// the bodyLine check is to prevent this guard to be true more than once
{
current->bodyLine = yyLineNr;
BEGIN( GetCallType );
}
else if (!current->name.isEmpty()) // normal function
{
current->args = yytext;
current->bodyLine = yyLineNr;
currentArgumentContext = FuncQual;
fullArgString=current->args.copy();
copyArgString=¤t->args;
BEGIN( ReadFuncArgType ) ;
//printf(">>> Read function arguments!\n");
}
}
<GetCallType>{BN}*{ID}{BN}*"*" {
lineCount();
addType(current);
funcPtrType="(";
funcPtrType+=yytext;
roundCount=0;
BEGIN( FuncPtr );
}
<FindMembers>"(" {
if (!current->name.isEmpty())
{
current->args = yytext;
current->bodyLine = yyLineNr;
currentArgumentContext = FuncQual;
fullArgString=current->args.copy();
copyArgString=¤t->args;
BEGIN( ReadFuncArgType ) ;
//printf(">>> Read function arguments current->argList->count()=%d\n",current->argList->count());
}
}
/*
<FindMembers>"("{BN}*("void"{BN}*)?")" {
lineCount();
current->args = "()";
BEGIN( FuncQual );
}
*/
/*- Function argument reading rules ---------------------------------------*/
<ReadFuncArgType>[^ \/\r\t\n\)\(\"\'#]+ { *copyArgString+=yytext;
fullArgString+=yytext;
}
<CopyArgString,CopyArgPHPString>[^\n\\\"\']+ { *copyArgString+=yytext;
fullArgString+=yytext;
}
<CopyArgRound>[^\/\n\)\(\"\']+ {
*copyArgString+=yytext;
fullArgString+=yytext;
}
<ReadFuncArgType,ReadTempArgs>{BN}* {
*copyArgString+=" ";
fullArgString+=" ";
lineCount();
}
<ReadFuncArgType,CopyArgRound,CopyArgSharp,ReadTempArgs>\" {
*copyArgString+=*yytext;
fullArgString+=*yytext;
lastCopyArgStringContext = YY_START;
BEGIN( CopyArgString );
}
<ReadFuncArgType,ReadTempArgs>"(" {
*copyArgString+=*yytext;
fullArgString+=*yytext;
argRoundCount=0;
lastCopyArgContext = YY_START;
BEGIN( CopyArgRound );
}
<ReadFuncArgType>")" {
*copyArgString+=*yytext;
fullArgString+=*yytext;
stringToArgumentList(fullArgString,current->argList);
if (insideJS)
{
fixArgumentListForJavaScript(current->argList);
}
handleParametersCommentBlocks(current->argList);
/* remember the current documentation block, since
we could overwrite it with the documentation of
a function argument, which we then have to correct later
on
*/
docBackup = current->doc;
briefBackup = current->brief;
BEGIN( currentArgumentContext );
}
/* a special comment */
<ReadFuncArgType,ReadTempArgs>("/*"[*!]|"//"[/!])("<"?) {
if (currentArgumentContext==DefineEnd)
{
// for defines we interpret a comment
// as documentation for the define
int i;for (i=yyleng-1;i>=0;i--)
{
unput(yytext[i]);
}
stringToArgumentList(fullArgString,current->argList);
handleParametersCommentBlocks(current->argList);
BEGIN( currentArgumentContext );
}
else // not a define
{
// for functions we interpret a comment
// as documentation for the argument
fullArgString+=yytext;
lastCopyArgChar=0;
lastCommentInArgContext=YY_START;
if (yytext[1]=='/')
BEGIN( CopyArgCommentLine );
else
BEGIN( CopyArgComment );
}
}
/* a non-special comment */
<ReadFuncArgType,ReadTempArgs>"/**/" { /* empty comment */ }
<ReadFuncArgType,ReadTempArgs>"/*" {
lastCContext = YY_START;
BEGIN( SkipComment );
}
<ReadFuncArgType,ReadTempArgs>"//" {
lastCContext = YY_START;
BEGIN( SkipCxxComment );
}
/*
<ReadFuncArgType,ReadTempArgs>"'#" { if (insidePHP)
REJECT;
*copyArgString+=yytext;
fullArgString+=yytext;
}
<ReadFuncArgType,ReadTempArgs>"#" {
if (!insidePHP)
REJECT;
lastCContext = YY_START;
BEGIN( SkipCxxComment );
}
*/
/* `)' followed by a special comment */
<ReadFuncArgType>")"{BN}*("/*"[*!]|"//"[/!])"<" {
lineCount();
if (currentArgumentContext==DefineEnd)
{
// for defines we interpret a comment
// as documentation for the define
int i;for (i=yyleng-1;i>0;i--)
{
unput(yytext[i]);
}
*copyArgString+=*yytext;
fullArgString+=*yytext;
stringToArgumentList(fullArgString,current->argList);
handleParametersCommentBlocks(current->argList);
BEGIN( currentArgumentContext );
}
else
{
// for functions we interpret a comment
// as documentation for the last argument
lastCopyArgChar=*yytext;
QCString text=&yytext[1];
text=text.stripWhiteSpace();
lastCommentInArgContext=YY_START;
fullArgString+=text;
if (text.find("//")!=-1)
BEGIN( CopyArgCommentLine );
else
BEGIN( CopyArgComment );
}
}
<CopyArgComment>^{B}*"*"+/{BN}+
<CopyArgComment>[^\n\\\@\*]+ { fullArgString+=yytext; }
<CopyArgComment>"*/" { fullArgString+=yytext;
if (lastCopyArgChar!=0)
unput(lastCopyArgChar);
BEGIN( lastCommentInArgContext );
}
<CopyArgCommentLine>\n { fullArgString+=yytext;
yyLineNr++;
if (lastCopyArgChar!=0)
unput(lastCopyArgChar);
BEGIN( lastCommentInArgContext );
}
<CopyArgCommentLine>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9] { // verbatim command (which could contain nested comments!)
docBlockName=&yytext[1];
fullArgString+=yytext;
BEGIN(CopyArgVerbatim);
}
<CopyArgCommentLine>{CMD}("f$"|"f["|"f{") {
docBlockName=&yytext[1];
if (docBlockName.at(1)=='[')
{
docBlockName.at(1)='}';
}
if (docBlockName.at(1)=='{')
{
docBlockName.at(1)='}';
}
fullArgString+=yytext;
BEGIN(CopyArgVerbatim);
}
<CopyArgVerbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"endmanonly"|"enddot"|"endcode"|"f$"|"f]"|"f}")/[^a-z_A-Z0-9] { // end of verbatim block
fullArgString+=yytext;
if (yytext[1]=='f') // end of formula
{
BEGIN(CopyArgCommentLine);
}
if (&yytext[4]==docBlockName)
{
BEGIN(CopyArgCommentLine);
}
}
<CopyArgCommentLine>[^\\\@\n]+ { fullArgString+=yytext; }
<CopyArgCommentLine>. { fullArgString+=*yytext; }
<CopyArgComment,CopyArgVerbatim>\n { fullArgString+=*yytext; yyLineNr++; }
<CopyArgComment,CopyArgVerbatim>. { fullArgString+=*yytext; }
<CopyArgComment>{CMD}("brief"|"short"){B}+ {
warn(yyFileName,yyLineNr,
"Warning: Ignoring %cbrief command inside argument documentation",*yytext
);
fullArgString+=' ';
}
<ReadTempArgs>"<" {
*copyArgString+=*yytext;
fullArgString+=*yytext;
argSharpCount=1;
BEGIN( CopyArgSharp );
}
<ReadTempArgs>">" {
*copyArgString+=*yytext;
fullArgString+=*yytext;
//printf("end template list %s\n",copyArgString->data());
stringToArgumentList(fullArgString,currentArgumentList);
BEGIN( currentArgumentContext );
}
<CopyArgRound>"(" {
argRoundCount++;
*copyArgString+=*yytext;
fullArgString+=*yytext;
}
<CopyArgRound>")" {
*copyArgString+=*yytext;
fullArgString+=*yytext;
if (argRoundCount>0)
argRoundCount--;
else
BEGIN( lastCopyArgContext );
}
<CopyArgSharp>"<" {
argSharpCount++;
//printf("argSharpCount++=%d copy\n",argSharpCount);
*copyArgString+=*yytext;
fullArgString+=*yytext;
}
<CopyArgSharp>">" {
*copyArgString+=*yytext;
fullArgString+=*yytext;
argSharpCount--;
if (argSharpCount>0)
{
//printf("argSharpCount--=%d copy\n",argSharpCount);
}
else
{
BEGIN( ReadTempArgs );
//printf("end of argSharpCount\n");
}
}
<CopyArgString,CopyArgPHPString>\\. {
*copyArgString+=yytext;
fullArgString+=yytext;
}
<CopyArgString>\" {
*copyArgString+=*yytext;
fullArgString+=*yytext;
BEGIN( lastCopyArgStringContext );
}
<CopyArgPHPString>\' {
*copyArgString+=*yytext;
fullArgString+=*yytext;
BEGIN( lastCopyArgStringContext );
}
<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>{CHARLIT} {
if (insidePHP)
{
REJECT;
}
else
{
*copyArgString+=yytext;
fullArgString+=yytext;
}
}
<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>\' {
*copyArgString+=yytext;
fullArgString+=yytext;
if (insidePHP)
{
lastCopyArgStringContext=YY_START;
BEGIN(CopyArgPHPString);
}
}
<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgPHPString,CopyArgRound,CopyArgSharp>\n {
yyLineNr++;
*copyArgString+=*yytext;
fullArgString+=*yytext;
}
<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgPHPString,CopyArgRound,CopyArgSharp>. {
*copyArgString+=*yytext;
fullArgString+=*yytext;
}
/*------------------------------------------------------------------------*/
<FuncRound>"(" { current->args += *yytext ;
++roundCount ;
}
<FuncRound>")" { current->args += *yytext ;
if ( roundCount )
--roundCount ;
else
BEGIN( FuncQual ) ;
}
/*
<FuncQual>"#" { if (insidePHP)
REJECT;
lastCPPContext = YY_START;
BEGIN(SkipCPP);
}
*/
<FuncQual>[{:;,] {
if ( strcmp(yytext,";")==0 &&
insidePHP &&
!containsWord(current->type,"function") )
{
current->reset();
initEntry();
BEGIN( FindMembers );
}
else
{
unput(*yytext); BEGIN( Function );
}
}
<FuncQual>{BN}*"abstract"{BN}* { // pure virtual member function
lineCount() ;
current->virt = Pure;
current->args += " override ";
}
<FuncQual>{BN}*"override"{BN}* { // overridden virtual member function
lineCount() ;
current->spec |= Entry::Override;
current->args += " override ";
}
<FuncQual>{BN}*"sealed"{BN}* { // sealed member function
lineCount() ;
current->spec |= Entry::Sealed;
current->args += " sealed ";
}
<FuncQual>{BN}*"new"{BN}* { // new member function
lineCount() ;
current->spec |= Entry::New;
current->args += " new ";
}
<FuncQual>{BN}*"const"{BN}* { // const member function
lineCount() ;
current->args += " const ";
current->argList->constSpecifier=TRUE;
}
<FuncQual>{BN}*"volatile"{BN}* { // volatile member function
lineCount() ;
current->args += " volatile ";
current->argList->volatileSpecifier=TRUE;
}
<FuncQual>{BN}*"="{BN}*"0"{BN}* { // pure virtual member function
lineCount() ;
current->args += " = 0";
current->virt = Pure;
current->argList->pureSpecifier=TRUE;
}
<FuncRound,FuncFunc>{BN}*","{BN}* {
lineCount() ;
current->args += ", " ;
}
<FuncQual,FuncRound,FuncFunc>{BN}+ {
lineCount() ;
current->args += ' ' ;
}
<Function,FuncQual,FuncRound,FuncFunc>"#" { if (insidePHP)
REJECT;
lastCPPContext = YY_START;
BEGIN(SkipCPP);
}
<FuncQual>"=" {
if (insideCli &&
(current_root->section&Entry::COMPOUND_MASK)
)
{
BEGIN(CliOverride);
}
else
{
// typically an initialized function pointer
lastInitializerContext=YY_START;
initBracketCount=0;
BEGIN(ReadInitializer);
}
}
<CliOverride>{ID} {
}
<CliOverride>"{" {
unput(*yytext);
BEGIN(FuncQual);
}
<CliOverride>\n {
yyLineNr++;
}
<CliOverride>. {
}
<FuncPtrInit>[{;] {
unput(*yytext);
BEGIN(FuncQual);
}
<FuncPtrInit>\" {
current->args += *yytext;
pCopyQuotedString=¤t->args;
lastStringContext=FuncPtrInit;
BEGIN(CopyString);
}
<FuncPtrInit>\' {
current->args += *yytext;
if (insidePHP)
{
pCopyQuotedString=¤t->args;
lastStringContext=FuncPtrInit;
BEGIN(CopyPHPString);
}
}
<FuncPtrInit>{CHARLIT} {
if (insidePHP)
{
REJECT;
}
else
{
current->args += yytext;
}
}
<FuncPtrInit>{ID} {
current->args += yytext;
}
<FuncPtrInit>. {
current->args += *yytext;
}
<FuncPtrInit>\n {
current->args += *yytext;
yyLineNr++;
}
<FuncQual>{ID} { // typically a K&R style C function
if (insideCS && strcmp(yytext,"where")==0)
{
// type contraint for a method
delete current->typeConstr;
current->typeConstr = new ArgumentList;
current->typeConstr->append(new Argument);
lastCSConstraint = YY_START;
BEGIN( CSConstraintName );
}
else if (checkForKnRstyleC())
{
//fprintf(stderr,"===> got a K&R style function\n");
current->args = yytext;
oldStyleArgType.resize(0);
BEGIN(OldStyleArgs);
}
else
{
current->args += yytext;
}
}
<OldStyleArgs>[,;] {
QCString oldStyleArgPtr;
QCString oldStyleArgName;
splitKnRArg(oldStyleArgPtr,oldStyleArgName);
QCString doc,brief;
if (current->doc!=docBackup)
{
doc=current->doc.copy();
current->doc=docBackup;
}
if (current->brief!=briefBackup)
{
brief=current->brief.copy();
current->brief=briefBackup;
}
addKnRArgInfo(oldStyleArgType+oldStyleArgPtr,
oldStyleArgName,brief,doc);
current->args.resize(0);
if (*yytext==';') oldStyleArgType.resize(0);
}
<OldStyleArgs>{ID} { current->args += yytext; }
<OldStyleArgs>"{" {
current->args = argListToString(current->argList);
unput('{');
BEGIN(FuncQual);
}
<OldStyleArgs>. { current->args += *yytext; }
<FuncQual,FuncRound,FuncFunc>. { current->args += *yytext; }
<FuncQual>{BN}*"try"{BN}+ { /* try-function-block */
insideTryBlock=TRUE;
lineCount();
}
<FuncQual>{BN}*"throw"{BN}*"(" { // C++ style throw clause
current->exception = " throw (" ;
roundCount=0;
lineCount() ;
BEGIN( ExcpRound ) ;
}
<FuncQual>{BN}*"raises"{BN}*"(" {
current->exception = " raises (" ;
lineCount() ;
roundCount=0;
BEGIN( ExcpRound ) ;
}
<FuncQual>{BN}*"throws"{BN}+ { // Java style throw clause
current->exception = " throws " ;
lineCount() ;
BEGIN( ExcpList );
}
<ExcpRound>"(" { current->exception += *yytext ;
++roundCount ;
}
<ExcpRound>")" { current->exception += *yytext ;
if ( roundCount )
--roundCount ;
else
BEGIN( FuncQual ) ;
}
<ExcpRound>. {
current->exception += *yytext;
}
<ExcpList>"{" {
unput('{'); BEGIN( FuncQual );
}
<ExcpList>";" {
unput(';'); BEGIN( FuncQual );
}
<ExcpList>"\n" {
current->exception += ' ';
yyLineNr++;
}
<ExcpList>. {
current->exception += *yytext;
}
<Function>"(" { current->type += current->name ;
current->name = current->args ;
current->args = yytext ;
roundCount=0;
BEGIN( FuncRound ) ;
}
<Function>":" {
if (!insidePHP) BEGIN(SkipInits);
}
<Function>[;{,] {
current->name=current->name.simplifyWhiteSpace();
current->type=current->type.simplifyWhiteSpace();
current->args=removeRedundantWhiteSpace(current->args);
// was: current->args.simplifyWhiteSpace();
current->fileName = yyFileName;
current->startLine = yyLineNr;
static QRegExp re("([^)]*\\[*&][^)]*)"); // (...*...)
if (*yytext!=';' || (current_root->section&Entry::COMPOUND_MASK) )
{
int tempArg=current->name.find('<');
QCString tempName;
if (tempArg==-1) tempName=current->name; else tempName=current->name.left(tempArg);
if (!current->type.isEmpty() &&
(current->type.find(re,0)!=-1 || current->type.left(8)=="typedef "))
{
//printf("Scanner.l: found in class variable: `%s' `%s' `%s'\n", current->type.data(),current->name.data(),current->args.data());
current->section = Entry::VARIABLE_SEC ;
}
else
{
//printf("Scanner.l: found in class function: `%s' `%s' `%s'\n", current->type.data(),current->name.data(),current->args.data());
current->section = Entry::FUNCTION_SEC ;
current->proto = *yytext==';';
}
}
else // a global function prototype or function variable
{
//printf("Scanner.l: prototype? type=`%s' name=`%s' args=`%s'\n",current->type.data(),current->name.data(),current->args.data());
if (!current->type.isEmpty() &&
(current->type.find(re,0)!=-1 || current->type.left(8)=="typedef "))
{
//printf("Scanner.l: found function variable!\n");
current->section = Entry::VARIABLE_SEC;
}
else
{
//printf("Scanner.l: found prototype\n");
current->section = Entry::FUNCTION_SEC;
current->proto = TRUE;
}
}
//printf("Adding entry `%s'\n",current->name.data());
if ( insidePHP)
{
if (findAndRemoveWord(current->type,"final"))
{
current->spec |= Entry::Final;
}
if (findAndRemoveWord(current->type,"abstract"))
{
current->spec |= Entry::Abstract;
}
}
if ( insidePHP && !containsWord(current->type,"function"))
{
initEntry();
if ( *yytext == '{' )
{
lastCurlyContext = FindMembers;
curlyCount=0;
BEGIN( SkipCurly );
}
else
{
BEGIN( FindMembers );
}
}
else
{
if ( insidePHP)
{
findAndRemoveWord(current->type,"function");
}
previous = current;
current_root->addSubEntry(current);
current = new Entry ;
initEntry();
// Objective C 2.0: Required/Optional section
if (previous->spec & (Entry::Optional | Entry::Required))
{
current->spec |= previous->spec & (Entry::Optional|Entry::Required);
}
lastCurlyContext = FindMembers;
if ( *yytext == ',' )
{
current->type = previous->type.data();
}
if ( *yytext == '{' )
{
if ( !insidePHP && (current_root->section & Entry::COMPOUND_MASK) )
{
previous->spec |= Entry::Inline;
}
//addToBody(yytext);
curlyCount=0;
BEGIN( SkipCurly ) ;
}
else
{
if (previous->section!=Entry::VARIABLE_SEC)
previous->bodyLine=-1; // a function/member declaration
BEGIN( FindMembers ) ;
}
}
}
<SkipInits>"{" {
//addToBody(yytext);
//lastCurlyContext = FindMembers;
//curlyCount=0;
//BEGIN( SkipCurly ) ;
unput('{');
BEGIN( Function );
}
<SkipCurly>"{" {
//addToBody(yytext);
++curlyCount ;
}
<SkipCurly>"}" {
//addToBody(yytext);
if( curlyCount )
{
--curlyCount ;
}
else
{
#if 0
if (!Config_getBool("HIDE_IN_BODY_DOCS") &&
!current->doc.isEmpty())
{
// copy documentation found inside the body
// to the previous item
if (previous->inbodyLine==-1)
{
previous->inbodyLine = current->docLine;
previous->inbodyFile = current->docFile;
}
//printf("*** inbodyDocs+=%s\n",current->doc.data());
previous->inbodyDocs += current->doc;
current->doc.resize(0);
}
#endif
if (current->sli && previous) // copy special list items
{
QListIterator<ListItemInfo> li(*current->sli);
ListItemInfo *lii;
for (li.toFirst();(lii=li.current());++li)
{
previous->addSpecialListItem(lii->type,lii->itemId);
}
delete current->sli;
current->sli = 0;
}
if (previous) previous->endBodyLine=yyLineNr;
BEGIN( lastCurlyContext ) ;
}
}
<SkipCurly>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" {
lineCount();
if ( curlyCount )
{
//addToBody(yytext);
--curlyCount ;
}
else
{
current->endBodyLine=yyLineNr;
tempEntry = current; // temporarily switch to the previous entry
current = previous;
docBlockContext = SkipCurlyEndDoc;
docBlockInBody = FALSE;
docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF") ) ||
( yytext[yyleng-2]=='!' && Config_getBool("QT_AUTOBRIEF") );
docBlock.resize(0);
docBlockTerm = '}';
if (yytext[yyleng-3]=='/')
{
startCommentBlock(TRUE);
BEGIN( DocLine );
}
else
{
startCommentBlock(FALSE);
BEGIN( DocBlock );
}
}
}
<SkipCurlyEndDoc>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { // desc is followed by another one
docBlockContext = SkipCurlyEndDoc;
docBlockInBody = FALSE;
docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF") ) ||
( yytext[yyleng-2]=='!' && Config_getBool("QT_AUTOBRIEF") );
docBlock.resize(0);
docBlockTerm = '}';
if (yytext[yyleng-3]=='/')
{
startCommentBlock(TRUE);
BEGIN( DocLine );
}
else
{
startCommentBlock(FALSE);
BEGIN( DocBlock );
}
}
<SkipCurlyEndDoc>"}" {
//addToBody("}");
current = tempEntry;
BEGIN( lastCurlyContext );
}
<SkipCurly>\" {
//addToBody(yytext);
lastStringContext=SkipCurly;
BEGIN( SkipString );
}
<SkipCurly>^{B}*"#" {
if (insidePHP)
REJECT;
//addToBody(yytext);
BEGIN( SkipCurlyCpp );
}
<SkipCurly,SkipInits>\n {
yyLineNr++;
//addToBody(yytext);
}
<SkipCurly,SkipCurlyCpp>[^\n#"'@\\/{}]+ {
//addToBody(yytext);
}
<SkipCurlyCpp>\n {
//addToBody(yytext);
yyLineNr++;
lastCurlyContext = FindMembers;
BEGIN( SkipCurly );
}
<SkipCurlyCpp>\\[\r]*"\n"[\r]* {
//addToBody(yytext);
yyLineNr++;
}
<SkipInits,SkipCurly,SkipCurlyCpp>"/*" {
//addToBody(yytext);
lastCContext = YY_START;
BEGIN(SkipComment);
}
<SkipInits,SkipCurly,SkipCurlyCpp>"//" {
//addToBody(yytext);
lastCContext = YY_START;
BEGIN(SkipCxxComment);
}
<SkipInits>\" {
lastStringContext=YY_START;
BEGIN( SkipString );
}
<SkipInits>; {
warn(yyFileName,yyLineNr,
"Warning: Found ';' while parsing initializer list! "
"(doxygen could be confused by a macro call without semicolon)"
);
BEGIN( FindMembers );
}
<SkipInits,SkipCurly,SkipCurlyCpp>"#" {
if (!insidePHP)
REJECT;
//addToBody(yytext);
lastCContext = YY_START;
BEGIN(SkipCxxComment);
}
<SkipInits,SkipCurly,SkipCurlyCpp>@\" {
if (!insideCS) REJECT;
// C# verbatim string
lastSkipVerbStringContext=YY_START;
pSkipVerbString=¤t->initializer;
BEGIN(SkipVerbString);
}
<SkipInits,SkipCurly,SkipCurlyCpp>{CHARLIT} {
if (insidePHP) REJECT;
}
<SkipInits,SkipCurly,SkipCurlyCpp>\' {
if (insidePHP)
{
lastStringContext=YY_START;
BEGIN(SkipPHPString);
}
}
<SkipInits,SkipCurly,SkipCurlyCpp>. { }
<SkipString,SkipPHPString>\\. { }
<SkipString>\" {
BEGIN( lastStringContext );
}
<SkipPHPString>\' {
BEGIN( lastStringContext );
}
<SkipString,SkipPHPString>"/*"|"*/"|"//" { }
<SkipString,SkipPHPString>\n {
yyLineNr++;
}
<SkipString,SkipPHPString>. { }
<Bases,CompoundName>";" {
current->section = Entry::EMPTY_SEC ;
current->type.resize(0) ;
current->name.resize(0) ;
current->args.resize(0) ;
current->argList->clear();
BEGIN( FindMembers ) ;
}
<CompoundName>{SCOPENAME}{BN}*/"<" {
sharpCount = 0;
current->name = yytext ;
if (current->spec & Entry::Protocol)
{
current->name+="-p";
}
lineCount();
lastClassTemplSpecContext = ClassVar;
if (insideObjC) // protocol list
{
BEGIN( ObjCProtocolList );
}
else if (insideCS) // C# generic class
{
BEGIN( CSGeneric );
}
else // C++ template specialization
{
roundCount=0;
BEGIN( ClassTemplSpec );
}
}
<CSGeneric>"<" {
if (current->tArgLists==0)
{
current->tArgLists = new QList<ArgumentList>;
current->tArgLists->setAutoDelete(TRUE);
}
ArgumentList *al = new ArgumentList;
current->spec |= Entry::Template;
current->tArgLists->append(al);
currentArgumentList = al;
templateStr="<";
current->name += "<";
fullArgString = templateStr;
copyArgString = ¤t->name;
currentArgumentContext = ClassVar;
BEGIN( ReadTempArgs );
}
<ObjCProtocolList>"<" {
insideProtocolList=TRUE;
BEGIN( Bases );
}
<ClassTemplSpec>">"({BN}*"::"{BN}*{SCOPENAME})? {
current->name += yytext;
lineCount();
if (--sharpCount<=0)
{
current->name = removeRedundantWhiteSpace(current->name);
if (current->spec & Entry::Protocol)
{ // Objective-C protocol
unput('{'); // fake start of body
BEGIN( ClassVar );
}
else
{
BEGIN( lastClassTemplSpecContext );
}
}
}
<ClassTemplSpec>"<" {
current->name += yytext;
sharpCount++;
}
<ClassTemplSpec>. {
current->name += yytext;
}
<CompoundName>{SCOPENAME}{BN}*";" { // forward declaration
unput(';');
current->reset();
if (isTypedef) // typedef of a class, put typedef keyword back
{
current->type.prepend("typedef");
}
BEGIN( FindMembers );
}
<CompoundName>{SCOPENAME}/"(" {
current->name = yytext ;
lineCount();
if (current->spec & Entry::Protocol)
{
current->name += "-p";
}
BEGIN( ClassVar );
}
<CompoundName>{SCOPENAME}/{BN}*"," { // multiple forward declarations on one line
// e.g. @protocol A,B;
current->reset();
}
<CompoundName>{SCOPENAME} {
current->name = yytext ;
lineCount();
if (current->spec & Entry::Protocol)
{
current->name += "-p";
}
if ((current->spec & Entry::Protocol) ||
current->section == Entry::OBJCIMPL_SEC)
{
unput('{'); // fake start of body
}
BEGIN( ClassVar );
}
<CompoundName>{CSSCOPENAME} { // C# style scope
current->name = substitute(yytext,".","::");
lineCount();
BEGIN( ClassVar );
}
<ClassVar>{SCOPENAME}{BN}*/"(" {
if (insideIDL && strncmp(yytext,"switch",6)==0 && !isId(yytext[6]))
{
// Corba IDL style union
roundCount=0;
BEGIN(SkipUnionSwitch);
}
else
{
addType(current);
current->name = yytext;
current->name = current->name.stripWhiteSpace();
lineCount();
BEGIN( FindMembers );
}
}
<ClassVar>"," {
if (isTypedef)
{
// multiple types in one typedef
unput(',');
current->type.prepend("typedef ");
BEGIN(FindMembers);
}
else
{
// Multiple class forward declaration
}
}
<ClassVar>("sealed"|"abstract")/{BN}*(":"|"{") {
if (insideCli)
{
if (yytext[0]=='s') // sealed
current->spec |= Entry::SealedClass;
else // abstract
current->spec |= Entry::AbstractClass;
BEGIN( ClassVar );
}
else
{
REJECT;
}
}
<ClassVar>{ID} {
if (insideIDL && strcmp(yytext,"switch")==0)
{
// Corba IDL style union
roundCount=0;
BEGIN(SkipUnionSwitch);
}
else if ((insideJava || insidePHP || insideJS) && (strcmp(yytext,"implements")==0 || strcmp(yytext,"extends")==0))
{
current->type.resize(0);
baseProt=Public;
baseVirt=Normal;
baseName.resize(0);
BEGIN( BasesProt ) ;
}
else if (insideCS && strcmp(yytext,"where")==0) // C# type contraint
{
delete current->typeConstr;
current->typeConstr = new ArgumentList;
current->typeConstr->append(new Argument);
lastCSConstraint = YY_START;
BEGIN( CSConstraintName );
}
else if (insideCli && strcmp(yytext,"abstract"))
{
current->spec|=Entry::Abstract;
}
else if (insideCli && strcmp(yytext,"sealed"))
{
current->spec|=Entry::Sealed;
}
else
{
if (current->section == Entry::ENUM_SEC)
{ // found "enum a b" -> variable
current->section = Entry::VARIABLE_SEC ;
}
current->type += ' ' ;
current->type += current->name ;
current->name = yytext ;
if (nameIsOperator(current->name))
{
BEGIN( Operator );
}
}
}
<ClassVar>[(\[] {
if (insideObjC && *yytext=='(') // class category
{
current->name+='(';
if (current->section!=Entry::OBJCIMPL_SEC)
{
current->spec|=Entry::Category;
}
BEGIN( ClassCategory );
}
else
{
// probably a function anyway
unput(*yytext);
BEGIN( FindMembers );
}
}
<CSConstraintType,CSConstraintName>"/**/" { /* empty comment */ }
<CSConstraintType,CSConstraintName>("/*"[*!]|"//"[/!])("<"?) { // special comment
fullArgString.resize(0);
lastCopyArgChar='#'; // end marker
lastCommentInArgContext=YY_START;
if (yytext[1]=='/')
BEGIN( CopyArgCommentLine );
else
BEGIN( CopyArgComment );
}
<CSConstraintType,CSConstraintName>"#" { // artifically inserted token to signal end of comment block
current->typeConstr->last()->docs = fullArgString;
}
<CSConstraintType>"{" { // end of type constraint reached
// parse documentation of the constraints
handleParametersCommentBlocks(current->typeConstr);
unput('{');
BEGIN( lastCSConstraint );
}
<CSConstraintType,CSConstraintName>";" {
handleParametersCommentBlocks(current->typeConstr);
unput(';');
BEGIN( lastCSConstraint );
}
<CSConstraintName>":" {
BEGIN( CSConstraintType );
}
<CSConstraintName>{ID} {
// parameter name
current->typeConstr->last()->name=yytext;
}
<CSConstraintType>"where" { // another constraint for a different param
current->typeConstr->append(new Argument);
BEGIN( CSConstraintName );
}
<CSConstraintType>({ID}".")*{ID}("<"{ID}">")?("()")? {
if (current->typeConstr->last()->type.isEmpty())
// first type constraint for this parameter
{
current->typeConstr->last()->type=yytext;
}
else // new type constraint for same parameter
{
QCString name = current->typeConstr->last()->name;
current->typeConstr->append(new Argument);
current->typeConstr->last()->name=name;
current->typeConstr->last()->type=yytext;
}
}
<CSConstraintName,CSConstraintType>\n {
yyLineNr++;
}
<CSConstraintName,CSConstraintType>. {
}
<ClassCategory>{ID} {
current->name+=yytext;
}
<ClassCategory>")" {
current->name+=')';
if ((current->section & Entry::Protocol) ||
current->section == Entry::OBJCIMPL_SEC)
{
unput('{'); // fake start of body
}
else // category has no variables so push back an empty body
{
unput('}');
unput('{');
}
BEGIN( ClassVar );
}
<ClassVar>":" {
current->type.resize(0);
if ((current->spec & Entry::Interface) ||
(current->spec & Entry::Struct) ||
(current->spec & Entry::Ref) ||
(current->spec & Entry::Value) ||
insidePHP || insideCS || insideD || insideObjC
)
baseProt=Public;
else
baseProt=Private;
baseVirt=Normal;
baseName.resize(0);
BEGIN( BasesProt ) ;
}
<ClassVar>[;=*&] {
unput(*yytext);
if (isTypedef) // typedef of a class, put typedef keyword back
{
current->type.prepend("typedef");
}
BEGIN( FindMembers );
}
<Bases,ClassVar>"///"/[^/] {
if (!insideObjC)
{
REJECT;
}
else
{
lineCount();
current->program+=yytext;
current->fileName = yyFileName ;
current->startLine = yyLineNr ;
curlyCount=0;
BEGIN( ReadBodyIntf );
}
}
<Bases,ClassVar>("//"{B}*)?"/**"/[^/*] |
<Bases,ClassVar>("//"{B}*)?"/*!" |
<Bases,ClassVar>"//!" |
<Bases,ClassVar>[\-+]{BN}* {
if (!insideObjC)
{
REJECT;
}
else
{
lineCount();
current->program+=yytext;
current->fileName = yyFileName ;
current->startLine = yyLineNr ;
curlyCount=0;
BEGIN( ReadBodyIntf );
}
}
<CompoundName,ClassVar>{B}*"{"{B}* {
current->fileName = yyFileName ;
current->startLine = yyLineNr ;
current->name = removeRedundantWhiteSpace(current->name);
if (current->name.isEmpty() && !isTypedef) // anonymous compound
{
if (current->section==Entry::NAMESPACE_SEC) // allow reopening of anonymous namespaces
{
if (Config_getBool("EXTRACT_ANON_NSPACES")) // use visible name
{
current->name="anonymous_namespace{"+stripPath(current->fileName)+"}";
}
else // use invisible name
{
current->name.sprintf("@%d",anonNSCount);
}
}
else
{
current->name.sprintf("@%d",anonCount++);
}
}
curlyCount=0;
if (current_root && // not a nested struct inside an @interface section
!(current_root->spec & Entry::Interface) &&
((current->spec & (Entry::Interface | Entry::Protocol | Entry::Category) ||
current->section==Entry::OBJCIMPL_SEC)
) &&
insideObjC
)
{ // ObjC body that ends with @end
BEGIN( ReadBodyIntf );
}
else if (current->section==Entry::NAMESPACE_SEC)
{ // namespace body
BEGIN( ReadNSBody );
}
else
{ // class body
BEGIN( ReadBody ) ;
}
}
<BasesProt>"virtual"{BN}+ { lineCount(); baseVirt = Virtual; }
<BasesProt>"public"{BN}+ { lineCount(); baseProt = Public; }
<BasesProt>"protected"{BN}+ { lineCount(); baseProt = Protected; }
<BasesProt>"private"{BN}+ { lineCount(); baseProt = Private; }
<BasesProt>{BN} { lineCount(); }
<BasesProt>. { unput(*yytext); BEGIN(Bases); }
<Bases>("::")?{BN}*({ID}{BN}*"::"{BN}*)*{ID} {
QCString baseScope = yytext;
if (insideCS && baseScope.stripWhiteSpace()=="where")
{
// type contraint for a class
delete current->typeConstr;
current->typeConstr = new ArgumentList;
current->typeConstr->append(new Argument);
lastCSConstraint = YY_START;
BEGIN( CSConstraintName );
}
else
{
baseName+=yytext;
current->args += ' ';
current->args += yytext;
}
}
<Bases>{BN}*{ID}("."{ID})* { // Java style class
QCString name = substitute(yytext,".","::");
baseName += name;
current->args += ' ';
current->args += name;
}
<ClassVar,Bases>\n/{BN}*[^{, \t\n] {
if (!insideObjC)
{
REJECT;
}
else
{
yyLineNr++;
unput('{');
}
}
<ClassVar,Bases>"@end" { // empty ObjC interface
unput('d'); // insert fake body: {}@end
unput('n');
unput('e');
unput('@');
unput('}');
unput('{');
}
<ClassVar>"<" { current->name += *yytext;
sharpCount=1;
roundCount=0;
lastSkipSharpContext = YY_START;
specName = ¤t->name;
BEGIN ( Specialization );
}
<Bases>"<" {
sharpCount=1;
roundCount=0;
lastSkipSharpContext = YY_START;
if (insideObjC) // start of protocol list
{
unput(',');
}
else // template specialization
{
baseName += *yytext;
specName = &baseName;
BEGIN ( Specialization );
}
}
<Specialization>"<" { *specName += *yytext;
if (roundCount==0) sharpCount++;
}
<Specialization>">" {
*specName += *yytext;
if (roundCount==0 && --sharpCount<=0)
BEGIN(lastSkipSharpContext);
}
<Specialization>{BN}+ { lineCount(); *specName +=' '; }
<Specialization>"<<" { *specName += yytext; }
<Specialization>">>"/{B}*"::" { // M$ C++ extension to allow >> to close a template...
unput('>');
unput(' ');
unput('>');
}
<Specialization>">>" {
if (insideCS) // for C# >> ends a nested template
{
REJECT;
}
else // for C++ >> is a bitshift
// operator and > > would end
// a nested template.
// We require the bitshift to be enclosed in braces.
// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html
{
if (roundCount>0)
{
*specName += yytext;
}
else
{
unput('>');
unput(' ');
unput('>');
}
}
}
<Specialization>"typename"{BN}+ { lineCount(); }
<Specialization>"(" { *specName += *yytext; roundCount++; }
<Specialization>")" { *specName += *yytext; roundCount--; }
<Specialization>. {
*specName += *yytext;
}
<SkipSharp>"<" { ++sharpCount; }
<SkipSharp>">" { if (--sharpCount<=0)
BEGIN ( lastSkipSharpContext );
}
<SkipRound>"(" { ++roundCount; }
<SkipRound>")" { if (--roundCount<=0)
BEGIN ( lastSkipRoundContext );
}
<Bases>","|(">"({BN}*"{")?)|({BN}+"implements"{BN}*) { lineCount();
if (insideProtocolList)
{
baseName+="-p";
}
else
{
current->args += ',' ;
}
current->name = removeRedundantWhiteSpace(current->name);
if (!baseName.isEmpty())
{
current->extends->append(
new BaseInfo(baseName,baseProt,baseVirt)
);
}
if ((current->spec & Entry::Interface) ||
insideJava || insidePHP || insideCS ||
insideD || insideObjC)
{
baseProt=Public;
}
else
{
baseProt=Private;
}
baseVirt=Normal;
baseName.resize(0);
if (*yytext=='>')
{ // end of a ObjC protocol list
insideProtocolList=FALSE;
if (yyleng==1)
{
unput('{'); // dummy start body
}
else
{
yyless(1);
}
}
else
{
if (*yytext==',' && insideObjC) // Begin of protocol list
{
insideProtocolList=TRUE;
}
BEGIN(BasesProt);
}
}
<Bases>{B}*"{"{B}* { current->fileName = yyFileName ;
current->startLine = yyLineNr ;
current->name = removeRedundantWhiteSpace(current->name);
if (!baseName.isEmpty())
current->extends->append(
new BaseInfo(baseName,baseProt,baseVirt)
);
curlyCount=0;
if (insideObjC)
{
BEGIN( ReadBodyIntf );
}
else
{
BEGIN( ReadBody ) ;
}
}
<SkipUnionSwitch>{B}*"(" {
roundCount++;
}
<SkipUnionSwitch>")" {
if (--roundCount==0)
{
BEGIN(ClassVar);
}
}
<SkipUnionSwitch>\n { yyLineNr++; }
<SkipUnionSwitch>.
<Comment>{BN}+ { current->program += yytext ;
lineCount() ;
}
<Comment>"/*" { current->program += yytext ; }
<Comment>"//" { current->program += yytext ; }
<Comment>{CMD}("code"|"verbatim") {
insideCode=TRUE;
current->program += yytext ;
}
<Comment>{CMD}("endcode"|"endverbatim") {
insideCode=FALSE;
current->program += yytext ;
}
<Comment>[^ \.\t\r\n\/\*]+ { current->program += yytext ; }
<Comment>"*/" { current->program += yytext ;
if (!insideCode) BEGIN( lastContext ) ;
}
<Comment>. { current->program += *yytext ; }
<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>("//"{B}*)?"/*!" {
//printf("Start doc block at %d\n",yyLineNr);
removeSlashes=(yytext[1]=='/');
tmpDocType=-1;
if (!current->doc.isEmpty())
{
current->doc+="\n\n";
}
else
{
current->docLine = yyLineNr;
current->docFile = yyFileName;
}
lastDocContext = YY_START;
if (current_root->section & Entry::SCOPE_MASK)
{
current->inside = current_root->name+"::";
}
docBlockContext = YY_START;
docBlockInBody = YY_START==SkipCurly;
docBlockAutoBrief = Config_getBool("QT_AUTOBRIEF");
docBlock.resize(0);
if (docBlockAutoBrief)
{
current->briefLine = yyLineNr;
current->briefFile = yyFileName;
}
startCommentBlock(FALSE);
BEGIN( DocBlock );
}
<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>("//"{B}*)?"/**"/[^/*] {
removeSlashes=(yytext[1]=='/');
lastDocContext = YY_START;
//printf("Found comment block at %s:%d\n",yyFileName,yyLineNr);
if (current_root->section & Entry::SCOPE_MASK)
{
current->inside = current_root->name+"::";
}
current->docLine = yyLineNr;
current->docFile = yyFileName;
docBlockContext = YY_START;
docBlockInBody = YY_START==SkipCurly;
docBlockAutoBrief = Config_getBool("JAVADOC_AUTOBRIEF");
docBlock.resize(0);
if (docBlockAutoBrief)
{
current->briefLine = yyLineNr;
current->briefFile = yyFileName;
}
startCommentBlock(FALSE);
BEGIN( DocBlock );
}
<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"//!" {
tmpDocType=-1;
lastDocContext = YY_START;
if (current_root->section & Entry::SCOPE_MASK)
{
current->inside = current_root->name+"::";
}
docBlockContext = YY_START;
docBlockInBody = YY_START==SkipCurly;
docBlockAutoBrief = FALSE;
docBlock.resize(0);
startCommentBlock(current->brief.isEmpty());
BEGIN( DocLine );
}
<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"///"/[^/] {
tmpDocType=-1;
lastDocContext = YY_START;
if (current_root->section & Entry::SCOPE_MASK)
{
current->inside = current_root->name+"::";
}
docBlockContext = YY_START;
docBlockInBody = YY_START==SkipCurly;
docBlockAutoBrief = FALSE;
docBlock.resize(0);
startCommentBlock(current->brief.isEmpty());
BEGIN( DocLine );
}
<FindMembers>"extern"{BN}*"\"C"("++")?"\""{BN}*("{")? {
lineCount();
externC=TRUE;
}
<FindMembers>"{" {
if (externC)
{
externC=FALSE;
}
else if (insideCS &&
!current->name.isEmpty() &&
!current->type.isEmpty())
{
if (containsWord(current->type,"event")) // event
{
current->mtype = mtype = Event;
}
else // property
{
current->mtype = mtype = Property;
}
current->bodyLine = yyLineNr;
curlyCount=0;
BEGIN( CSAccessorDecl );
}
else
{
if ((insideJava || insideCS || insideD) &&
current->name.isEmpty()
)
{
// static Java initializer
needsSemi = FALSE;
if (current->stat)
{
current->name="[static initializer]";
current->type.resize(0);
}
else
{
current->name="[instance initializer]";
}
unput(*yytext);
BEGIN( Function );
}
else
{
needsSemi = TRUE;
current->type.resize(0);
current->name.resize(0);
current->args.resize(0);
current->argList->clear();
curlyCount=0;
BEGIN( SkipCurlyBlock );
}
}
}
<CSAccessorDecl>"{" { curlyCount++; }
<CSAccessorDecl>"}" {
if (curlyCount)
{
curlyCount--;
}
else
{
mtype = Method;
unput(';');
BEGIN(FindMembers);
}
}
<CSAccessorDecl>"set" { if (curlyCount==0) current->spec |= Entry::Settable; }
<CSAccessorDecl>"get" { if (curlyCount==0) current->spec |= Entry::Gettable; }
<CSAccessorDecl>"add" { if (curlyCount==0) current->spec |= Entry::Addable; }
<CSAccessorDecl>"remove" { if (curlyCount==0) current->spec |= Entry::Removable; }
<CSAccessorDecl>"raise" { if (curlyCount==0) current->spec |= Entry::Raisable; }
<CSAccessorDecl>. {}
<CSAccessorDecl>\n { yyLineNr++; }
/**********************************************************************************/
/******************** Documentation block related rules ***************************/
/**********************************************************************************/
/* ---- Single line comments ------ */
<DocLine>[^\n]*"\n"[ \t]*"//"[/!] { // continuation of multiline C++-style comment
docBlock+=yytext;
docBlock.resize(docBlock.size() - 3);
yyLineNr++;
}
<DocLine>[^\n]*/"\n" { // whole line
docBlock+=yytext;
handleCommentBlock(docBlock,current->brief.isEmpty());
BEGIN( docBlockContext );
}
/* ---- Comments blocks ------ */
<DocBlock>"*"*"*/" { // end of comment block
handleCommentBlock(docBlock,FALSE);
BEGIN(docBlockContext);
}
<DocBlock>^{B}*("//")?{B}*"*"+/[^//] { // start of a comment line
}
<DocBlock>^{B}*("//"){B}* { // strip embedded C++ comments if at the start of a line
}
<DocBlock>"//" { // slashes in the middle of a comment block
docBlock+=yytext;
}
<DocBlock>"/*" { // start of a new comment in the
// middle of a comment block
docBlock+=yytext;
}
<DocBlock>("@@"|"\\\\"){ID}/[^a-z_A-Z0-9] { // escaped command
docBlock+=yytext;
}
<DocBlock>{CMD}("f$"|"f["|"f{") {
docBlock+=yytext;
docBlockName=&yytext[1];
if (docBlockName.at(1)=='{')
{
docBlockName.at(1)='}';
}
BEGIN(DocCopyBlock);
}
<DocBlock>"<"{PRE}">" {
docBlock+=yytext;
docBlockName="<pre>";
BEGIN(DocCopyBlock);
}
<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9] { // verbatim command (which could contain nested comments!)
docBlock+=yytext;
docBlockName=&yytext[1];
BEGIN(DocCopyBlock);
}
<DocBlock>{B}*"<code>" {
if (insideCS)
{
docBlock+=yytext;
docBlockName="<code>";
BEGIN(DocCopyBlock);
}
else
{
REJECT;
}
}
<DocBlock>[^@*\/\\\n]+ { // any character that isn't special
docBlock+=yytext;
}
<DocBlock>\n { // newline
yyLineNr++;
docBlock+=*yytext;
}
<DocBlock>. { // command block
docBlock+=*yytext;
}
/* ---- Copy verbatim sections ------ */
<DocCopyBlock>"</"{PRE}">" { // end of a <pre> block
docBlock+=yytext;
if (docBlockName=="<pre>")
{
BEGIN(DocBlock);
}
}
<DocCopyBlock>"</"{CODE}">" { // end of a <code> block
docBlock+=yytext;
if (docBlockName=="<code>")
{
BEGIN(DocBlock);
}
}
<DocCopyBlock>[\\@]("f$"|"f]"|"f}") {
docBlock+=yytext;
BEGIN(DocBlock);
}
<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"endmanonly"|"enddot"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block
docBlock+=yytext;
if (&yytext[4]==docBlockName)
{
BEGIN(DocBlock);
}
}
<DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line
if (docBlockName=="verbatim")
{
REJECT;
}
}
<DocCopyBlock>[^\<@/*\]\$\\\n]+ { // any character that is not special
docBlock+=yytext;
}
<DocCopyBlock>"/*"|"*/"|"//" {
docBlock+=yytext;
}
<DocCopyBlock>\n { // newline
docBlock+=*yytext;
yyLineNr++;
}
<DocCopyBlock>. { // any other character
docBlock+=*yytext;
}
<DocCopyBlock><<EOF>> {
warn(yyFileName,yyLineNr,
"Warning: reached end of file while inside a %s block!\n"
"The command that should end the block seems to be missing!\n",
docBlockName.data());
yyterminate();
}
/* ------------- Prototype parser -------------- */
<Prototype>"operator"{B}*"("{B}*")" {
current->name+=yytext;
}
<Prototype>"(" {
current->args+=*yytext;
currentArgumentContext = PrototypeQual;
fullArgString = current->args.copy();
copyArgString = ¤t->args;
BEGIN( ReadFuncArgType ) ;
}
<Prototype>"("({ID}"::")*({B}*[&*])+ {
current->type+=current->name+yytext;
current->name.resize(0);
BEGIN( PrototypePtr );
}
<PrototypePtr>{SCOPENAME} {
current->name+=yytext;
}
<PrototypePtr>"(" {
current->args+=*yytext;
currentArgumentContext = PrototypeQual;
fullArgString = current->args.copy();
copyArgString = ¤t->args;
BEGIN( ReadFuncArgType ) ;
}
<PrototypePtr>")" {
current->type+=')';
BEGIN( Prototype );
}
<PrototypePtr>. {
current->name+=yytext;
}
<PrototypeQual>"{" {
BEGIN( PrototypeSkipLine);
}
<PrototypeQual>{B}*"const"{B}* {
current->args += " const ";
current->argList->constSpecifier=TRUE;
}
<PrototypeQual>{B}*"volatile"{B}* {
current->args += " volatile ";
current->argList->volatileSpecifier=TRUE;
}
<PrototypeQual>{B}*"="{B}*"0"{B}* {
current->args += " = 0";
current->virt = Pure;
current->argList->pureSpecifier=TRUE;
}
<PrototypeQual>"throw"{B}*"(" {
current->exception = "throw(";
BEGIN(PrototypeExc);
}
<PrototypeExc>")" {
current->exception += ')';
BEGIN(PrototypeQual);
}
<PrototypeExc>. {
current->exception += *yytext;
}
<PrototypeQual>. {
current->args += *yytext;
}
<Prototype>. {
current->name += *yytext;
}
<PrototypeSkipLine>. {
}
/* ------------ Generic rules -------------- */
<SkipCxxComment>.*"\\\n" { // line continuation
yyLineNr++;
}
<SkipCxxComment>.*/\n {
BEGIN( lastCContext ) ;
}
<SkipComment>[^\*\n]+
<*>\n { yyLineNr++ ; }
<*>\" {
if (insideIDL && insideCppQuote)
{
BEGIN(EndCppQuote);
}
}
<*>"#" {
if (!insidePHP)
REJECT;
lastCContext = YY_START ;
BEGIN( SkipCxxComment ) ;
}
<*>\' {
if (insidePHP)
{
lastStringContext=YY_START;
BEGIN(SkipPHPString);
}
}
<*>\" {
if (insidePHP)
{
lastStringContext=YY_START;
BEGIN(SkipString);
}
}
<*>.
<SkipComment>"//"|"/*"
<*>"/*" { lastCContext = YY_START ;
BEGIN( SkipComment ) ;
}
<SkipComment>{B}*"*/" { BEGIN( lastCContext ) ; }
<*>"//" {
lastCContext = YY_START ;
BEGIN( SkipCxxComment ) ;
}
%%
//----------------------------------------------------------------------------
static void startCommentBlock(bool brief)
{
if (brief)
{
current->briefFile = yyFileName;
current->briefLine = yyLineNr;
}
else
{
current->docFile = yyFileName;
current->docLine = yyLineNr;
}
}
//----------------------------------------------------------------------------
static void newEntry()
{
current_root->addSubEntry(current);
previous = current;
current = new Entry ;
initEntry();
}
static void handleCommentBlock(const QCString &doc,bool brief)
{
static bool hideInBodyDocs = Config_getBool("HIDE_IN_BODY_DOCS");
int position=0;
bool needsEntry=FALSE;
if (docBlockInBody && hideInBodyDocs) return;
//printf("parseCommentBlock [%s]\n",doc.data());
int lineNr = brief ? current->briefLine : current->docLine; // line of block start
while (parseCommentBlock(
g_thisParser,
docBlockInBody && previous ? previous : current,
doc, // text
yyFileName, // file
lineNr, // line of block start
docBlockInBody ? FALSE : brief,
docBlockInBody ? FALSE : docBlockAutoBrief,
docBlockInBody,
protection,
position,
needsEntry
)
)
{
//printf("parseCommentBlock position=%d [%s]\n",position,doc.data()+position);
if (needsEntry) newEntry();
}
if (needsEntry)
{
newEntry();
}
if (docBlockTerm)
{
unput(docBlockTerm);
docBlockTerm=0;
}
}
static void handleParametersCommentBlocks(ArgumentList *al)
{
//printf(">>>>>>> handleParametersCommentBlocks()\n");
ArgumentListIterator ali(*al);
Argument *a;
for (ali.toFirst();(a=ali.current());++ali)
{
//printf(" Param %s docs=%s\n",a->name.data(),a->docs.data());
if (!a->docs.isEmpty())
{
int position=0;
bool needsEntry;
// save context
QCString orgDoc = current->doc;
QCString orgBrief = current->brief;
int orgDocLine = current->docLine;
int orgBriefLine = current->briefLine;
current->doc.resize(0);
current->brief.resize(0);
//printf("handleParametersCommentBlock [%s]\n",doc.data());
while (parseCommentBlock(
g_thisParser,
current,
a->docs, // text
yyFileName, // file
current->docLine, // line of block start
FALSE,
FALSE,
FALSE,
protection,
position,
needsEntry
)
)
{
//printf("handleParametersCommentBlock position=%d [%s]\n",position,doc.data()+position);
if (needsEntry) newEntry();
}
if (needsEntry)
{
newEntry();
}
a->docs = current->doc;
// restore context
current->doc = orgDoc;
current->brief = orgBrief;
current->docLine = orgDocLine;
current->briefLine = orgBriefLine;
}
}
}
//----------------------------------------------------------------------------
static void parseCompounds(Entry *rt)
{
//printf("parseCompounds(%s)\n",rt->name.data());
g_inputFromFile = FALSE;
EntryListIterator eli(*rt->children());
Entry *ce;
for (;(ce=eli.current());++eli)
{
if (!ce->program.isEmpty())
{
//printf("-- %s ---------\n%s\n---------------\n",
// ce->name.data(),ce->program.data());
// init scanner state
padCount=0;
depthIf = 0;
inputString = ce->program;
inputPosition = 0;
scanYYrestart( scanYYin ) ;
if (ce->section==Entry::ENUM_SEC)
BEGIN( FindFields ) ;
else
BEGIN( FindMembers ) ;
current_root = ce ;
yyFileName = ce->fileName;
//setContext();
yyLineNr = ce->startLine ;
insideObjC = ce->objc;
//printf("---> Inner block starts at line %d objC=%d\n",yyLineNr,insideObjC);
//current->reset();
if (current) delete current;
current = new Entry;
gstat = FALSE;
int ni=ce->name.findRev("::"); if (ni==-1) ni=0; else ni+=2;
// set default protection based on the compound type
if( ce->section==Entry::CLASS_SEC ) // class
{
if (insidePHP || insideD || insideJS)
{
current->protection = protection = Public ;
}
else if (insideJava)
{
current->protection = protection = Package ;
}
else if (ce->spec&(Entry::Interface | Entry::Ref | Entry::Value | Entry::Struct | Entry::Union))
{
if (ce->objc)
{
current->protection = protection = Protected ;
}
else
{
current->protection = protection = Public ;
}
}
else
{
current->protection = protection = Private ;
}
}
else if (ce->section == Entry::ENUM_SEC ) // enum
{
current->protection = protection = ce->protection;
}
else if (!ce->name.isEmpty() && ce->name.at(ni)=='@') // unnamed union or namespace
{
if (ce->section == Entry::NAMESPACE_SEC ) // unnamed namespace
{
current->stat = gstat = TRUE;
}
current->protection = protection = ce->protection;
}
else // named struct, union, protocol, category
{
current->protection = protection = Public ;
}
mtype = Method;
virt = Normal;
//printf("name=%s current->stat=%d gstat=%d\n",ce->name.data(),current->stat,gstat);
//memberGroupId = DOX_NOGROUP;
//memberGroupRelates.resize(0);
//memberGroupInside.resize(0);
groupEnterCompound(yyFileName,yyLineNr,ce->name);
scanYYlex() ;
g_lexInit=TRUE;
//forceEndGroup();
groupLeaveCompound(yyFileName,yyLineNr,ce->name);
delete current; current=0;
ce->program.resize(0);
if (depthIf>0)
{
warn(yyFileName,yyLineNr,"Documentation block ended in the middle of a conditional section!");
}
}
parseCompounds(ce);
}
}
//----------------------------------------------------------------------------
static void parseMain(const char *fileName,const char *fileBuf,Entry *rt)
{
initParser();
//g_inputFromFile = TRUE;
inputString = fileBuf;
inputPosition = 0;
g_inputFromFile = FALSE;
//anonCount = 0; // don't reset per file
depthIf = 0;
protection = Public;
mtype = Method;
gstat = FALSE;
virt = Normal;
current_root = rt;
global_root = rt;
inputFile.setName(fileName);
if (inputFile.open(IO_ReadOnly))
{
yyLineNr= 1 ;
yyFileName = fileName;
setContext();
msg("Parsing file %s...\n",yyFileName.data());
current_root = rt ;
initParser();
groupEnterFile(yyFileName,yyLineNr);
current = new Entry;
//printf("current=%p current_root=%p\n",current,current_root);
int sec=guessSection(yyFileName);
if (sec)
{
current->name = yyFileName;
current->section = sec;
current_root->addSubEntry(current);
current = new Entry;
}
current->reset();
scanYYrestart( scanYYin );
if ( insidePHP )
{
BEGIN( FindMembersPHP );
}
else
{
BEGIN( FindMembers );
}
scanYYlex();
g_lexInit=TRUE;
if (YY_START==Comment)
{
warn(yyFileName,yyLineNr,"File ended in the middle of a comment block! Perhaps a missing \\endcode?");
}
//forceEndGroup();
groupLeaveFile(yyFileName,yyLineNr);
if (depthIf>0)
{
warn(yyFileName,yyLineNr,"Documentation block ended in the middle of a conditional section!");
}
rt->program.resize(0);
delete current; current=0;
parseCompounds(rt);
inputFile.close();
anonNSCount++;
}
}
//----------------------------------------------------------------------------
static void parsePrototype(const QCString &text)
{
//printf("**** parsePrototype(%s) begin\n",text.data());
if (text.isEmpty())
{
warn(yyFileName,yyLineNr,"Empty prototype found!");
return;
}
const char *orgInputString;
int orgInputPosition;
YY_BUFFER_STATE orgState;
bool orgInputFromFile;
// save scanner state
orgState = YY_CURRENT_BUFFER;
yy_switch_to_buffer(yy_create_buffer(scanYYin, YY_BUF_SIZE));
orgInputString = inputString;
orgInputPosition = inputPosition;
orgInputFromFile = g_inputFromFile;
// set new string
inputString = text;
inputPosition = 0;
g_inputFromFile = FALSE;
scanYYrestart( scanYYin );
BEGIN(Prototype);
scanYYlex();
g_lexInit=TRUE;
current->name = current->name.stripWhiteSpace();
if (current->section == Entry::MEMBERDOC_SEC && current->args.isEmpty())
current->section = Entry::VARIABLEDOC_SEC;
// restore original scanner state
YY_BUFFER_STATE tmpState = YY_CURRENT_BUFFER;
yy_switch_to_buffer(orgState);
yy_delete_buffer(tmpState);
inputString = orgInputString;
inputPosition = orgInputPosition;
g_inputFromFile = orgInputFromFile;
//printf("**** parsePrototype end\n");
}
void scanFreeScanner()
{
#if defined(YY_FLEX_SUBMINOR_VERSION)
if (g_lexInit)
{
scanYYlex_destroy();
}
#endif
}
//static void handleGroupStartCommand(const char *header)
//{
// memberGroupHeader=header;
// startGroupInDoc();
//}
//
//static void handleGroupEndCommand()
//{
// endGroup();
// previous=0;
//}
//----------------------------------------------------------------------------
void CLanguageScanner::parseInput(const char *fileName,const char *fileBuf,Entry *root)
{
g_thisParser = this;
::parseMain(fileName,fileBuf,root);
}
void CLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf,
const char * scopeName,
const QCString & input,
bool isExampleBlock,
const char * exampleName,
FileDef * fileDef,
int startLine,
int endLine,
bool inlineFragment,
MemberDef *memberDef
)
{
::parseCCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName,
fileDef,startLine,endLine,inlineFragment,memberDef);
}
bool CLanguageScanner::needsPreprocessing(const QCString &extension)
{
QCString fe=extension.lower();
return
!( fe==".java" || fe==".as" || fe==".d" || fe==".php" ||
fe==".php4" || fe==".inc" || fe==".phtml"
);
}
void CLanguageScanner::resetCodeParserState()
{
::resetCCodeParserState();
}
void CLanguageScanner::parsePrototype(const char *text)
{
::parsePrototype(text);
}
//----------------------------------------------------------------------------
#if !defined(YY_FLEX_SUBMINOR_VERSION)
//----------------------------------------------------------------------------
extern "C" { // some bogus code to keep the compiler happy
void scannerYYdummy() { yy_flex_realloc(0,0); }
}
#endif