/***************************************************************************** * * * * Copyright (C) 1997-2005 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 #include #include #include #include "qtbc.h" #include #include #include #include #include #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 lastAfterDocContext; static int lastInitializerContext; static int lastClassTemplSpecContext; static int lastPreLineCtrlContext; static int lastSkipVerbStringContext; static int lastCommentInArgContext; 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 int yyLineNr = 1 ; static int anonCount = 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 int memberGroupId = DOX_NOGROUP; //static QCString memberGroupHeader; //static QCString memberGroupDocs; 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 insideCppQuote = FALSE; static bool insideObjC = FALSE; //!< processing Objective C code? 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 *pCopyRoundString; static QCString *pCopyCurlyString; static QCString *pCopyQuotedString; static QCString *pSkipVerbString; static QStack 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 docBlockJavaStyle; static char docBlockTerm; //----------------------------------------------------------------------------- // 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; //memberGroupId = DOX_NOGROUP; //memberGroupRelates.resize(0); //memberGroupInside.resize(0); mtype = Method; gstat = FALSE; virt = Normal; baseVirt = Normal; isTypedef = FALSE; autoGroupStack.clear(); insideTryBlock = FALSE; autoGroupStack.setAutoDelete(TRUE); insideFormula = FALSE; insideCode=FALSE; previous = 0; } static void initEntry() { if (insideJava) { protection = current_root->section==Entry::INTERFACE_SEC ? Public : Package; } current->protection = protection ; current->mtype = mtype; current->virt = virt; current->stat = gstat; //current->mGrpId = memberGroupId; //current->relates = memberGroupRelates; //current->inside = memberGroupInside; current->objc = insideObjC; //if (!autoGroupStack.isEmpty()) //{ // //printf("Appending group %s\n",autoGroupStack.top()->groupname.data()); // current->groups->append(new Grouping(*autoGroupStack.top())); //} initGroupInfo(current); } //----------------------------------------------------------------------------- ///// 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 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; insideIDL = fileName.right(4)==".idl" || fileName.right(5)==".pidl" || fileName.right(4)==".odl"; insideJava = fileName.right(5)==".java" || fileName.right(3)==".as"; insideCS = fileName.right(3)==".cs"; // for normal keywords add colon insideD = fileName.right(2)==".d"; // for normal keywords add colon insidePHP = fileName.right(4)==".php" || fileName.right(5)==".php4" || fileName.right(4)==".inc" || fileName.right(6)==".phtml"; insideObjC = fileName.right(2)==".m" || fileName.right(2)==".M" || fileName.right(3)==".mm"; 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; current->tArgLists->setAutoDelete(TRUE); } //printf("prependScope #=%d #current=%d\n",current_root->tArgLists->count(),current->tArgLists->count()); QListIterator talsi(*current_root->tArgLists); ArgumentList *srcAl=0; for (talsi.toLast();(srcAl=talsi.current());--talsi) { ArgumentList *dstAl = new ArgumentList; dstAl->setAutoDelete(TRUE); QListIterator 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; 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 (iargs.at(i))=='*' || isspace((uchar)c))) i++; oldStyleArgType += current->args.mid(s,i-s); s=i; while (iargs.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 (iargs.at(i))=='*' || isspace((uchar)c))) i++; oldStyleArgType += current->args.mid(s,i-s); s=i; while (iargs.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 (jargs.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; } } } } //----------------------------------------------------------------------------- /* ----------------------------------------------------------------- */ #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"|"latexonly"|"htmlonly"|"xmlonly"|"{"|"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\\:\\\/\-\+] FILEECHAR [a-z_A-Z0-9\-\+] FILE ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]+"\"") ID "$"?[a-z_A-Z][a-z_A-Z0-9]* LABELID [a-z_A-Z][a-z_A-Z0-9\-]* SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?) SCOPENAME "$"?(({ID}?{BN}*"::"{BN}*)*)((~{BN}*)?{ID}) TSCOPE {ID}("<"[a-z_A-Z0-9 \t\*\&]*">")? CSSCOPENAME (({ID}?{BN}*"."{BN}*)*)((~{BN}*)?{ID}) ATTR ({B}+[^>\n]*)? A [aA] BR [bB][rR] PRE [pP][rR][eE] TABLE [tT][aA][bB][lL][eE] P [pP] UL [uU][lL] OL [oO][lL] DL [dD][lL] TITLE [tT][iI][tT][lL][eE] CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^' \\\n]{1,4}"'")) PHPKW ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;] IDLATTR ("["[^\]]*"]"){BN}* %option noyywrap /* language parsing states */ %x Define %x DefineEnd %x CompoundName %x ClassVar %x ClassCategory %x ClassTemplSpec %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 TypedefName %x TryFunctionBlock %x TryFunctionBlockEnd %x Comment %x PackageName %x JavaImport %x CSAccessorDecl %x PreLineCtrl %x DefinePHP %x DefinePHPEnd %x OldStyleArgs %x SkipVerbString %x ObjCMethod %x ObjCReturnType %x ObjCParams %x ObjCParamType %x ObjCProtocolList %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 EndFuncPtr %x ReadFuncArgType %x ReadTempArgs %x IDLUnionCase %x NSAliasName %x NSAliasArg %x CopyString %x CopyPHPString %x CopyRound %x CopyCurly %x SkipUnionSwitch %x Specialization %x FuncPtrInit %x FuncFunc %x FuncFuncEnd %x FuncFuncType %x CopyArgString %x CopyArgPHPString %x CopyArgRound %x CopyArgSharp %x CopyArgComment %x CopyArgCommentLine /** Prototype scanner states */ %x Prototype %x PrototypePtr %x PrototypeQual %x PrototypeExc %x PrototypeSkipLine /** comment parsing states */ %x DocLine %x DocBlock %x DocCopyBlock %% "{" { curlyCount=0; needsSemi = TRUE; BEGIN(SkipCurlyBlock); } "(" { roundCount=0; BEGIN(SkipRoundBlock); } "(" { ++roundCount; } ")" { if (roundCount ) --roundCount ; else BEGIN( NextSemi ) ; } "{" { ++curlyCount ; } "}" { if( curlyCount ) { --curlyCount ; } else if (needsSemi) { BEGIN( NextSemi ); } else { BEGIN( FindMembers ); } } \' { if (insidePHP) { lastStringContext=NextSemi; BEGIN(SkipPHPString); } } {CHARLIT} { if (insidePHP) REJECT; } \" { lastStringContext=NextSemi; BEGIN(SkipString); } [;,] { unput(*yytext); BEGIN( FindMembers ); } [;,] { unput(*yytext); BEGIN( FindMembers ); } "[^\n<]+ { // Non-PHP code text, ignore } \n { // Non-PHP code text, ignore yyLineNr++; } . { // Non-PHP code text, ignore } "?>" { // PHP code end if (insidePHP) BEGIN( FindMembersPHP ); else REJECT; } {PHPKW} { if (insidePHP) BEGIN( NextSemi ); else REJECT; } {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() ; } {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() ; } {B}*"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() ; } {B}*"public"{BN}*"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(); } {B}*"protected"{BN}*"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(); } {B}*"private"{BN}*"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(); } {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() ; } {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() ; } {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() ; } {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() ; } {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() ; } {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() ; } [\-+]{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 ); } } "(" { // start of method's return type BEGIN( ObjCReturnType ); } {ID} { // found method name if (current->type.isEmpty()) { current->type = "id"; } current->name = yytext; } ":"{B}* { // start of parameter list current->name += ':'; Argument *a = new Argument; current->argList->append(a); BEGIN( ObjCParams ); } [^)]* { // TODO: check if nested braches are possible. current->type = yytext; } ")" { BEGIN( ObjCMethod ); } ({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); } {ID}{BN}* { // name of parameter lineCount(); current->argList->getLast()->name=QCString(yytext).stripWhiteSpace(); } ","{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); } /* ":" { current->name += ':'; } */ "(" { BEGIN( ObjCParamType ); } [^)]* { current->argList->getLast()->type=QCString(yytext).stripWhiteSpace(); } ")"/{B}* { BEGIN( 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 ); } (";"{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 ); } {BN}{1,80} { lineCount(); } {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 ) ; } ";" { BEGIN(FindMembers); } {B}*"static"{BN}+ { current->type += " static "; current->stat = TRUE; lineCount(); } {B}*"extern"{BN}+ { current->stat = FALSE; current->explicitExternal = TRUE; lineCount(); } {B}*"virtual"{BN}+ { current->type += " virtual "; current->virt = Virtual; lineCount(); } {B}*"abstract"{BN}+ { if (!insidePHP) { current->type += " abstract "; current->virt = Pure; } else { current->memSpec|=Entry::Abstract; } lineCount(); } {B}*"inline"{BN}+ { current->memSpec|=Entry::Inline; lineCount(); } {B}*"mutable"{BN}+ { current->memSpec|=Entry::Mutable; lineCount(); } {B}*"explicit"{BN}+ { current->memSpec|=Entry::Explicit; lineCount(); } /* {B}*"import"{BN}+ { // IDL import keyword BEGIN( NextSemi ); } */ {B}*"typename"{BN}+ { lineCount(); } {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 ); } {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(); } } {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(); } } {B}*((("disp")?"interface")|"valuetype"){BN}+ { // M$/Corba IDL interface lineCount(); if (insideIDL || insideJava || insideCS || insideD || insidePHP) { isTypedef=FALSE; current->section = Entry::INTERFACE_SEC; addType( current ) ; current->type += " interface" ; current->fileName = yyFileName; current->startLine = yyLineNr; current->bodyLine = yyLineNr; BEGIN( CompoundName ); } else { addType( current ) ; current->name = QCString(yytext).stripWhiteSpace(); } } {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 ); } {B}*"@interface"{BN}+ { // Objective-C class interface lineCount(); isTypedef=FALSE; current->section = Entry::INTERFACE_SEC; current->objc = insideObjC = TRUE; current->protection = protection = Public ; addType( current ) ; current->type += " interface" ; current->fileName = yyFileName; current->startLine = yyLineNr; current->bodyLine = yyLineNr; BEGIN( CompoundName ); } {B}*"@protocol"{BN}+ { // Objective-C protocol definition lineCount(); isTypedef=FALSE; current->section = Entry::PROTOCOL_SEC; current->objc = insideObjC = TRUE; current->protection = protection = Public ; addType( current ) ; current->type += " protocol" ; current->fileName = yyFileName; current->startLine = yyLineNr; current->bodyLine = yyLineNr; BEGIN( CompoundName ); } {B}*"exception"{BN}+ { // Corba IDL exception isTypedef=FALSE; current->section = Entry::EXCEPTION_SEC; addType( current ) ; current->type += " exception" ; current->fileName = yyFileName; current->startLine = yyLineNr; current->bodyLine = yyLineNr; lineCount(); BEGIN( CompoundName ); } "@class" | // for Objective C class declarations {B}*(("typedef"{BN}+)?)("volatile"{BN}+)?"class{" | {B}*(("typedef"{BN}+)?)("volatile"{BN}+)?"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; lineCount() ; if (yytext[yyleng-1]=='{') unput('{'); BEGIN( CompoundName ) ; } {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(); } } {B}*(("typedef"{BN}+)?)("volatile"{BN}+)?"struct{" | {B}*(("typedef"{BN}+)?)("volatile"{BN}+)?"struct"/{BN}+ { isTypedef=((QCString)yytext).find("typedef")!=-1; current->section = Entry::STRUCT_SEC ; addType( current ) ; current->type += " struct" ; current->fileName = yyFileName; current->startLine = yyLineNr; current->bodyLine = yyLineNr; lineCount() ; if (yytext[yyleng-1]=='{') unput('{'); BEGIN( CompoundName ) ; } {B}*(("typedef"{BN}+)?)("volatile"{BN}+)?"union{" | {B}*(("typedef"{BN}+)?)("volatile"{BN}+)?"union"{BN}+ { isTypedef=((QCString)yytext).find("typedef")!=-1; current->section = Entry::UNION_SEC ; addType( current ) ; current->type += " union" ; current->fileName = yyFileName; current->startLine = yyLineNr; current->bodyLine = yyLineNr; lineCount() ; if (yytext[yyleng-1]=='{') unput('{'); BEGIN( CompoundName ) ; } {B}*(("typedef"{BN}+)?){IDLATTR}?"enum{" | {B}*(("typedef"{BN}+)?){IDLATTR}?"enum"{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 ) ; } "("{BN}*")"({BN}*"<"[^>]*">"){BN}*/"(" { // A::operator()(int arg) lineCount(); current->name += "()"; BEGIN( FindMembers ); } "("{BN}*")"{BN}*/"(" { lineCount(); current->name += yytext ; current->name = current->name.simplifyWhiteSpace(); BEGIN( FindMembers ) ; } ";" { // can occur when importing members unput(';'); BEGIN( FindMembers ) ; } [^(] { lineCount(); current->name += *yytext ; } "<>" { /* skip guided templ specifiers */ } "(" { current->name = current->name.simplifyWhiteSpace(); unput(*yytext); BEGIN( FindMembers ) ; } "template"({BN}*)"<"/[>]? { lineCount(); if (current->tArgLists==0) { current->tArgLists = new QList; current->tArgLists->setAutoDelete(TRUE); } ArgumentList *al = new ArgumentList; al->setAutoDelete(TRUE); current->tArgLists->append(al); currentArgumentList = al; templateStr="<"; fullArgString = templateStr.copy(); copyArgString = &templateStr; currentArgumentContext = FindMembers; BEGIN( ReadTempArgs ); } "namespace"{BN}+/{ID}{BN}*"=" { // namespace alias lineCount(); BEGIN( NSAliasName ); } {ID} { aliasName = yytext; BEGIN( 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)); //} } ";" { BEGIN( FindMembers ); } ({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); } ({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); } "using"{BN}+ { current->startLine=yyLineNr; lineCount(); BEGIN(Using); } "namespace"{BN}+ { lineCount(); BEGIN(UsingDirective); } {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); } {SCOPENAME} { current->name=removeRedundantWhiteSpace(yytext); current->fileName = yyFileName; current->section=Entry::USINGDIR_SEC; current_root->addSubEntry(current); current = new Entry ; initEntry(); BEGIN(Using); } ";" { BEGIN(FindMembers); } {SCOPENAME}{BN}*"<>" { // guided template decl QCString n=yytext; addType( current ); current->name=n.left(n.length()-2); } {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 ); } {SCOPENAME}{BN}*/"<" { sharpCount=0; lineCount(); current->name+=((QCString)yytext).stripWhiteSpace(); //current->memberSpec.resize(0); // currentTemplateSpec = ¤t->memberSpec; if (nameIsOperator(current->name)) BEGIN( Operator ); else BEGIN( EndTemplate ); } "<<" { current->name+=yytext; // *currentTemplateSpec+=yytext; } "<" { current->name+='<'; // *currentTemplateSpec+='<'; sharpCount++; } ">>" { current->name+=yytext; // *currentTemplateSpec+=yytext; } ">" { current->name+='>'; // *currentTemplateSpec+='>'; if (--sharpCount<=0) { //printf("Found %s\n",current->name.data()); BEGIN(FindMembers); } } ">"{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 ) ; } } ">"{BN}*/"("({BN}*{ID}{BN}*"::")*({BN}*"*"{BN}*)+ { // function pointer returning a template instance lineCount(); current->name+='>'; BEGIN(FindMembers); } ">"{BN}*/"::" { lineCount(); current->name+='>'; // *currentTemplateSpec+='>'; if (--sharpCount<=0) { BEGIN(FindMemberName); } } . { current->name+=*yytext; // *currentTemplateSpec+=*yytext; } "define"{BN}*"("{BN}*["'] { if (insidePHP) { current->bodyLine = yyLineNr; BEGIN( DefinePHP ); } else REJECT; } "Q_OBJECT" { // Qt object macro } "Q_PROPERTY" { // Qt property declaration current->protection = protection = Public ; current->mtype = mtype = Property; current->type.resize(0); BEGIN(QtPropType); } "(" { // start of property arguments } ")" { // end of property arguments unput(';'); BEGIN(FindMembers); } "const"|"volatile" { current->type+=yytext; } {B}+ { current->type+=yytext; } {ID} { current->type+=yytext; BEGIN(QtPropName); } {ID} { current->name=yytext; BEGIN(QtPropAttr); } "READ" { current->memSpec |= Entry::Readable; BEGIN(QtPropRead); } "WRITE" { current->memSpec |= Entry::Writable; BEGIN(QtPropWrite); } "RESET"{B}+{ID} { // reset method => not supported yet } "SCRIPTABLE"{B}+{ID} { // scriptable property => not supported yet } "DESIGNABLE"{B}+{ID} { // designable property => not supported yet } {ID} { current->read = yytext; BEGIN(QtPropAttr); } {ID} { current->write = yytext; BEGIN(QtPropAttr); } "friend"{BN}+("class"|"union"|"struct"){BN}+ { current->name=yytext; BEGIN(FindMembers); } {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 (YY_START==FindMembers) { addType( current ) ; } bool javaLike = insideJava || insideCS || insideD || insidePHP; 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 (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); } } } "." { if (insideJava || insideCS || insideD) { current->name+="."; } } "::" { current->name+=yytext; } "("{B}*"\"" { insideCppQuote=TRUE; BEGIN(FindMembers); } "::" ":" { BEGIN(FindMembers); } \n { yyLineNr++; } . \n { yyLineNr++; } "{" { curlyCount=0; lastCurlyContext = TryFunctionBlockEnd ; BEGIN( SkipCurly ); } . "catch" { BEGIN(TryFunctionBlock); } . { unput(*yytext); BEGIN( FindMembers ); } ")" { insideCppQuote=FALSE; BEGIN(FindMembers); } {B}*"#" { if (insidePHP) REJECT; lastCPPContext = YY_START; BEGIN( SkipCPP ) ; } {B}*"#"{B}*"define" { if (insidePHP) REJECT; current->bodyLine = yyLineNr; BEGIN( Define ); } {B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */ yyLineNr = atoi(&yytext[1]); //printf("setting line number to %d\n",yyLineNr); lastPreLineCtrlContext = YY_START; BEGIN( PreLineCtrl ); } "\""[^\n\"]*"\"" { yyFileName = stripQuotes(yytext); } . {} \n { yyLineNr++; BEGIN( lastPreLineCtrlContext ); } . \\[\r]*"\n"[\r]* { yyLineNr++ ; } [\r]*\n[\r]* { yyLineNr++ ; BEGIN( lastCPPContext) ; } {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 ) ; } /* ")" { //printf("Define with args\n"); current->args += ')'; BEGIN( DefineEnd ); } . { current->args += *yytext; } */ {ID} { //printf("Define `%s' without args\n",yytext); current->bodyLine = yyLineNr; current->name = yytext; BEGIN(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); } ";" { //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); } . \\[\r]?\n { yyLineNr++; } \" { if (insideIDL && insideCppQuote) { BEGIN(EndCppQuote); } else { lastStringContext=DefineEnd; BEGIN(SkipString); } } . {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 ); } [*&]+ { current->name += yytext ; addType( current ); } ";"{BN}*("/**"|"//!"|"/*!"|"///")"<" { lineCount(); if (current->bodyLine==-1) { current->bodyLine=yyLineNr; } docBlockContext = YY_START; docBlockInBody = FALSE; docBlockJavaStyle = yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF"); docBlock.resize(0); docBlockTerm = ';'; if (yytext[yyleng-3]=='/') { startCommentBlock(TRUE); BEGIN( DocLine ); } else { startCommentBlock(FALSE); BEGIN( DocBlock ); } } ","{BN}*("/**"|"//!"|"/*!"|"///")"<" { lineCount(); docBlockContext = YY_START; docBlockInBody = FALSE; docBlockJavaStyle = yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF"); docBlock.resize(0); docBlockTerm = ','; if (yytext[yyleng-3]=='/') { startCommentBlock(TRUE); BEGIN( DocLine ); } else { startCommentBlock(FALSE); BEGIN( DocBlock ); } } {BN}*("/**"|"//!"|"/*!"|"///")"<" { lineCount(); if (current->bodyLine==-1) { current->bodyLine=yyLineNr; } docBlockContext = YY_START; docBlockInBody = FALSE; docBlockJavaStyle = yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF"); docBlock.resize(0); docBlockTerm = 0; if (yytext[yyleng-3]=='/') { startCommentBlock(TRUE); BEGIN( DocLine ); } else { startCommentBlock(FALSE); BEGIN( DocBlock ); } } ("//"([!/]?){B}*{CMD}"{")|("/*"([!*]?){B}*{CMD}"{") { //Entry *tmp = current; //if (previous) //{ // current = previous; //} //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; docBlockJavaStyle = 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); docBlockJavaStyle = yytext[2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF"); docBlockTerm = 0; startCommentBlock(FALSE); BEGIN(DocBlock); } else { lastCContext=YY_START; BEGIN(SkipComment); } } } "//"([!/]?){B}*{CMD}"}".*|"/*"([!*]?){B}*{CMD}"}".*"*/" { closeGroup(current,yyFileName,yyLineNr); } "=" { current->bodyLine = yyLineNr; lastInitializerContext = YY_START; initBracketCount=0; BEGIN(ReadInitializer); } /* Read initializer rules */ "(" { lastRoundContext=YY_START; pCopyRoundString=¤t->initializer; roundCount=0; current->initializer+=*yytext; BEGIN(CopyRound); } "{" { lastCurlyContext=YY_START; pCopyCurlyString=¤t->initializer; curlyCount=0; current->initializer+=*yytext; BEGIN(CopyCurly); } [;,] { //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; } } \" { if (insideIDL && insideCppQuote) { BEGIN(EndCppQuote); } else { lastStringContext=YY_START; current->initializer+=*yytext; pCopyQuotedString=¤t->initializer; BEGIN(CopyString); } } "->" { current->initializer+=yytext; } "<<" { current->initializer+=yytext; } ">>" { current->initializer+=yytext; } [<\[{(] { initBracketCount++; current->initializer+=*yytext; } [>\]})] { initBracketCount--; current->initializer+=*yytext; } \' { if (insidePHP) { current->initializer+=yytext; pCopyQuotedString = ¤t->initializer; lastStringContext=YY_START; BEGIN(CopyPHPString); } else { current->initializer+=yytext; } } {CHARLIT} { if (insidePHP) { REJECT; } else { current->initializer+=yytext; } } \n { current->initializer+=*yytext; yyLineNr++; } "@\"" { //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); } } [^\n"]+ { *pSkipVerbString+=yytext; } "\"\"" { // quote escape *pSkipVerbString+=yytext; } "\"" { *pSkipVerbString+=*yytext; BEGIN(lastSkipVerbStringContext); } \n { *pSkipVerbString+=*yytext; yyLineNr++; } . { *pSkipVerbString+=*yytext; } . { current->initializer+=*yytext; } /* generic quoted string copy rules */ \\. { *pCopyQuotedString+=yytext; } \" { *pCopyQuotedString+=*yytext; BEGIN( lastStringContext ); } \' { *pCopyQuotedString+=*yytext; BEGIN( lastStringContext ); } "/*"|"*/"|"//" { *pCopyQuotedString+=yytext; } \n { *pCopyQuotedString+=*yytext; yyLineNr++; } . { *pCopyQuotedString+=*yytext; } /* generic round bracket list copy rules */ \" { *pCopyRoundString+=*yytext; pCopyQuotedString=pCopyRoundString; lastStringContext=YY_START; BEGIN(CopyString); } "(" { *pCopyRoundString+=*yytext; roundCount++; } ")" { *pCopyRoundString+=*yytext; if (--roundCount<0) BEGIN(lastRoundContext); } \n { yyLineNr++; *pCopyRoundString+=*yytext; } \' { if (insidePHP) { current->initializer+=yytext; pCopyQuotedString = pCopyRoundString; lastStringContext=YY_START; BEGIN(CopyPHPString); } else { *pCopyRoundString+=yytext; } } {CHARLIT} { if (insidePHP) { REJECT; } else { *pCopyRoundString+=yytext; } } [^"'()\n]+ { *pCopyRoundString+=yytext; } . { *pCopyRoundString+=*yytext; } /* generic curly bracket list copy rules */ \" { *pCopyCurlyString+=*yytext; pCopyQuotedString=pCopyCurlyString; lastStringContext=YY_START; BEGIN(CopyString); } \' { *pCopyCurlyString+=*yytext; if (insidePHP) { pCopyQuotedString=pCopyCurlyString; lastStringContext=YY_START; BEGIN(CopyPHPString); } } "{" { *pCopyCurlyString+=*yytext; curlyCount++; } "}" { *pCopyCurlyString+=*yytext; if (--curlyCount<0) BEGIN(lastCurlyContext); } {CHARLIT} { if (insidePHP) { REJECT; } else { *pCopyCurlyString+=yytext; } } [^"'{}\/\n]+ { *pCopyCurlyString+=yytext; } "/" { *pCopyCurlyString+=yytext; } \n { yyLineNr++; *pCopyCurlyString+=*yytext; } . { *pCopyCurlyString+=*yytext; } ":" { if (current->type.isEmpty()) // bit pad field { addType(current); current->name.sprintf("__pad%d__",padCount++); } BEGIN(BitFields); current->bitfields+=":"; } . { current->bitfields+=*yytext; } [;,] { 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); } 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(); current->section = Entry::VARIABLE_SEC ; current->fileName = yyFileName; current->startLine = yyLineNr; 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 ; } initEntry(); } BEGIN( FindMembers ) ; } "[" { if (current->name.isEmpty() || current->name=="typedef") // IDL function property { squareCount=1; lastSquareContext = YY_START; BEGIN(SkipSquare); } else { current->args += yytext ; squareCount=1; BEGIN( Array ) ; } } "]" { current->args += *yytext ; if (--squareCount<=0) BEGIN( FindMembers ) ; } "[" { current->args += *yytext ; squareCount++; } . { current->args += *yytext ; } "[" { squareCount++; } "]" { if (--squareCount<=0) BEGIN( lastSquareContext ); } \" { lastStringContext=YY_START; BEGIN( SkipString ); } [^\n\[\]\"]+ "<" { addType( current ) ; current->type += yytext ; BEGIN( Sharp ) ; } ">" { current->type += *yytext ; if (--sharpCount<=0) BEGIN( FindMembers ) ; } "<" { current->type += *yytext ; sharpCount++; } {BN}+ { lineCount(); } . { current->type += *yytext ; } {ID} { current->name = yytext; } "=" { lastInitializerContext = YY_START; initBracketCount=0; BEGIN(ReadInitializer); } "," { //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); 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(); } } "[" { // attribute list in IDL squareCount=1; lastSquareContext = YY_START; BEGIN(SkipSquare); } /* "," { unput(*yytext); BEGIN(FindFields); } */ [^\r\n\#{}"@'/]* { current->program += yytext ; } "//".* { current->program += yytext ; } "#".* { if (!insidePHP) REJECT; // append PHP comment. current->program += yytext ; } @\" { current->program += yytext ; pSkipVerbString = ¤t->program; lastSkipVerbStringContext=YY_START; BEGIN( SkipVerbString ); } \" { current->program += yytext ; pCopyQuotedString = ¤t->program; lastStringContext=YY_START; BEGIN( CopyString ); } "/*"{B}* { current->program += yytext ; lastContext = YY_START ; BEGIN( Comment ) ; } "/*"{BL} { current->program += yytext ; ++yyLineNr ; lastContext = YY_START ; BEGIN( Comment ) ; } "'" { if (!insidePHP) { current->program += yytext; } else { // begin of single quoted string current->program += yytext; pCopyQuotedString = ¤t->program; lastStringContext=YY_START; BEGIN(CopyPHPString); } } {CHARLIT} { if (insidePHP) { REJECT; // for PHP code single quotes // are used for strings of arbitrary length } else { current->program += yytext; } } "{" { current->program += yytext ; ++curlyCount ; } "}" { //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(); //cn.prepend(rn+"::"); } 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->section==Entry::INTERFACE_SEC || current->section==Entry::CATEGORY_SEC) ) // method definition follows { BEGIN( ReadBodyIntf ) ; } else { current_root->addSubEntry( current ) ; current = new Entry(*current); if (current->section==Entry::NAMESPACE_SEC || current->section==Entry::INTERFACE_SEC || insideJava || insidePHP || insideCS || insideD ) { // namespaces and interfaces and java classes ends with a closing bracket without semicolon current->reset(); initEntry(); BEGIN( FindMembers ) ; } else { BEGIN( MemberSpec ) ; } } } } } "}"{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 ); } } {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 ) ; current = new Entry; initEntry(); BEGIN(MemberSpecSkip); } ";" { /* 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 ) ; current = new Entry(*current); unput(';'); BEGIN( MemberSpec ) ; } ([*&]*{BN}*)*{ID}("["[^\]\n]*"]")* { // the [] part could be improved. lineCount(); int i=0,l=yyleng,j; while (i[,;] { //printf("current->name=`%s' msName=`%s'\n",current->name.data(),msName.data()); if (msName.isEmpty() && !current->name.isEmpty()) /* && (current->section & Entry::COMPOUND_MASK)) */ { // 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; 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 (!msName.isEmpty()) { 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; //current->args.simplifyWhiteSpace(); //if (!current->name.isEmpty() && current->name[0]!='@' && // current->parent->section & Entry::COMPOUND_MASK) // varEntry->type+=current->parent->name+"::"; if (isTypedef) { varEntry->type.prepend("typedef "); // //printf("current->name = %s %s\n",current->name.data(),msName.data()); // if (!current->name.isEmpty() && current->name.at(0)!='@') // { // //printf("2>>>>>>>>>> adding %s->%s\n",msName.data(),current->name.data()); // QCString scope; // if (current_root->section & Entry::SCOPE_MASK) scope=current_root->name; // Doxygen::typedefDict.insert(msName,new TypedefInfo(current->name,scope)); // } } 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 gli(*current->groups); Grouping *g; for (;(g=gli.current());++gli) { varEntry->groups->append(new Grouping(*g)); } if (current->sli) // copy special list items { QListIterator li(*current->sli); ListItemInfo *lii; for (li.toFirst();(lii=li.current());++li) { varEntry->addSpecialListItem(lii->type,lii->itemId); } //delete current->sli; //current->sli = 0; } //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; current->reset(); initEntry(); BEGIN( FindMembers ); } } "=" { lastInitializerContext=YY_START; initBracketCount=0; BEGIN(ReadInitializer); /* BEGIN(MemberSpecSkip); */ } /* "{" { curlyCount=0; lastCurlyContext = MemberSpecSkip; previous = current; BEGIN(SkipCurly); } */ "," { BEGIN(MemberSpec); } ";" { unput(';'); BEGIN(MemberSpec); } {BN}+ { current->program += yytext ; lineCount() ; } "@end"/[^a-z_A-Z0-9] { // end of Objective C block current_root->addSubEntry( current ) ; current=new Entry; initEntry(); insideObjC=FALSE; BEGIN( FindMembers ); } . { current->program += yytext ; } "("/({BN}*{TSCOPE}{BN}*"::")*{TSCOPE}{BN}*")"{BN}*"(" | /* typedef void (A::func_t)(args...) */ ("("({BN}*{TSCOPE}{BN}*"::")*({BN}*"*"{BN}*)+)+ { /* typedef void (A::*ptr_t)(args...) */ current->bodyLine = yyLineNr; lineCount(); addType(current); funcPtrType=yytext; roundCount=0; //current->type += yytext; BEGIN( FuncPtr ); } {SCOPENAME} { current->name = yytext; if (current->name=="const" || current->name=="volatile") { funcPtrType += current->name; } else { BEGIN( EndFuncPtr ); } } . { //printf("Error: FuncPtr `%c' unexpected at line %d of %s\n",*yytext,yyLineNr,yyFileName); } ")"{BN}*/";" { // a variable with extra braces lineCount(); current->type+=funcPtrType.data()+1; BEGIN(FindMembers); } ")"{BN}*/"(" { // a function pointer lineCount(); current->type+=funcPtrType+")"; BEGIN(FindMembers); } ")"{BN}*/"[" { // an array of variables lineCount(); current->type+=funcPtrType.data(); current->args += ")"; BEGIN(FindMembers); } "(" { // a function returning a function current->args += *yytext ; roundCount=0; BEGIN( FuncFunc ); } "["[^\n\]]*"]" { funcPtrType+=yytext; } ")" { BEGIN(FindMembers); } "(" { current->args += *yytext ; ++roundCount; } ")" { current->args += *yytext ; if ( roundCount ) --roundCount; else { BEGIN(FuncFuncEnd); } } ")"{BN}*"(" { lineCount(); current->type+=funcPtrType+")("; BEGIN(FuncFuncType); } ")"{BN}*/[;{] { lineCount(); current->type+=funcPtrType.data()+1; BEGIN(Function); } . { current->args += *yytext; } "(" { current->type += *yytext; roundCount++; } ")" { current->type += *yytext; if (roundCount) --roundCount; else BEGIN(Function); } {BN}*","{BN}* { lineCount() ; current->type += ", " ; } {BN}+ { lineCount() ; current->type += ' ' ; } . { current->type += *yytext; } "("/{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"); } } {BN}*{ID}{BN}*"*" { lineCount(); addType(current); funcPtrType="("; funcPtrType+=yytext; roundCount=0; BEGIN( FuncPtr ); } "(" { 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()); } } /* "("{BN}*("void"{BN}*)?")" { lineCount(); current->args = "()"; BEGIN( FuncQual ); } */ /*- Function argument reading rules ---------------------------------------*/ [^ \/\r\t\n\)\(\"\'#]+ { *copyArgString+=yytext; fullArgString+=yytext; } [^\n\\\"\']+ { *copyArgString+=yytext; fullArgString+=yytext; } [^\/\n\)\(\"\']+ { *copyArgString+=yytext; fullArgString+=yytext; } {BN}* { *copyArgString+=" "; fullArgString+=" "; lineCount(); } \" { *copyArgString+=*yytext; fullArgString+=*yytext; lastCopyArgStringContext = YY_START; BEGIN( CopyArgString ); } "(" { *copyArgString+=*yytext; fullArgString+=*yytext; argRoundCount=0; lastCopyArgContext = YY_START; BEGIN( CopyArgRound ); } ")" { *copyArgString+=*yytext; fullArgString+=*yytext; stringToArgumentList(fullArgString,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.copy(); briefBackup = current->brief.copy(); BEGIN( currentArgumentContext ); } /* a special comment */ ("/*"[*!]|"//"[/!])("<"?) { 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); BEGIN( currentArgumentContext ); } else { // 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 */ "/*" { lastCContext = YY_START; BEGIN( SkipComment ); } "//" { lastCContext = YY_START; BEGIN( SkipCxxComment ); } /* "'#" { if (insidePHP) REJECT; *copyArgString+=yytext; fullArgString+=yytext; } "#" { if (!insidePHP) REJECT; lastCContext = YY_START; BEGIN( SkipCxxComment ); } */ /* `)' followed by a special comment */ ")"{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); 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 ); } } ^{B}*"*"+/{BN}+ [^\n\\\@\*]+ { fullArgString+=yytext; } "*/" { fullArgString+=yytext; if (lastCopyArgChar!=0) unput(lastCopyArgChar); BEGIN( lastCommentInArgContext ); } \n { fullArgString+=yytext; yyLineNr++; if (lastCopyArgChar!=0) unput(lastCopyArgChar); BEGIN( lastCommentInArgContext ); } [^\\\@\n]+ { fullArgString+=yytext; } . { fullArgString+=*yytext; } \n { fullArgString+=*yytext; yyLineNr++; } . { fullArgString+=*yytext; } {CMD}("brief"|"short"){B}+ { warn(yyFileName,yyLineNr, "Warning: Ignoring %cbrief command inside argument documentation",*yytext ); fullArgString+=' '; } "<" { *copyArgString+=*yytext; fullArgString+=*yytext; argSharpCount=1; BEGIN( CopyArgSharp ); } ">" { *copyArgString+=*yytext; fullArgString+=*yytext; //printf("end template list %s\n",copyArgString->data()); stringToArgumentList(fullArgString,currentArgumentList); BEGIN( currentArgumentContext ); } "(" { argRoundCount++; *copyArgString+=*yytext; fullArgString+=*yytext; } ")" { *copyArgString+=*yytext; fullArgString+=*yytext; if (argRoundCount>0) argRoundCount--; else BEGIN( lastCopyArgContext ); } "<" { argSharpCount++; //printf("argSharpCount++=%d copy\n",argSharpCount); *copyArgString+=*yytext; fullArgString+=*yytext; } ">" { *copyArgString+=*yytext; fullArgString+=*yytext; argSharpCount--; if (argSharpCount>0) { //printf("argSharpCount--=%d copy\n",argSharpCount); } else { BEGIN( ReadTempArgs ); //printf("end of argSharpCount\n"); } } \\. { *copyArgString+=yytext; fullArgString+=yytext; } \" { *copyArgString+=*yytext; fullArgString+=*yytext; BEGIN( lastCopyArgStringContext ); } \' { *copyArgString+=*yytext; fullArgString+=*yytext; BEGIN( lastCopyArgStringContext ); } {CHARLIT} { if (insidePHP) { REJECT; } else { *copyArgString+=yytext; fullArgString+=yytext; } } \' { *copyArgString+=yytext; fullArgString+=yytext; if (insidePHP) { lastCopyArgStringContext=YY_START; BEGIN(CopyArgPHPString); } } \n { yyLineNr++; *copyArgString+=*yytext; fullArgString+=*yytext; } . { *copyArgString+=*yytext; fullArgString+=*yytext; } /*------------------------------------------------------------------------*/ "(" { current->args += *yytext ; ++roundCount ; } ")" { current->args += *yytext ; if ( roundCount ) --roundCount ; else BEGIN( FuncQual ) ; } /* "#" { if (insidePHP) REJECT; lastCPPContext = YY_START; BEGIN(SkipCPP); } */ [{:;,] { if ( strcmp(yytext,";")==0 && insidePHP && !containsWord(current->type,"function") ) { current->reset(); initEntry(); BEGIN( FindMembers ); } else { unput(*yytext); BEGIN( Function ); } } {BN}*"const"{BN}* { // const member function lineCount() ; current->args += " const "; current->argList->constSpecifier=TRUE; } {BN}*"volatile"{BN}* { // volatile member function lineCount() ; current->args += " volatile "; current->argList->volatileSpecifier=TRUE; } {BN}*"="{BN}*"0"{BN}* { // pure virtual member function lineCount() ; current->args += " = 0"; current->virt = Pure; current->argList->pureSpecifier=TRUE; } {BN}*","{BN}* { lineCount() ; current->args += ", " ; } {BN}+ { lineCount() ; current->args += ' ' ; } "#" { if (insidePHP) REJECT; lastCPPContext = YY_START; BEGIN(SkipCPP); } "=" { // typically an initialized function pointer //current->args += *yytext; //BEGIN(FuncPtrInit); lastInitializerContext=YY_START; initBracketCount=0; BEGIN(ReadInitializer); } [{;] { unput(*yytext); BEGIN(FuncQual); } \" { current->args += *yytext; pCopyQuotedString=¤t->args; lastStringContext=FuncPtrInit; BEGIN(CopyString); } \' { current->args += *yytext; if (insidePHP) { pCopyQuotedString=¤t->args; lastStringContext=FuncPtrInit; BEGIN(CopyPHPString); } } {CHARLIT} { if (insidePHP) { REJECT; } else { current->args += yytext; } } {ID} { current->args += yytext; } . { current->args += *yytext; } \n { current->args += *yytext; yyLineNr++; } {ID} { // typically a K&R style C function if (checkForKnRstyleC()) { //fprintf(stderr,"===> got a K&R style function\n"); current->args = yytext; oldStyleArgType.resize(0); BEGIN(OldStyleArgs); } else { current->args += yytext; } } [,;] { 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); } {ID} { current->args += yytext; } "{" { current->args = argListToString(current->argList); unput('{'); BEGIN(FuncQual); } . { current->args += *yytext; } . { current->args += *yytext; } {BN}*"try"{BN}+ { /* try-function-block */ insideTryBlock=TRUE; lineCount(); } {BN}*"throw"{BN}*"(" { // C++ style throw clause current->exception = " throw (" ; roundCount=0; lineCount() ; BEGIN( ExcpRound ) ; } {BN}*"raises"{BN}*"(" { current->exception = " raises (" ; lineCount() ; roundCount=0; BEGIN( ExcpRound ) ; } {BN}*"throws"{BN}+ { // Java style throw clause current->exception = " throws " ; lineCount() ; BEGIN( ExcpList ); } "(" { current->exception += *yytext ; ++roundCount ; } ")" { current->exception += *yytext ; if ( roundCount ) --roundCount ; else BEGIN( FuncQual ) ; } . { current->exception += *yytext; } "{" { unput('{'); BEGIN( FuncQual ); } ";" { unput(';'); BEGIN( FuncQual ); } "\n" { current->exception += ' '; yyLineNr++; } . { current->exception += *yytext; } "(" { current->type += current->name ; current->name = current->args ; current->args = yytext ; roundCount=0; BEGIN( FuncRound ) ; } ":" { if (!insidePHP) BEGIN(SkipInits); } [;{,] { 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; if (*yytext!=';' || (current_root->section&Entry::COMPOUND_MASK) ) { int tempArg=current->name.find('<'); QCString tempName; static QRegExp re("operator[^a-z_A-Z0-9]"); if (tempArg==-1) tempName=current->name; else tempName=current->name.left(tempArg); if (/*(current->type.isEmpty() && tempName.find(re)==-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 { static QRegExp re("([^)]*)"); //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->memSpec |= Entry::Final; } if (findAndRemoveWord(current->type,"abstract")) { current->memSpec |= Entry::Abstract; } } if ( insidePHP && !containsWord(current->type,"function")) { initEntry(); } else { if ( insidePHP) { findAndRemoveWord(current->type,"function"); } previous = current; current_root->addSubEntry(current); current = new Entry ; initEntry(); lastCurlyContext = FindMembers; if ( *yytext == ',' ) { current->type = previous->type.data(); } if ( *yytext == '{' ) { if ( !insidePHP && (current_root->section & Entry::COMPOUND_MASK) ) { previous->memSpec |= Entry::Inline; } //addToBody(yytext); curlyCount=0; BEGIN( SkipCurly ) ; } else { if (previous->section!=Entry::VARIABLE_SEC) previous->bodyLine=-1; // a function/member declaration BEGIN( FindMembers ) ; } } } "{" { //addToBody(yytext); //lastCurlyContext = FindMembers; //curlyCount=0; //BEGIN( SkipCurly ) ; unput('{'); BEGIN( Function ); } "{" { //addToBody(yytext); ++curlyCount ; } "}" { //addToBody(yytext); if( curlyCount ) { --curlyCount ; } else { 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; } previous->inbodyDocs += current->doc; current->doc.resize(0); } if (current->sli) // copy special list items { QListIterator li(*current->sli); ListItemInfo *lii; for (li.toFirst();(lii=li.current());++li) { previous->addSpecialListItem(lii->type,lii->itemId); } delete current->sli; current->sli = 0; } previous->endBodyLine=yyLineNr; BEGIN( lastCurlyContext ) ; } } "}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { if ( curlyCount ) { //addToBody(yytext); --curlyCount ; } else { current->endBodyLine=yyLineNr; lineCount(); tempEntry = current; // temporarily switch to the previous entry current = previous; docBlockContext = SkipCurlyEndDoc; docBlockInBody = FALSE; docBlockJavaStyle = yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF"); docBlock.resize(0); docBlockTerm = '}'; if (yytext[yyleng-3]=='/') { startCommentBlock(TRUE); BEGIN( DocLine ); } else { startCommentBlock(FALSE); BEGIN( DocBlock ); } } } "}" { //addToBody("}"); current = tempEntry; BEGIN( lastCurlyContext ); } \" { //addToBody(yytext); lastStringContext=SkipCurly; BEGIN( SkipString ); } ^{B}*"#" { if (insidePHP) REJECT; //addToBody(yytext); BEGIN( SkipCurlyCpp ); } \n { yyLineNr++; //addToBody(yytext); } [^\n"'@\\/{}]+ { //addToBody(yytext); } \n { //addToBody(yytext); yyLineNr++; lastCurlyContext = FindMembers; BEGIN( SkipCurly ); } \\[\r]*"\n"[\r]* { //addToBody(yytext); yyLineNr++; } "/*" { //addToBody(yytext); lastCContext = YY_START; BEGIN(SkipComment); } "//" { //addToBody(yytext); lastCContext = YY_START; BEGIN(SkipCxxComment); } \" { lastStringContext=YY_START; BEGIN( SkipString ); } ; { warn(yyFileName,yyLineNr, "Warning: Found ';' while parsing initializer list! " "(doxygen could be confused by a macro call without semicolon)" ); BEGIN( FindMembers ); } "#" { if (!insidePHP) REJECT; //addToBody(yytext); lastCContext = YY_START; BEGIN(SkipCxxComment); } @\" { if (!insideCS) REJECT; // C# verbatim string lastSkipVerbStringContext=YY_START; pSkipVerbString=¤t->initializer; BEGIN(SkipVerbString); } {CHARLIT} { if (insidePHP) REJECT; } \' { if (insidePHP) { lastStringContext=YY_START; BEGIN(SkipPHPString); } } . { } \\. { } \" { BEGIN( lastStringContext ); } \' { BEGIN( lastStringContext ); } "/*"|"*/"|"//" { } \n { yyLineNr++; } . { } ";" { current->section = Entry::EMPTY_SEC ; current->type.resize(0) ; current->name.resize(0) ; current->args.resize(0) ; current->argList->clear(); BEGIN( FindMembers ) ; } {SCOPENAME}{BN}*/"<" { sharpCount = 0; current->name = yytext ; if (current->section==Entry::PROTOCOL_SEC) { current->name+="-p"; } lineCount(); lastClassTemplSpecContext = ClassVar; if (insideObjC) // protocol list { BEGIN( ObjCProtocolList ); } else // C++ template specialization { BEGIN( ClassTemplSpec ); } } "<" { insideProtocolList=TRUE; BEGIN( Bases ); } ">"({BN}*"::"{BN}*{SCOPENAME})? { current->name += yytext; lineCount(); if (--sharpCount<=0) { current->name = removeRedundantWhiteSpace(current->name); if (current->section == Entry::PROTOCOL_SEC) { // Objective-C protocol unput('{'); // fake start of body BEGIN( ClassVar ); } else { BEGIN( lastClassTemplSpecContext ); } } } "<" { current->name += yytext; sharpCount++; } . { current->name += yytext; } {SCOPENAME}{BN}*";" { // forward declaration unput(';'); current->reset(); if (isTypedef) // typedef of a class, put typedef keyword back { current->type.prepend("typedef"); } BEGIN( FindMembers ); } {SCOPENAME} { current->name = yytext ; lineCount(); if (current->section == Entry::PROTOCOL_SEC) { current->name += "-p"; } if (current->section == Entry::PROTOCOL_SEC /*|| current->section == Entry::OBJCIMPL_SEC*/) { unput('{'); // fake start of body } BEGIN( ClassVar ); } {CSSCOPENAME} { // C# style scope current->name = substitute(yytext,".","::"); lineCount(); BEGIN( 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 ); } } "," { if (isTypedef) { // multiple types in one typedef unput(','); current->type.prepend("typedef "); BEGIN(FindMembers); } else { // Multiple class forward declaration } } {ID} { if (insideIDL && strcmp(yytext,"switch")==0) { // Corba IDL style union roundCount=0; BEGIN(SkipUnionSwitch); } else if ((insideJava || insidePHP) && (strcmp(yytext,"implements")==0 || strcmp(yytext,"extends")==0)) { current->type.resize(0); baseProt=Public; baseVirt=Normal; baseName.resize(0); BEGIN( BasesProt ) ; } 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 (insideObjC && *yytext=='(') // class category { current->name+='('; if (current->section!=Entry::OBJCIMPL_SEC) { current->section=Entry::CATEGORY_SEC; } BEGIN( ClassCategory ); } else { // probably a function anyway unput(*yytext); BEGIN( FindMembers ); } } {ID} { current->name+=yytext; } ")" { current->name+=')'; // category has no variables so push back an empty body unput('}'); unput('{'); BEGIN( ClassVar ); } ":" { current->type.resize(0); if (current->section == Entry::INTERFACE_SEC || current->section == Entry::STRUCT_SEC || insidePHP || insideCS || insideD || insideObjC ) baseProt=Public; else baseProt=Private; baseVirt=Normal; baseName.resize(0); BEGIN( BasesProt ) ; } [;=*&] { unput(*yytext); if (isTypedef) // typedef of a class, put typedef keyword back { current->type.prepend("typedef"); } BEGIN( FindMembers ); } "///"/[^/] { if (!insideObjC) { REJECT; } else { lineCount(); current->program+=yytext; current->fileName = yyFileName ; current->startLine = yyLineNr ; curlyCount=0; BEGIN( ReadBodyIntf ); } } ("//"{B}*)?"/**"/[^/*] | ("//"{B}*)?"/*!" | "//!" | [\-+]{BN}+ { if (!insideObjC) { REJECT; } else { lineCount(); current->program+=yytext; current->fileName = yyFileName ; current->startLine = yyLineNr ; curlyCount=0; BEGIN( ReadBodyIntf ); } } {B}*"{"{B}* { current->fileName = yyFileName ; current->startLine = yyLineNr ; current->name = removeRedundantWhiteSpace(current->name); if (current->name.isEmpty() && !isTypedef) // anonymous compound { current->name.sprintf("@%d",anonCount++); } curlyCount=0; if (/*current->section==Entry::PROTOCOL_SEC || 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 ) ; } } "virtual"{BN}+ { lineCount(); baseVirt = Virtual; } "public"{BN}+ { lineCount(); baseProt = Public; } "protected"{BN}+ { lineCount(); baseProt = Protected; } "private"{BN}+ { lineCount(); baseProt = Private; } {BN} { lineCount(); } . { unput(*yytext); BEGIN(Bases); } ("::")?{BN}*({ID}{BN}*"::"{BN}*)*{ID} { baseName+=yytext; current->args += ' '; current->args += yytext; } {BN}*{ID}("."{ID})* { // Java style class QCString name = substitute(yytext,".","::"); baseName += name; current->args += ' '; current->args += name; } \n/{BN}* { if (!insideObjC) { REJECT; } else { yyLineNr++; //unput('{'); } } "@end" { // empty ObjC interface unput('d'); // insert fake body: {}@end unput('n'); unput('e'); unput('@'); unput('}'); unput('{'); } "<" { current->name += *yytext; sharpCount=1; roundCount=0; lastSkipSharpContext = YY_START; specName = ¤t->name; BEGIN ( Specialization ); } "<" { sharpCount=1; roundCount=0; lastSkipSharpContext = YY_START; if (insideObjC) // start of protocol list { unput(','); } else // template specialization { baseName += *yytext; specName = &baseName; BEGIN ( Specialization ); } } "<" { *specName += *yytext; if (roundCount==0) sharpCount++; } ">" { *specName += *yytext; if (roundCount==0 && --sharpCount<=0) BEGIN(lastSkipSharpContext); } {BN}+ { lineCount(); *specName +=' '; } "<<" { *specName += yytext; } ">>" { *specName += yytext; } "typename"{BN}+ { lineCount(); } "(" { *specName += *yytext; roundCount++; } ")" { *specName += *yytext; roundCount--; } . { *specName += *yytext; } "<" { ++sharpCount; } ">" { if (--sharpCount<=0) BEGIN ( lastSkipSharpContext ); } "(" { ++roundCount; } ")" { if (--roundCount<=0) BEGIN ( lastSkipRoundContext ); } ","|">"|({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->section==Entry::INTERFACE_SEC || 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; } else { if (*yytext==',' && insideObjC) // Begin of protocol list { insideProtocolList=TRUE; } BEGIN(BasesProt); } } {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 ) ; } } {B}*"(" { roundCount++; } ")" { if (--roundCount==0) { BEGIN(ClassVar); } } \n { yyLineNr++; } . {BN}+ { current->program += yytext ; lineCount() ; } "/*" { current->program += yytext ; } "//" { current->program += yytext ; } {CMD}("code"|"verbatim") { insideCode=TRUE; current->program += yytext ; } {CMD}("endcode"|"endverbatim") { insideCode=FALSE; current->program += yytext ; } [^ \.\n\/\*]+ { current->program += yytext ; } "*/" { current->program += yytext ; if (!insideCode) BEGIN( lastContext ) ; } . { current->program += *yytext ; } ("//"{B}*)?"/*!" { //printf("Start doc block at %d\n",yyLineNr); removeSlashes=(yytext[1]=='/'); tmpDocType=-1; if (YY_START!=SkipCurly) { current->doc.resize(0); current->docLine = yyLineNr; current->docFile = yyFileName; } lastDocContext = YY_START; if (current_root->section & Entry::SCOPE_MASK) { current->inside = current_root->name+"::"; //if (current->mGrpId!=DOX_NOGROUP) //{ // memberGroupInside = current->inside.copy(); //} } docBlockContext = YY_START; docBlockInBody = YY_START==SkipCurly; docBlockJavaStyle = FALSE; docBlock.resize(0); startCommentBlock(FALSE); BEGIN( DocBlock ); } ("//"{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+"::"; //if (current->mGrpId!=DOX_NOGROUP) //{ // memberGroupInside = current->inside.copy(); //} } current->docLine = yyLineNr; current->docFile = yyFileName; docBlockContext = YY_START; docBlockInBody = YY_START==SkipCurly; docBlockJavaStyle = Config_getBool("JAVADOC_AUTOBRIEF"); docBlock.resize(0); if (docBlockJavaStyle) { current->briefLine = yyLineNr; current->briefFile = yyFileName; } if (!docBlockInBody) { current->doc.resize(0); if (docBlockJavaStyle) { current->brief.resize(0); } } startCommentBlock(FALSE); BEGIN( DocBlock ); } "//!" { if (YY_START!=SkipCurly) { current->brief.resize(0); current->briefFile=yyFileName; current->briefLine=yyLineNr; } tmpDocType=-1; lastDocContext = YY_START; if (current_root->section & Entry::SCOPE_MASK) { current->inside = current_root->name+"::"; //if (current->mGrpId!=DOX_NOGROUP) //{ // memberGroupInside = current->inside.copy(); //} } docBlockContext = YY_START; docBlockInBody = YY_START==SkipCurly; docBlockJavaStyle = FALSE; docBlock.resize(0); startCommentBlock(TRUE); BEGIN( DocLine ); } "///"/[^/] { if (YY_START!=SkipCurly) { current->brief.resize(0); current->briefFile=yyFileName; current->briefLine=yyLineNr; } tmpDocType=-1; lastDocContext = YY_START; if (current_root->section & Entry::SCOPE_MASK) { current->inside = current_root->name+"::"; //if (current->mGrpId!=DOX_NOGROUP) //{ // memberGroupInside = current->inside.copy(); //} } docBlockContext = YY_START; docBlockInBody = YY_START==SkipCurly; docBlockJavaStyle = FALSE; docBlock.resize(0); startCommentBlock(TRUE); BEGIN( DocLine ); } "extern"{BN}*"\"C"("++")?"\""{BN}*("{")? { lineCount(); } "{" { 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 ); } } } "{" { curlyCount++; } "}" { if (curlyCount) { curlyCount--; } else { unput(';'); BEGIN(FindMembers); } } "set" { if (curlyCount==0) current->memSpec |= Entry::Settable; } "get" { if (curlyCount==0) current->memSpec |= Entry::Gettable; } . {} \n { yyLineNr++; } /**********************************************************************************/ /******************** Documentation block related rules ***************************/ /**********************************************************************************/ /* ---- Single line comments ------ */ [^\n]*/"\n" { // whole line handleCommentBlock(yytext,TRUE); BEGIN( docBlockContext ); } /* ---- Comments blocks ------ */ "*"*"*/" { // end of comment block handleCommentBlock(docBlock,FALSE); BEGIN(docBlockContext); } ^{B}*("//")?{B}*"*"+/[^//] { // start of a comment line } ^{B}*("//"){B}* { // strip embedded C++ comments if at the start of a line } "//" { // slashes in the middle of a comment block docBlock+=yytext; } "/*" { // start of a new comment in the // middle of a comment block docBlock+=yytext; } ("@@"|"\\\\"){ID}/[^a-z_A-Z0-9] { // escaped command docBlock+=yytext; } {CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code"|"f$"|"f["|"f{")/[^a-z_A-Z0-9] { // verbatim command (which could contain nested comments!) docBlock+=yytext; if (yytext[2]=='[') { docBlockName="f]"; } else if (yytext[2]=='}') { docBlockName="f}"; } else { docBlockName=&yytext[1]; } BEGIN(DocCopyBlock); } [^@*\/\\\n]+ { // any character that isn't special docBlock+=yytext; } \n { // newline yyLineNr++; docBlock+=*yytext; } . { // command block docBlock+=*yytext; } /* ---- Copy verbatim sections ------ */ [\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddot"|"endcode"|"f$"|"f]"|"f}")/[^a-z_A-Z0-9] { // end of verbatim block docBlock+=yytext; if (yytext[1]=='f') // end of formula { BEGIN(DocBlock); } if (&yytext[4]==docBlockName) { BEGIN(DocBlock); } } ^{B}*"*"+/{BN}+ { // start of a comment line if (docBlockName=="verbatim") { REJECT; } } [^@/*\\\n]+ { // any character that is not special docBlock+=yytext; } "/*"|"*/"|"//" { docBlock+=yytext; } \n { // newline docBlock+=*yytext; yyLineNr++; } . { // any other character docBlock+=*yytext; } <> { warn(yyFileName,yyLineNr, "Warning: reached end of file while inside a %s block!\n", docBlockName.data()); yyterminate(); } /* ------------- Prototype parser -------------- */ "operator"{B}*"("{B}*")" { current->name+=yytext; } "(" { current->args+=*yytext; currentArgumentContext = PrototypeQual; fullArgString = current->args.copy(); copyArgString = ¤t->args; BEGIN( ReadFuncArgType ) ; } "("({ID}"::")*({B}*"*")+ { current->type+=current->name+yytext; current->name.resize(0); BEGIN( PrototypePtr ); } {SCOPENAME} { current->name+=yytext; } ")" { current->type+=')'; BEGIN( Prototype ); } "{" { BEGIN( PrototypeSkipLine); } {B}*"const"{B}* { current->args += " const "; current->argList->constSpecifier=TRUE; } {B}*"volatile"{B}* { current->args += " volatile "; current->argList->volatileSpecifier=TRUE; } {B}*"="{B}*"0"{B}* { current->args += " = 0"; current->virt = Pure; current->argList->pureSpecifier=TRUE; } "throw"{B}*"(" { current->exception = "throw("; BEGIN(PrototypeExc); } ")" { current->exception += ')'; BEGIN(PrototypeQual); } . { current->exception += *yytext; } . { current->name += *yytext; } . { } /* ------------ Generic rules -------------- */ .*/\n { BEGIN( lastCContext ) ; } [^\*\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); } } <*>. "//"|"/*" <*>"/*" { lastCContext = YY_START ; BEGIN( 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) { int position=0; bool needsEntry; if (docBlockInBody) { if (previous==0) { ASSERT(previous!=0); // shouldn't happen goto exit; } if (!previous->doc.isEmpty()) { // start a new paragraph for the next piece of text found in the body previous->doc=previous->doc.stripWhiteSpace()+"\n\n"; } } //printf("parseCommentBlock [%s]\n",doc.data()); while (parseCommentBlock( g_thisParser, docBlockInBody ? previous : current, doc, // text yyFileName, // file brief ? current->briefLine : current->docLine, // line of block start docBlockInBody ? FALSE : brief, docBlockInBody ? FALSE : docBlockJavaStyle, protection, position, needsEntry ) ) { //printf("parseCommentBlock position=%d [%s]\n",position,doc.data()+position); if (needsEntry) newEntry(); } if (needsEntry) { newEntry(); } exit: if (docBlockTerm) { unput(docBlockTerm); docBlockTerm=0; } } //---------------------------------------------------------------------------- //static void startGroupInDoc() //{ // if (current->section==Entry::GROUPDOC_SEC ) /* scope for a non-member group: @defgroup */ // { // autoGroupStack.push(new Grouping(current->name, // current->groupingPri() // )); // } // else /* if (current->section == Entry::MEMBERGRP_SEC) scope for a member group: @name */ // { // if (memberGroupId!=DOX_NOGROUP) // { // warn(yyFileName,yyLineNr,"Warning: member groups cannot be nested. Ending current group!\n"); // endGroup(); // } // memberGroupId = newMemberGroupId(); // MemberGroupInfo *info = new MemberGroupInfo; // if (current->section == Entry::MEMBERGRP_SEC) // { // info->header = memberGroupHeader.stripWhiteSpace(); // } // Doxygen::memGrpInfoDict.insert(memberGroupId,info); // memberGroupRelates = current->relates; // memberGroupInside = current->inside; // current->mGrpId = memberGroupId; // } //} // ////---------------------------------------------------------------------------- // //static void endGroup() //{ // if (memberGroupId!=DOX_NOGROUP) // end of member group // { // //Doxygen::memberDocDict.insert(memberGroupId, // // new QCString(memberGroupDocs) // // ); // MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(memberGroupId); // if (info) // { // info->doc = memberGroupDocs; // info->docFile = yyFileName; // } // memberGroupId=DOX_NOGROUP; // memberGroupRelates.resize(0); // memberGroupInside.resize(0); // if (YY_START!=ReadInitializer) // { // current->mGrpId=DOX_NOGROUP; // current->relates.resize(0); // } // memberGroupDocs.resize(0); // } // else if (!autoGroupStack.isEmpty()) // end of group // { // Grouping *current = autoGroupStack.pop(); // Grouping *parent = autoGroupStack.top(); // if( parent ) { // setCurrentGroup( &parent->groupname, parent->pri ); // } else { // setCurrentGroup( 0, Grouping::GROUPING_LOWEST ); // } // delete current; // } //} // ////---------------------------------------------------------------------------- // //static void forceEndGroup() //{ // while (memberGroupId!=DOX_NOGROUP || !autoGroupStack.isEmpty()) // { // //printf("forceEndGroup ends group %d\n",memberGroupId); // endGroup(); // } //} //---------------------------------------------------------------------------- static void parseCompounds(Entry *rt) { //printf("parseCompounds(%s)\n",rt->name.data()); g_inputFromFile = FALSE; EntryListIterator eli(*rt->sublist); 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 ( ce->fileName.right(4)==".php" || ce->fileName.right(4)==".inc" || ce->fileName.right(2)==".d" ) current->protection = protection = Public ; else if (ce->fileName.right(5)==".java") current->protection = protection = Package ; 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 if (ce->section==Entry::INTERFACE_SEC) { if (ce->objc) { current->protection = protection = Protected ; } else { current->protection = protection = Public ; } } 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() ; //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; 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; 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(); 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(); } } //---------------------------------------------------------------------------- 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(); 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"); } //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==".cs" || fe==".d" || fe==".php" || fe==".php4" || fe==".inc" || fe==".phtml" || fe==".m" || fe==".mm" ); } 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