1 /*****************************************************************************
3 * $Id: scanner.l,v 1.80 2001/03/19 19:27:41 root Exp $
5 * Copyright (C) 1997-2012 by Dimitri van Heesch.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation under the terms of the GNU General Public License is hereby
9 * granted. No representations are made about the suitability of this software
10 * for any purpose. It is provided "as is" without express or implied warranty.
11 * See the GNU General Public License for more details.
13 * Documents produced by Doxygen are derivative works derived from the
14 * input used in their production; they are not affected by this license.
43 #include "commentscan.h"
45 #include "arguments.h"
47 #define YY_NEVER_INTERACTIVE 1
50 /* -----------------------------------------------------------------
54 static ParserInterface *g_thisParser;
55 static const char * inputString;
56 static int inputPosition;
57 static QFile inputFile;
58 static int lastContext;
59 static int lastCContext;
60 static int lastDocContext;
61 static int lastCPPContext;
62 static int lastSkipSharpContext;
63 static int lastSkipRoundContext;
64 static int lastStringContext;
65 static int lastCurlyContext;
66 static int lastRoundContext;
67 static int lastSquareContext;
68 static int lastInitializerContext;
69 static int lastClassTemplSpecContext;
70 static int lastPreLineCtrlContext;
71 static int lastSkipVerbStringContext;
72 static int lastCommentInArgContext;
73 static int lastRawStringContext;
74 static int lastCSConstraint;
75 static int lastHereDocContext;
76 static int lastDefineContext;
77 static Protection protection;
78 static Protection baseProt;
79 static int sharpCount = 0 ;
80 static int roundCount = 0 ;
81 static int curlyCount = 0 ;
82 static int squareCount = 0 ;
83 static int padCount = 0 ;
84 static QCString slString;
85 static Entry* current_root = 0 ;
86 static Entry* global_root = 0 ;
87 static Entry* current = 0 ;
88 static Entry* previous = 0 ;
89 static Entry* tempEntry = 0 ;
90 static Entry* firstTypedefEntry = 0 ;
91 static Entry* memspecEntry = 0 ;
92 static int yyLineNr = 1 ;
93 static int anonCount = 0 ;
94 static int anonNSCount = 0 ;
95 static QCString yyFileName;
96 static MethodTypes mtype;
98 static bool removeSlashes;
99 static Specifier virt;
100 static Specifier baseVirt;
101 static QCString msType,msName,msArgs;
102 static bool isTypedef;
103 static int tmpDocType;
104 static QCString sectionLabel;
105 static QCString sectionTitle;
106 static QCString funcPtrType;
107 static QCString templateStr;
108 static QCString aliasName;
109 static QCString baseName;
110 static QCString* specName;
111 static QCString formulaText;
112 static QCString formulaEnd;
113 static bool useOverrideCommands = FALSE;
115 static SrcLangExt language;
116 static bool insideIDL = FALSE; //!< processing IDL code?
117 static bool insideJava = FALSE; //!< processing Java code?
118 static bool insideCS = FALSE; //!< processing C# code?
119 static bool insideD = FALSE; //!< processing D code?
120 static bool insidePHP = FALSE; //!< processing PHP code?
121 static bool insideObjC = FALSE; //!< processing Objective C code?
122 static bool insideCli = FALSE; //!< processing C++/CLI code?
123 static bool insideJS = FALSE; //!< processing JavaScript code?
124 static bool insideCpp = TRUE; //!< processing C/C++ code
126 static bool insideCppQuote = FALSE;
127 static bool insideProtocolList = FALSE;
129 static int argRoundCount;
130 static int argSharpCount;
131 static int currentArgumentContext;
132 static int lastCopyArgStringContext;
133 static int lastCopyArgContext;
134 static QCString *copyArgString;
135 static QCString fullArgString;
137 static ArgumentList *currentArgumentList;
138 static char lastCopyArgChar;
140 static QCString *pCopyQuotedString;
141 static QCString *pCopyRoundString;
142 static QCString *pCopyCurlyString;
143 static QCString *pCopyRawString;
145 static QGString *pCopyCurlyGString;
146 static QGString *pCopyRoundGString;
147 static QGString *pCopyQuotedGString;
148 static QGString *pCopyHereDocGString;
149 static QGString *pCopyRawGString;
150 static QGString *pSkipVerbString;
151 static QStack<Grouping> autoGroupStack;
153 static bool insideFormula;
154 static bool insideTryBlock=FALSE;
155 static bool insideCode;
156 static bool needsSemi;
158 //static int depthIf;
159 static int initBracketCount;
160 static QCString memberGroupRelates;
161 static QCString memberGroupInside;
162 static QCString xrefItemKey;
163 static QCString xrefItemTitle;
164 static QCString xrefListTitle;
166 static QCString g_skipBlockName;
167 static QCString oldStyleArgType;
168 static QCString docBackup;
169 static QCString briefBackup;
170 static bool g_inputFromFile;
172 static int docBlockContext;
173 static QGString docBlock;
174 static QCString docBlockName;
175 static bool docBlockInBody;
176 static bool docBlockAutoBrief;
177 static char docBlockTerm;
179 static QCString idlAttr;
180 static QCString idlProp;
182 static bool g_lexInit = FALSE;
185 static QCString g_delimiter;
189 //-----------------------------------------------------------------------------
191 // forward declarations
192 //static void handleGroupStartCommand(const char *header);
193 //static void handleGroupEndCommand();
195 //-----------------------------------------------------------------------------
197 static void initParser()
199 sectionLabel.resize(0);
200 sectionTitle.resize(0);
202 formulaText.resize(0);
213 autoGroupStack.clear();
214 insideTryBlock = FALSE;
215 autoGroupStack.setAutoDelete(TRUE);
216 insideFormula = FALSE;
218 insideCli=Config_getBool("CPP_CLI_SUPPORT");
222 static void initEntry()
226 protection = (current_root->spec & (Entry::Interface|Entry::Enum)) ? Public : Package;
228 current->protection = protection ;
229 current->mtype = mtype;
230 current->virt = virt;
231 current->stat = gstat;
232 current->lang = language;
233 //printf("*** initEntry() language=%d\n",language);
234 //if (!autoGroupStack.isEmpty())
236 // //printf("Appending group %s\n",autoGroupStack.top()->groupname.data());
237 // current->groups->append(new Grouping(*autoGroupStack.top()));
239 initGroupInfo(current);
244 //-----------------------------------------------------------------------------
246 ///// remove any automatic grouping and add new one (if given)
247 //static void setCurrentGroup( QCString *newgroup, Grouping::GroupPri_t pri )
249 // /* remove auto group name from current entry and discard it */
250 // Grouping *g = current->groups->first();
254 // if (g->pri <= Grouping::GROUPING_AUTO_DEF)
256 // current->groups->remove(i);
259 // g=current->groups->next();
263 // /* use new group name instead? */
266 // current->groups->append(new Grouping(*newgroup, pri));
270 //static int newMemberGroupId()
272 // static int curGroupId=0;
273 // return curGroupId++;
276 // forward declarations
277 //static void startGroupInDoc();
278 //static void endGroup();
280 //-----------------------------------------------------------------------------
282 static void lineCount()
284 static int tabSize = Config_getInt("TAB_SIZE");
286 for (p = yytext ; *p ; ++p )
289 yyLineNr++,g_column=0;
291 g_column+=tabSize - (g_column%tabSize);
297 static inline int computeIndent(const char *s,int startIndent)
300 static int tabSize=Config_getInt("TAB_SIZE");
305 if (c=='\t') col+=tabSize-(col%tabSize);
311 static void addType( Entry* current )
313 uint tl=current->type.length();
314 if( tl>0 && !current->name.isEmpty() && current->type.at(tl-1)!='.')
316 current->type += ' ' ;
318 current->type += current->name ;
319 current->name.resize(0) ;
320 tl=current->type.length();
321 if( tl>0 && !current->args.isEmpty() && current->type.at(tl-1)!='.')
323 current->type += ' ' ;
325 current->type += current->args ;
326 current->args.resize(0) ;
327 current->argList->clear();
331 static QCString stripQuotes(const char *s)
334 if (s==0 || *s==0) return name;
336 if (name.at(0)=='"' && name.at(name.length()-1)=='"')
338 name=name.mid(1,name.length()-2);
343 //-----------------------------------------------------------------
345 static void startCommentBlock(bool);
346 static void handleCommentBlock(const QCString &doc,bool brief);
347 static void handleParametersCommentBlocks(ArgumentList *al);
349 //-----------------------------------------------------------------
351 static bool nameIsOperator(QCString &name)
353 int i=name.find("operator");
354 if (i==-1) return FALSE;
355 if (i==0 && !isId(name.at(8))) return TRUE; // case operator ::X
356 if (i>0 && !isId(name.at(i-1)) && !isId(name.at(i+8))) return TRUE; // case X::operator
357 return FALSE; // case TEXToperatorTEXT
360 //-----------------------------------------------------------------------------
362 static void setContext()
364 QCString fileName = yyFileName;
365 language = getLanguageFromFileName(fileName);
366 insideIDL = language==SrcLangExt_IDL;
367 insideJava = language==SrcLangExt_Java;
368 insideCS = language==SrcLangExt_CSharp;
369 insideD = language==SrcLangExt_D;
370 insidePHP = language==SrcLangExt_PHP;
371 insideObjC = language==SrcLangExt_ObjC;
372 insideJS = language==SrcLangExt_JS;
373 insideCpp = language==SrcLangExt_Cpp;
376 useOverrideCommands = TRUE;
378 //printf("setContext(%s) insideIDL=%d insideJava=%d insideCS=%d "
379 // "insideD=%d insidePHP=%d insideObjC=%d\n",
380 // yyFileName.data(),insideIDL,insideJava,insideCS,insideD,insidePHP,insideObjC
384 //-----------------------------------------------------------------------------
386 static void prependScope()
388 if (current_root->section & Entry::SCOPE_MASK)
390 //printf("--- prependScope %s to %s\n",current_root->name.data(),current->name.data());
391 current->name.prepend(current_root->name+"::");
392 if (current_root->tArgLists)
394 if (current->tArgLists==0)
396 current->tArgLists = new QList<ArgumentList>;
397 current->tArgLists->setAutoDelete(TRUE);
399 //printf("prependScope #=%d #current=%d\n",current_root->tArgLists->count(),current->tArgLists->count());
400 QListIterator<ArgumentList> talsi(*current_root->tArgLists);
401 ArgumentList *srcAl=0;
402 for (talsi.toLast();(srcAl=talsi.current());--talsi)
404 ArgumentList *dstAl = new ArgumentList;
405 QListIterator<Argument> tali(*srcAl);
407 for (;(a=tali.current());++tali)
409 dstAl->append(new Argument(*a));
410 //printf("appending argument %s %s\n",a->type.data(),a->name.data());
412 current->tArgLists->insert(0,dstAl);
418 //-----------------------------------------------------------------------------
420 /*! Returns TRUE iff the current entry could be a K&R style C function */
421 static bool checkForKnRstyleC()
423 if (((QCString)yyFileName).right(2).lower()!=".c") return FALSE; // must be a C file
424 if (!current->argList) return FALSE; // must have arguments
425 ArgumentListIterator ali(*current->argList);
427 for (ali.toFirst();(a=ali.current());++ali)
429 // in K&R style argument do not have a type, but doxygen expects a type
430 // so it will think the argument has no name
431 if (a->type.isEmpty() || !a->name.isEmpty()) return FALSE;
436 //-----------------------------------------------------------------------------
438 static void splitKnRArg(QCString &oldStyleArgPtr,QCString &oldStyleArgName)
440 int si = current->args.length();
441 if (oldStyleArgType.isEmpty()) // new argument
443 static QRegExp re("([^)]*)");
444 int bi1 = current->args.findRev(re);
445 int bi2 = bi1!=-1 ? current->args.findRev(re,bi1-1) : -1;
447 if (bi1!=-1 && bi2!=-1) // found something like "int (*func)(int arg)"
450 oldStyleArgType = current->args.left(s);
452 while (i<si && ((c=current->args.at(i))=='*' || isspace((uchar)c))) i++;
453 oldStyleArgType += current->args.mid(s,i-s);
455 while (i<si && isId(current->args.at(i))) i++;
456 oldStyleArgName = current->args.mid(s,i-s);
457 oldStyleArgType+=current->args.mid(i);
459 else if (bi1!=-1) // redundant braces like in "int (*var)"
462 oldStyleArgType = current->args.left(s);
465 while (i<si && ((c=current->args.at(i))=='*' || isspace((uchar)c))) i++;
466 oldStyleArgType += current->args.mid(s,i-s);
468 while (i<si && isId(current->args.at(i))) i++;
469 oldStyleArgName = current->args.mid(s,i-s);
471 else // normal "int *var"
475 // look for start of name in "type *name"
476 while (i>=0 && isId(current->args.at(i))) i--;
478 // look for start of *'s
479 while (i>=0 && ((c=current->args.at(i))=='*' || isspace((uchar)c))) i--;
483 oldStyleArgType=current->args.left(i);
484 oldStyleArgPtr=current->args.mid(i,j-i);
485 oldStyleArgName=current->args.mid(j).stripWhiteSpace();
489 oldStyleArgName=current->args.copy().stripWhiteSpace();
493 else // continuation like *arg2 in "int *args,*arg2"
497 while (j<l && ((c=current->args.at(j))=='*' || isspace((uchar)c))) j++;
500 oldStyleArgPtr=current->args.left(j);
501 oldStyleArgName=current->args.mid(j).stripWhiteSpace();
505 oldStyleArgName=current->args.copy().stripWhiteSpace();
508 //fprintf(stderr,"type=%s ptr=%s name=%s\n",oldStyleArgType.data(),oldStyleArgPtr.data(),oldStyleArgName.data());
511 //-----------------------------------------------------------------------------
513 /*! Update the argument \a name with additional \a type info. For K&R style
514 * function the type is found \e after the argument list, so this routine
515 * in needed to fix up.
517 static void addKnRArgInfo(const QCString &type,const QCString &name,
518 const QCString &brief,const QCString &docs)
520 if (current->argList==0) return;
521 ArgumentListIterator ali(*current->argList);
523 for (ali.toFirst();(a=ali.current());++ali)
527 a->type=type.stripWhiteSpace();
528 if (a->type.left(9)=="register ") // strip keyword
530 a->type=a->type.mid(9);
532 a->name=name.stripWhiteSpace();
533 if (!brief.isEmpty() && !docs.isEmpty())
535 a->docs=brief+"\n\n"+docs;
537 else if (!brief.isEmpty())
549 //-----------------------------------------------------------------------------
552 void fixArgumentListForJavaScript(ArgumentList *al)
555 ArgumentListIterator ali(*al);
557 for (ali.toFirst();(a=ali.current());++ali)
559 if (!a->type.isEmpty() && a->name.isEmpty())
560 { // a->type is actually the (typeless) parameter name, so move it
567 /* ----------------------------------------------------------------- */
569 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
571 static int yyread(char *buf,int max_size)
576 c = inputFile.readBlock(buf,max_size);
577 if (c==-1) yy_fatal_error("input in flex scanner failed");
581 while( c < max_size && inputString[inputPosition] )
583 *buf = inputString[inputPosition++] ;
584 //printf("%d (%c)\n",*buf,*buf);
593 /* start command character */
595 SECTIONCMD {CMD}("image"|"author"|"internal"|"version"|"date"|"deprecated"|"param"|"exception"|"return"[s]?|"retval"|"bug"|"warning"|"par"|"sa"|"see"|"pre"|"post"|"invariant"|"note"|"remark"[s]?|"todo"|"test"|"xrefitem"|"ingroup"|"callgraph"|"callergraph"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"{"|"verbatim"|"dotfile"|"dot"|"defgroup"|"addtogroup"|"weakgroup"|"class"|"namespace"|"union"|"struct"|"fn"|"var"|"details"|"typedef"|"def"|"overload")|("<"{PRE}">")
599 BS ^(({B}*"//")?)(({B}*"*"+)?){B}*
600 FILESCHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+]
601 FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+]
602 FILE ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]+"\"")
603 ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
604 SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
605 SCOPENAME "$"?(({ID}?{BN}*"::"{BN}*)*)(((~|!){BN}*)?{ID})
606 PHPSCOPENAME ({ID}"\\")+{ID}
607 TSCOPE {ID}("<"[a-z_A-Z0-9 \t\*\&,:]*">")?
608 CSSCOPENAME (({ID}?{BN}*"."{BN}*)*)((~{BN}*)?{ID})
610 CODE [cC][oO][dD][eE]
611 CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'"))
612 PHPKW ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
613 IDLATTR ("["[^\]]*"]"){BN}*
614 TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
615 RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"("
616 RAWEND ")"[^ \t\(\)\\]{0,16}\"
620 /* language parsing states */
679 %x TryFunctionBlockEnd
739 %x CopyArgCommentLine
752 /** Prototype scanner states */
760 /** comment parsing states */
771 BEGIN(SkipCurlyBlock);
775 BEGIN(SkipRoundBlock);
777 <SkipRoundBlock>"(" {
780 <SkipRoundBlock>")" {
786 <SkipCurlyBlock>"{" {
789 <SkipCurlyBlock>"}" {
800 BEGIN( FindMembers );
806 lastStringContext=NextSemi;
807 BEGIN(SkipPHPString);
810 <NextSemi>{CHARLIT} { if (insidePHP) REJECT; }
812 lastStringContext=NextSemi;
817 BEGIN( FindMembers );
821 BEGIN( FindMembers );
823 <EnumBaseType>[{;,] {
824 current->args = current->args.simplifyWhiteSpace();
828 <FindMembers>"<?php" { // PHP code with unsupported extension?
831 <FindMembersPHP>"<?"("php"?) { // PHP code start
832 BEGIN( FindMembers );
834 <FindMembersPHP>"<script"{BN}+"language"{BN}*"="{BN}*['"]?"php"['"]?{BN}*">" { // PHP code start
836 BEGIN( FindMembers );
838 <FindMembersPHP>[^\n<]+ { // Non-PHP code text, ignore
840 <FindMembersPHP>\n { // Non-PHP code text, ignore
843 <FindMembersPHP>. { // Non-PHP code text, ignore
845 <FindMembers>"?>"|"</script>" { // PHP code end
847 BEGIN( FindMembersPHP );
851 <FindMembers>{PHPKW} { if (insidePHP)
856 <FindMembers>"%{"[^\n]* { // Mozilla XPIDL lang-specific block
860 <FindMembers>"%}" { // Mozilla XPIDL lang-specific block end
864 <FindMembers>{B}*("properties"){BN}*":"{BN}* { // IDL or Borland C++ builder property
865 current->mtype = mtype = Property;
866 current->protection = protection = Public ;
867 current->type.resize(0);
868 current->name.resize(0);
869 current->args.resize(0);
870 current->argList->clear();
874 <FindMembers>{B}*"k_dcop"{BN}*":"{BN}* { current->mtype = mtype = DCOP;
875 current->protection = protection = Public ;
876 current->type.resize(0);
877 current->name.resize(0);
878 current->args.resize(0);
879 current->argList->clear();
883 <FindMembers>{B}*("signals"|"Q_SIGNALS"){BN}*":"{BN}* { current->mtype = mtype = Signal;
885 current->protection = protection = Public ;
886 current->type.resize(0);
887 current->name.resize(0);
888 current->args.resize(0);
889 current->argList->clear();
893 <FindMembers>{B}*"public"{BN}*("slots"|"Q_SLOTS"){BN}*":"{BN}* {
894 current->protection = protection = Public ;
895 current->mtype = mtype = Slot;
896 current->type.resize(0);
897 current->name.resize(0);
898 current->args.resize(0);
899 current->argList->clear();
903 <FindMembers>{B}*"protected"{BN}*("slots"|"Q_SLOTS"){BN}*":"{BN}* {
904 current->protection = protection = Protected ;
905 current->mtype = mtype = Slot;
906 current->type.resize(0);
907 current->name.resize(0);
908 current->args.resize(0);
909 current->argList->clear();
913 <FindMembers>{B}*"private"{BN}*("slots"|"Q_SLOTS"){BN}*":"{BN}* {
914 current->protection = protection = Private ;
915 current->mtype = mtype = Slot;
916 current->type.resize(0);
917 current->name.resize(0);
918 current->args.resize(0);
919 current->argList->clear();
922 <FindMembers>{B}*("public"|"methods"|"__published"){BN}*":"{BN}* {
923 current->protection = protection = Public ;
924 current->mtype = mtype = Method;
925 current->type.resize(0);
926 current->name.resize(0);
927 current->args.resize(0);
928 current->argList->clear();
931 <FindMembers>{B}*"internal"{BN}*":"{BN}* { // for now treat C++/CLI's internal as package...
934 current->protection = protection = Package ;
935 current->mtype = mtype = Method;
936 current->type.resize(0);
937 current->name.resize(0);
938 current->args.resize(0);
939 current->argList->clear();
947 <FindMembers>{B}*"protected"{BN}*":"{BN}* {
948 current->protection = protection = Protected ;
949 current->mtype = mtype = Method;
950 current->type.resize(0);
951 current->name.resize(0);
952 current->args.resize(0);
953 current->argList->clear();
956 <FindMembers>{B}*"private"{BN}*":"{BN}* {
957 current->protection = protection = Private ;
958 current->mtype = mtype = Method;
959 current->type.resize(0);
960 current->name.resize(0);
961 current->args.resize(0);
962 current->argList->clear();
965 <FindMembers>{B}*"event"{BN}+ {
970 current->mtype = mtype = Event;
971 current->bodyLine = yyLineNr;
973 BEGIN( CliPropertyType );
978 current->mtype = Event;
979 current->bodyLine = yyLineNr;
986 <FindMembers>{B}*"property"{BN}+ {
991 current->mtype = mtype = Property;
992 current->bodyLine = yyLineNr;
994 BEGIN( CliPropertyType );
1001 <CliPropertyType>{ID} {
1003 current->name = yytext;
1005 <CliPropertyType>"[" { // C++/CLI indexed property
1006 current->name += yytext;
1007 BEGIN( CliPropertyIndex );
1009 <CliPropertyType>"{" {
1011 //printf("event: '%s' '%s'\n",current->type.data(),current->name.data());
1012 BEGIN( CSAccessorDecl );
1014 <CliPropertyType>";" {
1016 BEGIN( FindMembers );
1018 <CliPropertyType>\n {
1021 <CliPropertyType>{B}* {
1023 <CliPropertyType>. {
1025 current->type += yytext;
1027 <CliPropertyIndex>"]" {
1028 BEGIN( CliPropertyType );
1029 current->name+=yytext;
1031 <CliPropertyIndex>. {
1032 current->name+=yytext;
1035 <FindMembers>{B}*"property"{BN}+ {
1036 if (!current->type.isEmpty())
1042 current->mtype = mtype = Property;
1047 <FindMembers>{B}*"@private"{BN}+ {
1048 current->protection = protection = Private ;
1049 current->mtype = mtype = Method;
1050 current->type.resize(0);
1051 current->name.resize(0);
1052 current->args.resize(0);
1053 current->argList->clear();
1056 <FindMembers>{B}*"@protected"{BN}+ {
1057 current->protection = protection = Protected ;
1058 current->mtype = mtype = Method;
1059 current->type.resize(0);
1060 current->name.resize(0);
1061 current->args.resize(0);
1062 current->argList->clear();
1065 <FindMembers>{B}*"@public"{BN}+ {
1066 current->protection = protection = Public ;
1067 current->mtype = mtype = Method;
1068 current->type.resize(0);
1069 current->name.resize(0);
1070 current->args.resize(0);
1071 current->argList->clear();
1074 <FindMembers>[\-+]{BN}* {
1082 current->fileName = yyFileName;
1083 current->startLine = yyLineNr;
1084 current->bodyLine = yyLineNr;
1085 current->section = Entry::FUNCTION_SEC;
1086 current->protection = protection = Public ;
1087 language = current->lang = SrcLangExt_ObjC;
1089 current->virt = Virtual;
1090 current->stat=yytext[0]=='+';
1091 current->mtype = mtype = Method;
1092 current->type.resize(0);
1093 current->name.resize(0);
1094 current->args.resize(0);
1095 current->argList->clear();
1096 BEGIN( ObjCMethod );
1099 <ObjCMethod>"(" { // start of method's return type
1100 BEGIN( ObjCReturnType );
1102 <ObjCMethod>{ID} { // found method name
1103 if (current->type.isEmpty())
1105 current->type = "id";
1107 current->name = yytext;
1109 <ObjCMethod>":"{B}* { // start of parameter list
1110 current->name += ':';
1111 Argument *a = new Argument;
1112 current->argList->append(a);
1113 BEGIN( ObjCParams );
1115 <ObjCReturnType>[^)]* { // TODO: check if nested braches are possible.
1116 current->type = yytext;
1118 <ObjCReturnType>")" {
1119 BEGIN( ObjCMethod );
1121 <ObjCParams>({ID})?":" { // Keyword of parameter
1122 QCString keyw = yytext;
1123 keyw=keyw.left(keyw.length()-1); // strip :
1126 current->name += " :";
1130 current->name += keyw+":";
1132 if (current->argList->getLast()->type.isEmpty())
1134 current->argList->getLast()->type="id";
1136 Argument *a = new Argument;
1137 a->attrib=(QCString)"["+keyw+"]";
1138 current->argList->append(a);
1140 <ObjCParams>{ID}{BN}* { // name of parameter
1142 current->argList->getLast()->name=QCString(yytext).stripWhiteSpace();
1144 <ObjCParams>","{BN}*"..." { // name of parameter
1146 // do we want the comma as part of the name?
1147 //current->name += ",";
1148 Argument *a = new Argument;
1151 current->argList->append(a);
1155 current->name += ':';
1159 BEGIN( ObjCParamType );
1161 <ObjCParamType>[^)]* {
1162 current->argList->getLast()->type=QCString(yytext).stripWhiteSpace();
1164 <ObjCParamType>")"/{B}* {
1165 BEGIN( ObjCParams );
1167 <ObjCMethod,ObjCParams>";" { // end of method declaration
1168 if (current->argList->getLast() && current->argList->getLast()->type.isEmpty())
1170 current->argList->getLast()->type="id";
1172 current->args = argListToString(current->argList);
1173 //printf("argList=%s\n",current->args.data());
1177 <ObjCMethod,ObjCParams>(";"{BN}+)?"{" { // start of a method body
1179 //printf("Type=%s Name=%s args=%s\n",
1180 // current->type.data(),current->name.data(),argListToString(current->argList).data()
1182 if (current->argList->getLast() && current->argList->getLast()->type.isEmpty())
1184 current->argList->getLast()->type="id";
1186 current->args = argListToString(current->argList);
1190 <FindMembers>{BN}{1,80} {
1193 <FindMembers>"@"({ID}".")*{ID}{BN}*"(" {
1194 if (insideJava) // Java annotation
1197 lastSkipRoundContext = YY_START;
1201 else if (strncmp(yytext,"@property",9)==0) // ObjC 2.0 property
1203 current->mtype = mtype = Property;
1204 current->spec|=Entry::Readable | Entry::Writable | Entry::Assign;
1205 current->protection = Public ;
1207 BEGIN( ObjCPropAttr );
1214 <ObjCPropAttr>"getter="{ID} {
1215 current->read = yytext+7;
1217 <ObjCPropAttr>"setter="{ID} {
1218 current->write = yytext+7;
1220 <ObjCPropAttr>"readonly" {
1221 current->spec&=~Entry::Writable;
1223 <ObjCPropAttr>"readwrite" { // default
1225 <ObjCPropAttr>"assign" { // default
1227 <ObjCPropAttr>"unsafe_unretained" {
1228 current->spec&=~Entry::Assign;
1229 current->spec|=Entry::Unretained;
1231 <ObjCPropAttr>"retain" {
1232 current->spec&=~Entry::Assign;
1233 current->spec|=Entry::Retain;
1235 <ObjCPropAttr>"copy" {
1236 current->spec&=~Entry::Assign;
1237 current->spec|=Entry::Copy;
1239 <ObjCPropAttr>"weak" {
1240 current->spec&=~Entry::Assign;
1241 current->spec|=Entry::Weak;
1243 <ObjCPropAttr>"strong" {
1244 current->spec&=~Entry::Assign;
1245 current->spec|=Entry::Strong;
1247 <ObjCPropAttr>"nonatomic" {
1248 current->spec|=Entry::NonAtomic;
1253 <FindMembers>"@"{ID} {
1254 if (insideJava) // Java annotation
1258 else if (strcmp(yytext,"@property")==0) // ObjC 2.0 property
1260 current->mtype = mtype = Property;
1261 current->spec|=Entry::Writable | Entry::Readable;
1262 current->protection = Public ;
1264 else if (strcmp(yytext,"@synthesize")==0)
1266 BEGIN( ObjCSkipStatement );
1268 else if (strcmp(yytext,"@dynamic")==0)
1270 BEGIN( ObjCSkipStatement );
1277 <ObjCSkipStatement>";" {
1280 <PackageName>{ID}(("."|"\\"){ID})* {
1282 //printf("Found namespace %s lang=%d\n",yytext,current->lang);
1283 current->name = yytext;
1284 current->name = substitute(current->name,".","::");
1285 current->name = substitute(current->name,"\\","::");
1286 current->section = Entry::NAMESPACE_SEC;
1287 current->type = "namespace" ;
1288 current->fileName = yyFileName;
1289 current->startLine = yyLineNr;
1290 current->bodyLine = yyLineNr;
1294 current_root->addSubEntry(current);
1295 current_root = current ;
1296 current = new Entry ;
1302 BEGIN( ReadNSBody );
1304 <FindMembers>{B}*"initonly"{BN}+ {
1305 current->type += " initonly ";
1306 if (insideCli) current->spec |= Entry::Initonly;
1309 <FindMembers>{B}*"static"{BN}+ { current->type += " static ";
1310 current->stat = TRUE;
1313 <FindMembers>{B}*"extern"{BN}+ {
1314 current->stat = FALSE;
1315 current->explicitExternal = TRUE;
1318 <FindMembers>{B}*"virtual"{BN}+ { current->type += " virtual ";
1319 current->virt = Virtual;
1322 <FindMembers>{B}*"abstract"{BN}+ {
1325 current->type += " abstract ";
1326 current->virt = Pure;
1330 current->spec|=Entry::Abstract;
1334 <FindMembers>{B}*"inline"{BN}+ { current->spec|=Entry::Inline;
1337 <FindMembers>{B}*"mutable"{BN}+ { current->spec|=Entry::Mutable;
1340 <FindMembers>{B}*"explicit"{BN}+ { current->spec|=Entry::Explicit;
1343 <FindMembers>{B}*"@required"{BN}+ { // Objective C 2.0 protocol required section
1344 current->spec=(current->spec & ~Entry::Optional) | Entry::Required;
1347 <FindMembers>{B}*"@optional"{BN}+ { // Objective C 2.0 protocol optional section
1348 current->spec=(current->spec & ~Entry::Required) | Entry::Optional;
1352 <FindMembers>{B}*"import"{BN}+ { // IDL import keyword
1356 <FindMembers>{B}*"typename"{BN}+ { lineCount(); }
1357 <FindMembers>{B}*"namespace"{BN}*/[^a-z_A-Z0-9] {
1359 current->section = Entry::NAMESPACE_SEC;
1360 current->type = "namespace" ;
1361 current->fileName = yyFileName;
1362 current->startLine = yyLineNr;
1363 current->bodyLine = yyLineNr;
1367 BEGIN( PackageName );
1371 BEGIN( CompoundName );
1374 <FindMembers>{B}*"module"{BN}+ {
1379 current->section = Entry::NAMESPACE_SEC;
1380 current->type = "module" ;
1381 current->fileName = yyFileName;
1382 current->startLine = yyLineNr;
1383 current->bodyLine = yyLineNr;
1384 BEGIN( CompoundName );
1393 addType( current ) ;
1394 current->name = QCString(yytext).stripWhiteSpace();
1397 <FindMembers>{B}*"library"{BN}+ {
1402 current->section = Entry::NAMESPACE_SEC;
1403 current->type = "library" ;
1404 current->fileName = yyFileName;
1405 current->startLine = yyLineNr;
1406 current->bodyLine = yyLineNr;
1407 BEGIN( CompoundName );
1411 addType( current ) ;
1412 current->name = QCString(yytext).stripWhiteSpace();
1415 <FindMembers>{B}*((("disp")?"interface")|"valuetype"){BN}+ { // M$/Corba IDL/Java interface
1417 if (insideIDL || insideJava || insideCS || insideD || insidePHP)
1420 current->section = Entry::CLASS_SEC;
1421 current->spec = Entry::Interface;
1422 addType( current ) ;
1423 current->type += " interface" ;
1424 current->fileName = yyFileName;
1425 current->startLine = yyLineNr;
1426 current->bodyLine = yyLineNr;
1427 BEGIN( CompoundName );
1431 addType( current ) ;
1432 current->name = QCString(yytext).stripWhiteSpace();
1435 <FindMembers>{B}*"@implementation"{BN}+ { // Objective-C class implementation
1438 current->section = Entry::OBJCIMPL_SEC;
1439 language = current->lang = SrcLangExt_ObjC;
1441 current->protection = protection = Public ;
1442 addType( current ) ;
1443 current->type += " implementation" ;
1444 current->fileName = yyFileName;
1445 current->startLine = yyLineNr;
1446 current->bodyLine = yyLineNr;
1447 BEGIN( CompoundName );
1449 <FindMembers>{B}*"@interface"{BN}+ { // Objective-C class interface, or Java attribute
1452 current->section = Entry::CLASS_SEC;
1453 current->spec = Entry::Interface;
1456 language = current->lang = SrcLangExt_ObjC;
1459 current->protection = protection = Public ;
1460 addType( current ) ;
1461 current->type += " interface" ;
1462 current->fileName = yyFileName;
1463 current->startLine = yyLineNr;
1464 current->bodyLine = yyLineNr;
1465 BEGIN( CompoundName );
1467 <FindMembers>{B}*"@protocol"{BN}+ { // Objective-C protocol definition
1470 current->section = Entry::CLASS_SEC;
1471 current->spec = Entry::Protocol;
1472 language = current->lang = SrcLangExt_ObjC;
1474 current->protection = protection = Public ;
1475 addType( current ) ;
1476 current->type += " protocol" ;
1477 current->fileName = yyFileName;
1478 current->startLine = yyLineNr;
1479 current->bodyLine = yyLineNr;
1480 BEGIN( CompoundName );
1482 <FindMembers>{B}*"exception"{BN}+ { // Corba IDL exception
1484 current->section = Entry::CLASS_SEC;
1485 current->spec = Entry::Exception;
1486 addType( current ) ;
1487 current->type += " exception" ;
1488 current->fileName = yyFileName;
1489 current->startLine = yyLineNr;
1490 current->bodyLine = yyLineNr;
1492 BEGIN( CompoundName );
1494 <FindMembers>"@class" | // for Objective C class declarations
1495 <FindMembers>{B}*{TYPEDEFPREFIX}"class{" |
1496 <FindMembers>{B}*{TYPEDEFPREFIX}"class"{BN}+ {
1497 isTypedef=((QCString)yytext).find("typedef")!=-1;
1498 current->section = Entry::CLASS_SEC;
1499 addType( current ) ;
1500 current->type += " class" ;
1501 current->fileName = yyFileName;
1502 current->startLine = yyLineNr;
1503 current->bodyLine = yyLineNr;
1506 language = current->lang = SrcLangExt_ObjC;
1510 if (yytext[yyleng-1]=='{') unput('{');
1511 if (insidePHP && current->spec&Entry::Abstract)
1513 // convert Abstract to AbstractClass
1514 current->spec=(current->spec&~Entry::Abstract)|Entry::AbstractClass;
1516 BEGIN( CompoundName ) ;
1518 <FindMembers>{B}*"value class{" | // C++/CLI extension
1519 <FindMembers>{B}*"value class"{BN}+ {
1521 current->section = Entry::CLASS_SEC;
1522 current->spec = Entry::Value;
1523 addType( current ) ;
1524 current->type += " value class" ;
1525 current->fileName = yyFileName;
1526 current->startLine = yyLineNr;
1527 current->bodyLine = yyLineNr;
1529 if (yytext[yyleng-1]=='{') unput('{');
1530 BEGIN( CompoundName ) ;
1532 <FindMembers>{B}*"ref class{" | // C++/CLI extension
1533 <FindMembers>{B}*"ref class"{BN}+ {
1535 current->section = Entry::CLASS_SEC;
1536 current->spec = Entry::Ref;
1537 addType( current ) ;
1538 current->type += " ref class" ;
1539 current->fileName = yyFileName;
1540 current->startLine = yyLineNr;
1541 current->bodyLine = yyLineNr;
1543 if (yytext[yyleng-1]=='{') unput('{');
1544 BEGIN( CompoundName ) ;
1546 <FindMembers>{B}*"interface class{" | // C++/CLI extension
1547 <FindMembers>{B}*"interface class"{BN}+ {
1549 current->section = Entry::CLASS_SEC;
1550 current->spec = Entry::Interface;
1551 addType( current ) ;
1552 current->type += " interface class" ;
1553 current->fileName = yyFileName;
1554 current->startLine = yyLineNr;
1555 current->bodyLine = yyLineNr;
1557 if (yytext[yyleng-1]=='{') unput('{');
1558 BEGIN( CompoundName ) ;
1560 <FindMembers>{B}*"coclass"{BN}+ {
1564 current->section = Entry::CLASS_SEC;
1565 addType( current ) ;
1566 current->type += " coclass" ;
1567 current->fileName = yyFileName;
1568 current->startLine = yyLineNr;
1569 current->bodyLine = yyLineNr;
1571 BEGIN( CompoundName ) ;
1576 current->name = yytext;
1577 current->name = current->name.stripWhiteSpace();
1581 <FindMembers>{B}*{TYPEDEFPREFIX}"struct{" |
1582 <FindMembers>{B}*{TYPEDEFPREFIX}"struct"/{BN}+ {
1583 isTypedef=((QCString)yytext).find("typedef")!=-1;
1584 current->section = Entry::CLASS_SEC ;
1585 current->spec = Entry::Struct;
1586 // bug 582676: can be a struct nested in an interface so keep insideObjC state
1587 //current->objc = insideObjC = FALSE;
1588 addType( current ) ;
1589 current->type += " struct" ;
1590 current->fileName = yyFileName;
1591 current->startLine = yyLineNr;
1592 current->bodyLine = yyLineNr;
1594 if (yytext[yyleng-1]=='{') unput('{');
1595 BEGIN( CompoundName ) ;
1597 <FindMembers>{B}*"value struct{" | // C++/CLI extension
1598 <FindMembers>{B}*"value struct"{BN}+ {
1600 current->section = Entry::CLASS_SEC;
1601 current->spec = Entry::Struct | Entry::Value;
1602 addType( current ) ;
1603 current->type += " value struct" ;
1604 current->fileName = yyFileName;
1605 current->startLine = yyLineNr;
1606 current->bodyLine = yyLineNr;
1608 if (yytext[yyleng-1]=='{') unput('{');
1609 BEGIN( CompoundName ) ;
1611 <FindMembers>{B}*"ref struct{" | // C++/CLI extension
1612 <FindMembers>{B}*"ref struct"{BN}+ {
1614 current->section = Entry::CLASS_SEC;
1615 current->spec = Entry::Struct | Entry::Ref;
1616 addType( current ) ;
1617 current->type += " ref struct" ;
1618 current->fileName = yyFileName;
1619 current->startLine = yyLineNr;
1620 current->bodyLine = yyLineNr;
1622 if (yytext[yyleng-1]=='{') unput('{');
1623 BEGIN( CompoundName ) ;
1625 <FindMembers>{B}*"interface struct{" | // C++/CLI extension
1626 <FindMembers>{B}*"interface struct"{BN}+ {
1628 current->section = Entry::CLASS_SEC;
1629 current->spec = Entry::Struct | Entry::Interface;
1630 addType( current ) ;
1631 current->type += " interface struct";
1632 current->fileName = yyFileName;
1633 current->startLine = yyLineNr;
1634 current->bodyLine = yyLineNr;
1636 if (yytext[yyleng-1]=='{') unput('{');
1637 BEGIN( CompoundName ) ;
1639 <FindMembers>{B}*{TYPEDEFPREFIX}"union{" |
1640 <FindMembers>{B}*{TYPEDEFPREFIX}"union"{BN}+ {
1641 isTypedef=((QCString)yytext).find("typedef")!=-1;
1642 current->section = Entry::CLASS_SEC;
1643 current->spec = Entry::Union;
1644 // bug 582676: can be a struct nested in an interface so keep insideObjC state
1645 //current->objc = insideObjC = FALSE;
1646 addType( current ) ;
1647 current->type += " union" ;
1648 current->fileName = yyFileName;
1649 current->startLine = yyLineNr;
1650 current->bodyLine = yyLineNr;
1652 if (yytext[yyleng-1]=='{') unput('{');
1653 BEGIN( CompoundName ) ;
1655 <FindMembers>{B}*{TYPEDEFPREFIX}{IDLATTR}?"enum"({BN}+("class"|"struct"))?"{" |
1656 <FindMembers>{B}*{TYPEDEFPREFIX}{IDLATTR}?"enum"({BN}+("class"|"struct"))?{BN}+ { // for IDL: typedef [something] enum
1657 QCString text=yytext;
1658 isTypedef = text.find("typedef")!=-1;
1659 bool isStrongEnum = text.find("struct")!=-1 || text.find("class")!=-1;
1662 current->section = Entry::CLASS_SEC;
1663 current->spec = Entry::Enum;
1667 current->section = Entry::ENUM_SEC ;
1669 addType( current ) ;
1670 current->type += " enum";
1673 current->spec |= Entry::Strong;
1675 current->fileName = yyFileName;
1676 current->startLine = yyLineNr;
1677 current->bodyLine = yyLineNr;
1679 if (yytext[yyleng-1]=='{') unput('{');
1680 BEGIN( CompoundName ) ;
1682 <Operator>"("{BN}*")"({BN}*"<"[^>]*">"){BN}*/"(" { // A::operator()<int>(int arg)
1684 current->name += "()";
1685 BEGIN( FindMembers );
1687 <Operator>"("{BN}*")"{BN}*/"(" {
1689 current->name += yytext ;
1690 current->name = current->name.simplifyWhiteSpace();
1691 BEGIN( FindMembers ) ;
1693 <Operator>";" { // can occur when importing members
1695 BEGIN( FindMembers ) ;
1699 current->name += *yytext ;
1701 <Operator>"<>" { /* skip guided templ specifiers */ }
1703 current->name = current->name.simplifyWhiteSpace();
1705 BEGIN( FindMembers ) ;
1707 <FindMembers>("template"|"generic")({BN}*)"<"/[>]? { // generic is a C++/CLI extension
1709 if (current->tArgLists==0)
1711 current->tArgLists = new QList<ArgumentList>;
1712 current->tArgLists->setAutoDelete(TRUE);
1714 ArgumentList *al = new ArgumentList;
1715 //current->spec |= (yytext[0]=='g') ? Entry::Generic : Entry::Template;
1716 current->tArgLists->append(al);
1717 currentArgumentList = al;
1719 fullArgString = templateStr;
1720 copyArgString = &templateStr;
1721 currentArgumentContext = FindMembers;
1722 BEGIN( ReadTempArgs );
1724 <FindMembers>"namespace"{BN}+/{ID}{BN}*"=" { // namespace alias
1726 BEGIN( NSAliasName );
1730 BEGIN( NSAliasArg );
1732 <NSAliasArg>({ID}"::")*{ID} {
1733 //printf("Inserting namespace alias %s::%s->%s\n",current_root->name.data(),aliasName.data(),yytext);
1734 //if (current_root->name.isEmpty())
1736 // TODO: namespace aliases are now treated as global entities
1737 // while they should be aware of the scope they are in
1738 Doxygen::namespaceAliasDict.insert(aliasName,new QCString(yytext));
1742 // Doxygen::namespaceAliasDict.insert(current_root->name+"::"+aliasName,
1743 // new QCString(current_root->name+"::"+yytext));
1747 BEGIN( FindMembers );
1749 <PHPUse>({ID}{BN}*"\\"{BN}*)*{ID}/{BN}+"as" {
1754 <PHPUse>({ID}{BN}*"\\"{BN}*)*{ID} {
1756 current->name=removeRedundantWhiteSpace(substitute(yytext,"\\","::"));
1757 //printf("PHP: adding use relation: %s\n",current->name.data());
1758 current->fileName = yyFileName;
1759 // add a using declaraton
1760 current->section=Entry::USINGDECL_SEC;
1761 current_root->addSubEntry(current);
1762 current = new Entry(*current);
1763 // also add it as a using directive
1764 current->section=Entry::USINGDIR_SEC;
1765 current_root->addSubEntry(current);
1766 current = new Entry ;
1768 aliasName.resize(0);
1770 <PHPUseAs>{BN}+"as"{BN}+ {
1774 //printf("PHP: adding use as relation: %s->%s\n",yytext,aliasName.data());
1775 Doxygen::namespaceAliasDict.insert(yytext,
1776 new QCString(removeRedundantWhiteSpace(
1777 substitute(aliasName,"\\","::"))));
1778 aliasName.resize(0);
1780 <PHPUse,PHPUseAs>[,;] {
1790 <JavaImport>({ID}{BN}*"."{BN}*)+"*" { // package import => add as a using directive
1792 QCString scope=yytext;
1793 current->name=removeRedundantWhiteSpace(substitute(scope.left(scope.length()-1),".","::"));
1794 current->fileName = yyFileName;
1795 current->section=Entry::USINGDIR_SEC;
1796 current_root->addSubEntry(current);
1797 current = new Entry;
1801 <JavaImport>({ID}{BN}*"."{BN}*)+{ID} { // class import => add as a using declaration
1803 QCString scope=yytext;
1804 current->name=removeRedundantWhiteSpace(substitute(scope,".","::"));
1805 current->fileName = yyFileName;
1808 current->section=Entry::USINGDIR_SEC;
1812 //printf("import name = %s -> %s\n",yytext,current->name.data());
1813 current->section=Entry::USINGDECL_SEC;
1815 current_root->addSubEntry(current);
1816 current = new Entry ;
1820 <FindMembers>"using"{BN}+ {
1821 current->startLine=yyLineNr;
1825 <Using>"namespace"{BN}+ { lineCount(); BEGIN(UsingDirective); }
1826 <Using>{ID}{BN}*({BN}*("::"|"."){BN}*{ID})* {
1828 current->name=yytext;
1829 current->fileName = yyFileName;
1830 current->section=Entry::USINGDECL_SEC;
1831 current->startLine = yyLineNr;
1832 current_root->addSubEntry(current);
1834 current = new Entry ;
1835 if (insideCS) /* Hack: in C# a using declaration and
1836 directive have the same syntax, so we
1837 also add it as a using directive here
1840 current->name=yytext;
1841 current->fileName = yyFileName;
1842 current->startLine = yyLineNr;
1843 current->section=Entry::USINGDIR_SEC;
1844 current_root->addSubEntry(current);
1845 current = new Entry ;
1850 <Using>"=" { // C++11 style template alias?
1854 previous->section=Entry::VARIABLE_SEC;
1855 previous->type = "typedef "+previous->args;
1856 previous->type=previous->type.simplifyWhiteSpace();
1857 previous->args.resize(0);
1858 previous->name=previous->name.stripWhiteSpace();
1859 previous->bodyLine = yyLineNr;
1860 previous->spec |= Entry::Alias;
1864 previous->args+=yytext;
1867 previous->args+=yytext;
1870 <UsingDirective>{SCOPENAME} { current->name=removeRedundantWhiteSpace(yytext);
1871 current->fileName = yyFileName;
1872 current->section=Entry::USINGDIR_SEC;
1873 current_root->addSubEntry(current);
1874 current = new Entry ;
1878 <Using>";" { BEGIN(FindMembers); }
1879 <FindMembers>{SCOPENAME}{BN}*"<>" { // guided template decl
1882 current->name=n.left(n.length()-2);
1884 <FindMembers>{SCOPENAME}{BN}*/"<" { // Note: this could be a return type!
1889 current->name=yytext;
1890 current->name=current->name.stripWhiteSpace();
1891 //current->scopeSpec.resize(0);
1892 // currentTemplateSpec = ¤t->scopeSpec;
1893 if (nameIsOperator(current->name))
1896 BEGIN( EndTemplate );
1898 <FindMemberName>{SCOPENAME}{BN}*/"<" {
1902 current->name+=((QCString)yytext).stripWhiteSpace();
1903 //current->memberSpec.resize(0);
1904 // currentTemplateSpec = ¤t->memberSpec;
1905 if (nameIsOperator(current->name))
1908 BEGIN( EndTemplate );
1910 <EndTemplate>"<<<" {
1917 lastHereDocContext = YY_START;
1921 <ClassTemplSpec,EndTemplate>"<<" {
1922 current->name+=yytext;
1923 // *currentTemplateSpec+=yytext;
1927 // *currentTemplateSpec+='<';
1930 <ClassTemplSpec,EndTemplate>">>" {
1931 if (insideJava || insideCS || insideCli || roundCount==0)
1939 current->name+=yytext;
1941 // *currentTemplateSpec+=yytext;
1945 // *currentTemplateSpec+='>';
1946 if (--sharpCount<=0)
1948 //printf("Found %s\n",current->name.data());
1952 <EndTemplate>">"{BN}*"(" {
1955 // *currentTemplateSpec+='>';
1956 if (--sharpCount<=0)
1958 current->bodyLine = yyLineNr;
1959 current->args = "(";
1960 currentArgumentContext = FuncQual;
1961 fullArgString = current->args.copy();
1962 copyArgString = ¤t->args;
1963 //printf("Found %s\n",current->name.data());
1964 BEGIN( ReadFuncArgType ) ;
1967 <EndTemplate>">"{BN}*/"("({BN}*{ID}{BN}*"::")*({BN}*"*"{BN}*)+ { // function pointer returning a template instance
1972 <EndTemplate>">"{BN}*/"::" {
1975 // *currentTemplateSpec+='>';
1976 if (--sharpCount<=0)
1978 BEGIN(FindMemberName);
1981 <ClassTemplSpec,EndTemplate>"(" { current->name+=*yytext;
1984 <ClassTemplSpec,EndTemplate>")" { current->name+=*yytext;
1985 if (roundCount>0) roundCount--;
1988 current->name+=*yytext;
1989 // *currentTemplateSpec+=*yytext;
1991 <FindMembers>"define"{BN}*"("{BN}*["'] {
1994 current->bodyLine = yyLineNr;
2000 <CopyHereDoc>{ID} { // PHP heredoc
2001 g_delimiter = yytext;
2002 *pCopyHereDocGString += yytext;
2003 BEGIN(CopyHereDocEnd);
2005 <CopyHereDoc>"'"{ID}/"'" { // PHP nowdoc
2006 g_delimiter = &yytext[1];
2007 *pCopyHereDocGString += yytext;
2008 BEGIN(CopyHereDocEnd);
2010 <HereDoc>{ID} { // PHP heredoc
2011 g_delimiter = yytext;
2014 <HereDoc>"'"{ID}/"'" { // PHP nowdoc
2015 g_delimiter = &yytext[1];
2018 <HereDocEnd>^{ID} { // id at start of the line could mark the end of the block
2019 if (g_delimiter==yytext) // it is the end marker
2021 BEGIN(lastHereDocContext);
2025 <CopyHereDocEnd>^{ID} { // id at start of the line could mark the end of the block
2026 *pCopyHereDocGString += yytext;
2027 if (g_delimiter==yytext) // it is the end marker
2029 BEGIN(lastHereDocContext);
2032 <CopyHereDocEnd>\n {
2033 *pCopyHereDocGString += yytext;
2036 *pCopyHereDocGString += yytext;
2038 <FindMembers>"Q_OBJECT" { // Qt object macro
2040 <FindMembers>"Q_PROPERTY" { // Qt property declaration
2041 current->protection = protection = Public ;
2042 current->mtype = mtype = Property;
2043 current->type.resize(0);
2046 <QtPropType>"(" { // start of property arguments
2048 <QtPropAttr>")" { // end of property arguments
2052 <QtPropType>"const"|"volatile" {
2053 current->type+=yytext;
2056 current->type+=yytext;
2058 <QtPropType>({TSCOPE}"::")*{TSCOPE} {
2059 current->type+=yytext;
2063 current->name=yytext;
2066 <QtPropAttr>"READ" {
2067 current->spec |= Entry::Readable;
2070 <QtPropAttr>"WRITE" {
2071 current->spec |= Entry::Writable;
2074 <QtPropAttr>"RESET"{B}+{ID} { // reset method => not supported yet
2076 <QtPropAttr>"SCRIPTABLE"{B}+{ID} { // scriptable property => not supported yet
2078 <QtPropAttr>"DESIGNABLE"{B}+{ID} { // designable property => not supported yet
2081 current->read = yytext;
2085 current->write = yytext;
2088 <FindMembers>"friend"{BN}+("class"|"union"|"struct"){BN}+ {
2089 current->name=yytext;
2092 <FindMembers,FindMemberName>{SCOPENAME} {
2094 if (insideIDL && yyleng==9 && strcmp(yytext,"cpp_quote")==0)
2098 else if ((insideIDL || insideJava || insideD) && yyleng==6 && strcmp(yytext,"import")==0)
2102 else // insideJava or insideD
2105 else if (insidePHP && strcmp(yytext,"use")==0)
2109 else if (insideJava && strcmp(yytext,"package")==0)
2114 else if (insideIDL && strcmp(yytext,"case")==0)
2116 BEGIN(IDLUnionCase);
2118 else if (insideTryBlock && strcmp(yytext,"catch")==0)
2120 insideTryBlock=FALSE;
2121 BEGIN(TryFunctionBlock);
2123 else if (insideJS && strcmp(yytext,"var")==0)
2124 { // javascript variable
2125 current->type="var";
2127 else if (insideJS && strcmp(yytext,"function")==0)
2128 { // javascript function
2129 current->type="function";
2131 else if (insideCS && strcmp(yytext,"this")==0)
2134 addType( current ) ;
2135 current->name="this";
2138 else if (insideCpp && strcmp(yytext,"static_assert")==0)
2140 // C++11 static_assert
2141 BEGIN(StaticAssert);
2143 else if (insideCpp && strcmp(yytext,"decltype")==0)
2145 // C++11 decltype(x)
2146 current->type+=yytext;
2151 if (YY_START==FindMembers)
2153 addType( current ) ;
2155 bool javaLike = insideJava || insideCS || insideD || insidePHP || insideJS;
2156 if (javaLike && strcmp(yytext,"public")==0)
2158 current->protection = Public;
2160 else if (javaLike && strcmp(yytext,"protected")==0)
2162 current->protection = Protected;
2164 else if (javaLike && strcmp(yytext,"internal")==0)
2166 current->protection = Package;
2168 else if (javaLike && strcmp(yytext,"private")==0)
2170 current->protection = Private;
2172 else if (javaLike && strcmp(yytext,"static")==0)
2174 if (YY_START==FindMembers)
2175 current->name = yytext;
2177 current->name += yytext;
2178 current->stat = TRUE;
2182 if (YY_START==FindMembers)
2183 current->name = yytext;
2185 current->name += yytext;
2186 if (current->name.left(7)=="static ")
2188 current->stat = TRUE;
2189 current->name= current->name.mid(7);
2191 else if (current->name.left(7)=="inline ")
2193 if (current->type.isEmpty())
2195 current->type="inline";
2199 current->type+="inline ";
2201 current->name= current->name.mid(7);
2203 else if (current->name.left(6)=="const ")
2205 if (current->type.isEmpty())
2207 current->type="const";
2211 current->type+="const ";
2213 current->name=current->name.mid(6);
2216 QCString tmp=yytext;
2217 if (nameIsOperator(tmp))
2228 lastSkipRoundContext = FindMembers;
2232 <StaticAssert>{BN}+ { lineCount(); }
2233 <StaticAssert>. { // variable with static_assert as name?
2238 current->type+=yytext;
2239 lastRoundContext=FindMembers;
2240 pCopyRoundString=¤t->type;
2244 <DeclType>{BN}+ { lineCount(); }
2249 <CSIndexer>"["[^\n\]]*"]" {
2250 current->name+=removeRedundantWhiteSpace(yytext);
2253 <FindMembers>[0-9]{ID} { // some number where we did not expect one
2256 if (insideJava || insideCS || insideD)
2262 current->name+=yytext;
2264 <CppQuote>"("{B}*"\"" {
2265 insideCppQuote=TRUE;
2269 <IDLUnionCase>":" { BEGIN(FindMembers); }
2270 <IDLUnionCase>\n { lineCount(); }
2272 <TryFunctionBlock>\n { lineCount(); }
2273 <TryFunctionBlock>"{" {
2275 lastCurlyContext = TryFunctionBlockEnd ;
2279 <TryFunctionBlockEnd>{BN}*"catch" { lineCount(); BEGIN(TryFunctionBlock); // {BN}* added to fix bug 611193
2281 <TryFunctionBlockEnd>\n { unput(*yytext); // rule added to fix bug id 601138
2282 BEGIN( FindMembers );
2284 <TryFunctionBlockEnd>. { unput(*yytext);
2285 BEGIN( FindMembers );
2288 insideCppQuote=FALSE;
2291 <FindMembers,FindFields>{B}*"#" { if (insidePHP)
2293 lastCPPContext = YY_START;
2296 <FindMembers,FindFields>{B}*"#"{B}*("cmake")?"define" {
2299 current->bodyLine = yyLineNr;
2300 lastDefineContext = YY_START;
2303 <FindMembers,ReadBody,ReadNSBody,ReadBodyIntf,SkipCurly,SkipCurlyCpp>{B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */
2304 yyLineNr = atoi(&yytext[1]);
2305 //printf("setting line number to %d\n",yyLineNr);
2306 lastPreLineCtrlContext = YY_START;
2307 if (YY_START==ReadBody ||
2308 YY_START==ReadNSBody ||
2309 YY_START==ReadBodyIntf)
2311 current->program+=yytext;
2313 BEGIN( PreLineCtrl );
2315 <PreLineCtrl>"\""[^\n\"]*"\"" {
2316 yyFileName = stripQuotes(yytext);
2317 if (lastPreLineCtrlContext==ReadBody ||
2318 lastPreLineCtrlContext==ReadNSBody ||
2319 lastPreLineCtrlContext==ReadBodyIntf)
2321 current->program+=yytext;
2325 if (lastPreLineCtrlContext==ReadBody ||
2326 lastPreLineCtrlContext==ReadNSBody ||
2327 lastPreLineCtrlContext==ReadBodyIntf)
2329 current->program+=yytext;
2333 if (lastPreLineCtrlContext==ReadBody ||
2334 lastPreLineCtrlContext==ReadNSBody ||
2335 lastPreLineCtrlContext==ReadBodyIntf)
2337 current->program+=yytext;
2340 BEGIN( lastPreLineCtrlContext );
2343 <SkipCPP>\\[\r]*"\n"[\r]* { lineCount(); }
2344 <SkipCPP>[\r]*\n[\r]* { lineCount();
2345 BEGIN( lastCPPContext) ;
2347 <Define>{ID}{B}*"(" {
2348 current->name = yytext;
2349 current->name = current->name.left(current->name.length()-1).stripWhiteSpace();
2350 current->args = "(";
2351 current->bodyLine = yyLineNr;
2352 currentArgumentContext = DefineEnd;
2353 fullArgString=current->args.copy();
2354 copyArgString=¤t->args;
2355 BEGIN( ReadFuncArgType ) ;
2359 //printf("Define with args\n");
2360 current->args += ')';
2364 current->args += *yytext;
2368 //printf("Define `%s' without args\n",yytext);
2369 current->bodyLine = yyLineNr;
2370 current->name = yytext;
2374 //printf("End define: doc=%s docFile=%s docLine=%d\n",current->doc.data(),current->docFile.data(),current->docLine);
2376 current->fileName = yyFileName;
2377 current->startLine = yyLineNr;
2378 current->type.resize(0);
2379 current->args = current->args.simplifyWhiteSpace();
2380 current->name = current->name.stripWhiteSpace();
2381 current->section = Entry::DEFINE_SEC;
2382 current_root->addSubEntry(current);
2383 current = new Entry ;
2385 BEGIN(lastDefineContext);
2388 //printf("End define\n");
2389 current->fileName = yyFileName;
2390 current->startLine = yyLineNr;
2391 current->type.resize(0);
2392 current->type = "const";
2393 QCString init = current->initializer.data();
2394 init = init.simplifyWhiteSpace();
2395 init = init.left(init.length()-1);
2396 current->initializer = init;
2397 current->name = current->name.stripWhiteSpace();
2398 current->section = Entry::VARIABLE_SEC;
2399 current_root->addSubEntry(current);
2400 current = new Entry ;
2405 <DefineEnd>\\[\r]?\n {
2409 if (insideIDL && insideCppQuote)
2415 lastStringContext=DefineEnd;
2420 <DefinePHP>{ID}["']{BN}*","{BN}* {
2421 current->name = yytext;
2422 current->name = current->name.stripWhiteSpace();
2423 current->name = current->name.left(current->name.length()-1).stripWhiteSpace();
2424 current->name = current->name.left(current->name.length()-1);
2425 current->bodyLine = yyLineNr;
2426 lastRoundContext = DefinePHPEnd;
2427 pCopyRoundGString = ¤t->initializer;
2429 BEGIN( GCopyRound );
2432 <FindMembers>[\^%] { // ^ and % are C++/CLI extensions
2436 current->name = yytext ;
2443 <FindMembers>[*&]+ {
2444 current->name += yytext ;
2447 <FindMembers,MemberSpec,Function,NextSemi,EnumBaseType,BitFields,ReadInitializer,OldStyleArgs>";"{BN}*("/**"|"//!"|"/*!"|"///")"<" {
2449 if (current->bodyLine==-1)
2451 current->bodyLine=yyLineNr;
2453 docBlockContext = YY_START;
2454 docBlockInBody = FALSE;
2455 docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF") ) ||
2456 ( yytext[yyleng-2]=='!' && Config_getBool("QT_AUTOBRIEF") );
2459 if (YY_START==EnumBaseType && current->section==Entry::ENUM_SEC)
2461 current->bitfields = ":"+current->args;
2462 current->args.resize(0);
2463 current->section=Entry::VARIABLE_SEC;
2465 if (yytext[yyleng-3]=='/')
2467 startCommentBlock(TRUE);
2472 startCommentBlock(FALSE);
2476 <MemberSpec,FindFields,FindMembers,NextSemi,EnumBaseType,BitFields,ReadInitializer,OldStyleArgs>","{BN}*("/**"|"//!"|"/*!"|"///")"<" {
2478 docBlockContext = YY_START;
2479 docBlockInBody = FALSE;
2480 docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF") ) ||
2481 ( yytext[yyleng-2]=='!' && Config_getBool("QT_AUTOBRIEF") );
2484 if (YY_START==EnumBaseType && current->section==Entry::ENUM_SEC)
2486 current->bitfields = ":"+current->args;
2487 current->args.resize(0);
2488 current->section=Entry::VARIABLE_SEC;
2490 if (yytext[yyleng-3]=='/')
2492 startCommentBlock(TRUE);
2497 startCommentBlock(FALSE);
2501 <DefineEnd,FindFields,FindFieldArg,ReadInitializer,OldStyleArgs>{BN}*("/**"|"//!"|"/*!"|"///")"<" {
2503 if (current->bodyLine==-1)
2505 current->bodyLine=yyLineNr;
2507 docBlockContext = YY_START;
2508 docBlockInBody = FALSE;
2509 docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF") ) ||
2510 ( yytext[yyleng-2]=='!' && Config_getBool("QT_AUTOBRIEF") );
2513 if (yytext[yyleng-3]=='/')
2515 startCommentBlock(TRUE);
2520 startCommentBlock(FALSE);
2525 <FindMembers,FindFields>("//"([!/]?){B}*{CMD}"{")|("/*"([!*]?){B}*{CMD}"{") {
2526 //handleGroupStartCommand(current->name);
2527 if (previous && previous->section==Entry::GROUPDOC_SEC)
2529 // link open command to the group defined in the previous entry
2530 openGroup(previous,yyFileName,yyLineNr);
2534 // link open command to the current entry
2535 openGroup(current,yyFileName,yyLineNr);
2541 if (yytext[2]=='!' || yytext[2]=='/')
2543 docBlockContext = YY_START;
2544 docBlockInBody = FALSE;
2545 docBlockAutoBrief = FALSE;
2548 startCommentBlock(TRUE);
2553 lastCContext=YY_START;
2554 BEGIN(SkipCxxComment);
2559 if (yytext[2]=='!' || yytext[2]=='*')
2561 docBlockContext = YY_START;
2562 docBlockInBody = FALSE;
2564 docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF") ) ||
2565 ( yytext[yyleng-2]=='!' && Config_getBool("QT_AUTOBRIEF") );
2567 startCommentBlock(FALSE);
2572 lastCContext=YY_START;
2577 <FindMembers,FindFields,ReadInitializer>"//"([!/]?){B}*{CMD}"}".*|"/*"([!*]?){B}*{CMD}"}"[^*]*"*/" {
2578 closeGroup(current,yyFileName,yyLineNr);
2580 <FindMembers>"=" { // in PHP code this could also be due to "<?="
2581 current->bodyLine = yyLineNr;
2582 current->initializer = yytext;
2583 lastInitializerContext = YY_START;
2585 BEGIN(ReadInitializer);
2587 /* Read initializer rules */
2588 <ReadInitializer>"(" {
2589 lastRoundContext=YY_START;
2590 pCopyRoundGString=¤t->initializer;
2592 current->initializer+=*yytext;
2595 <ReadInitializer>"{" {
2596 lastCurlyContext=YY_START;
2597 pCopyCurlyGString=¤t->initializer;
2599 current->initializer+=*yytext;
2602 <ReadInitializer>[;,] {
2603 //printf(">> initializer `%s' <<\n",current->initializer.data());
2604 if (*yytext==';' && (current_root->spec&Entry::Enum))
2606 current->fileName = yyFileName;
2607 current->startLine = yyLineNr;
2608 current->args = current->args.simplifyWhiteSpace();
2609 current->name = current->name.stripWhiteSpace();
2610 current->section = Entry::VARIABLE_SEC;
2611 current_root->addSubEntry(current);
2612 current = new Entry;
2616 else if (*yytext==';' || (lastInitializerContext==FindFields && initBracketCount==0)) // initBracketCount==0 was added for bug 665778
2619 BEGIN(lastInitializerContext);
2621 else if (*yytext==',' && initBracketCount==0) // for "int a=0,b=0"
2624 BEGIN(lastInitializerContext);
2628 current->initializer+=*yytext;
2631 <ReadInitializer>{RAWBEGIN} { // C++11 raw string
2638 QCString text=yytext;
2639 current->initializer+=text;
2640 int i=text.find('"');
2641 g_delimiter = yytext+i+1;
2642 g_delimiter=g_delimiter.left(g_delimiter.length()-1);
2643 lastRawStringContext = YY_START;
2644 pCopyRawGString = ¤t->initializer;
2646 //printf("RawGString delimiter='%s'\n",delimiter.data());
2649 <RawGString>{RAWEND} {
2650 *pCopyRawGString+=yytext;
2651 QCString delimiter = yytext+1;
2652 delimiter=delimiter.left(delimiter.length()-1);
2653 if (delimiter==g_delimiter)
2655 BEGIN(lastRawStringContext);
2659 *pCopyRawGString+=yytext;
2662 *pCopyRawGString+=yytext;
2665 *pCopyRawGString+=yytext;
2668 <RawString>{RAWEND} {
2669 *pCopyRawString+=yytext;
2670 fullArgString+=yytext;
2671 QCString delimiter = yytext+1;
2672 delimiter=delimiter.left(delimiter.length()-1);
2673 if (delimiter==g_delimiter)
2675 BEGIN(lastRawStringContext);
2679 *pCopyRawString+=yytext;
2680 fullArgString+=yytext;
2683 *pCopyRawString+=yytext;
2684 fullArgString+=yytext;
2687 *pCopyRawString+=yytext;
2688 fullArgString+=yytext;
2691 <ReadInitializer>\" {
2692 if (insideIDL && insideCppQuote)
2698 lastStringContext=YY_START;
2699 current->initializer+=yytext;
2700 pCopyQuotedGString=¤t->initializer;
2704 <ReadInitializer>"->" {
2705 current->initializer+=yytext;
2707 <ReadInitializer>"<<" {
2708 current->initializer+=yytext;
2710 <ReadInitializer>">>" {
2711 current->initializer+=yytext;
2713 <ReadInitializer>[<\[{(] {
2715 current->initializer+=*yytext;
2717 <ReadInitializer>[>\]})] {
2719 current->initializer+=*yytext;
2721 <ReadInitializer>\' {
2724 current->initializer+=yytext;
2725 pCopyQuotedGString = ¤t->initializer;
2726 lastStringContext=YY_START;
2727 BEGIN(CopyPHPGString);
2731 current->initializer+=yytext;
2734 <ReadInitializer>{CHARLIT} {
2741 current->initializer+=yytext;
2744 <ReadInitializer>\n {
2745 current->initializer+=*yytext;
2748 <ReadInitializer>"@\"" {
2749 //printf("insideCS=%d\n",insideCS);
2750 current->initializer+=yytext;
2751 if (!insideCS && !insideObjC)
2757 // C#/ObjC verbatim string
2758 lastSkipVerbStringContext=YY_START;
2759 pSkipVerbString=¤t->initializer;
2760 BEGIN(SkipVerbString);
2763 <SkipVerbString>[^\n"]+ {
2764 *pSkipVerbString+=yytext;
2766 <SkipVerbString>"\"\"" { // quote escape
2767 *pSkipVerbString+=yytext;
2769 <SkipVerbString>"\"" {
2770 *pSkipVerbString+=*yytext;
2771 BEGIN(lastSkipVerbStringContext);
2773 <SkipVerbString>\n {
2774 *pSkipVerbString+=*yytext;
2778 *pSkipVerbString+=*yytext;
2780 <ReadInitializer>"?>" {
2782 BEGIN( FindMembersPHP );
2784 current->initializer+=yytext;
2786 <ReadInitializer>. {
2787 current->initializer+=*yytext;
2790 /* generic quoted string copy rules */
2791 <CopyString,CopyPHPString>\\. {
2792 *pCopyQuotedString+=yytext;
2795 *pCopyQuotedString+=*yytext;
2796 BEGIN( lastStringContext );
2799 *pCopyQuotedString+=*yytext;
2800 BEGIN( lastStringContext );
2802 <CopyString,CopyPHPString>"/*"|"*/"|"//" {
2803 *pCopyQuotedString+=yytext;
2805 <CopyString,CopyPHPString>\n {
2806 *pCopyQuotedString+=*yytext;
2809 <CopyString,CopyPHPString>. {
2810 *pCopyQuotedString+=*yytext;
2813 /* generic quoted growable string copy rules */
2814 <CopyGString,CopyPHPGString>\\. {
2815 *pCopyQuotedGString+=yytext;
2818 *pCopyQuotedGString+=*yytext;
2819 BEGIN( lastStringContext );
2821 <CopyPHPGString>\' {
2822 *pCopyQuotedGString+=*yytext;
2823 BEGIN( lastStringContext );
2825 <CopyGString,CopyPHPGString>"/*"|"*/"|"//" {
2826 *pCopyQuotedGString+=yytext;
2828 <CopyGString,CopyPHPGString>\n {
2829 *pCopyQuotedGString+=*yytext;
2832 <CopyGString,CopyPHPGString>. {
2833 *pCopyQuotedGString+=*yytext;
2836 /* generic round bracket list copy rules */
2838 *pCopyRoundString+=*yytext;
2839 pCopyQuotedString=pCopyRoundString;
2840 lastStringContext=YY_START;
2844 *pCopyRoundString+=*yytext;
2848 *pCopyRoundString+=*yytext;
2850 BEGIN(lastRoundContext);
2854 *pCopyRoundString+=*yytext;
2859 current->initializer+=yytext;
2860 pCopyQuotedString = pCopyRoundString;
2861 lastStringContext=YY_START;
2862 BEGIN(CopyPHPString);
2866 *pCopyRoundString+=yytext;
2869 <CopyRound>{CHARLIT} {
2876 *pCopyRoundString+=yytext;
2879 <CopyRound>[^"'()\n]+ {
2880 *pCopyRoundString+=yytext;
2883 *pCopyRoundString+=*yytext;
2886 /* generic round bracket list copy rules for growable strings */
2888 *pCopyRoundGString+=*yytext;
2889 pCopyQuotedGString=pCopyRoundGString;
2890 lastStringContext=YY_START;
2894 *pCopyRoundGString+=*yytext;
2898 *pCopyRoundGString+=*yytext;
2900 BEGIN(lastRoundContext);
2904 *pCopyRoundGString+=*yytext;
2909 current->initializer+=yytext;
2910 pCopyQuotedGString = pCopyRoundGString;
2911 lastStringContext=YY_START;
2912 BEGIN(CopyPHPGString);
2916 *pCopyRoundGString+=yytext;
2919 <GCopyRound>{CHARLIT} {
2926 *pCopyRoundGString+=yytext;
2929 <GCopyRound>[^"'()\n/]+ {
2930 *pCopyRoundGString+=yytext;
2933 *pCopyRoundGString+=*yytext;
2936 /* generic curly bracket list copy rules */
2938 *pCopyCurlyString+=*yytext;
2939 pCopyQuotedString=pCopyCurlyString;
2940 lastStringContext=YY_START;
2944 *pCopyCurlyString+=*yytext;
2947 pCopyQuotedString=pCopyCurlyString;
2948 lastStringContext=YY_START;
2949 BEGIN(CopyPHPString);
2953 *pCopyCurlyString+=*yytext;
2957 *pCopyCurlyString+=*yytext;
2959 BEGIN(lastCurlyContext);
2961 <CopyCurly>{CHARLIT} { if (insidePHP)
2967 *pCopyCurlyString+=yytext;
2970 <CopyCurly>[^"'{}\/\n]+ {
2971 *pCopyCurlyString+=yytext;
2973 <CopyCurly>"/" { *pCopyCurlyString+=yytext; }
2976 *pCopyCurlyString+=*yytext;
2979 *pCopyCurlyString+=*yytext;
2982 /* generic curly bracket list copy rules for growable strings */
2983 <GCopyCurly>^"#"{B}+[0-9]+{B}+"\""[^\"\n]+"\""{B}+"1"{B}*\n? { // start of included file marker
2985 <GCopyCurly>^"#"{B}+[0-9]+{B}+"\""[^\"\n]+"\""{B}+"2"{B}*\n? { // end of included file marker
2986 QCString line = QCString(yytext);
2987 int s = line.find(' ');
2988 int e = line.find('"',s);
2989 yyLineNr = line.mid(s,e-s).toInt();
2990 if (yytext[yyleng-1]=='\n')
2997 *pCopyCurlyGString+=*yytext;
2998 pCopyQuotedGString=pCopyCurlyGString;
2999 lastStringContext=YY_START;
3003 *pCopyCurlyGString+=*yytext;
3006 pCopyQuotedGString=pCopyCurlyGString;
3007 lastStringContext=YY_START;
3008 BEGIN(CopyPHPGString);
3012 *pCopyCurlyGString+=*yytext;
3016 *pCopyCurlyGString+=*yytext;
3018 BEGIN(lastCurlyContext);
3020 <GCopyCurly>{CHARLIT} { if (insidePHP)
3026 *pCopyCurlyGString+=yytext;
3029 <GCopyCurly>[^"'{}\/\n]+ {
3030 *pCopyCurlyGString+=yytext;
3032 <GCopyCurly>"/" { *pCopyCurlyGString+=yytext; }
3035 *pCopyCurlyGString+=*yytext;
3038 *pCopyCurlyGString+=*yytext;
3041 /* ---------------------- */
3045 if (current->type.isEmpty()) // anonymous padding field, e.g. "int :7;"
3048 current->name.sprintf("__pad%d__",padCount++);
3051 current->bitfields+=":";
3054 current->bitfields+=*yytext;
3057 current->args+=*yytext;
3063 QCString oldType = current->type;
3064 if (current->bodyLine==-1)
3066 current->bodyLine = yyLineNr;
3068 if ( insidePHP && current->type.left(3) == "var" )
3070 current->type = current->type.mid(3);
3072 if (isTypedef && current->type.left(8)!="typedef ")
3074 current->type.prepend("typedef ");
3076 bool needNewCurrent=FALSE;
3077 if (!current->name.isEmpty() && current->section!=Entry::ENUM_SEC)
3079 current->type=current->type.simplifyWhiteSpace();
3080 current->args=removeRedundantWhiteSpace(current->args);
3081 current->name=current->name.stripWhiteSpace();
3082 if (current->section==Entry::CLASS_SEC) // remove spec for "struct Bla bla;"
3086 current->section = Entry::VARIABLE_SEC ;
3087 current->fileName = yyFileName;
3088 current->startLine = yyLineNr;
3089 current_root->addSubEntry( current ) ;
3090 needNewCurrent=TRUE;
3092 if ( *yytext == ',')
3094 bool stat = current->stat;
3097 current = new Entry(*current);
3100 current->stat = stat; // the static attribute holds for all variables
3101 current->name.resize(0);
3102 current->args.resize(0);
3103 current->brief.resize(0);
3104 current->doc.resize(0);
3105 current->initializer.resize(0);
3106 current->bitfields.resize(0);
3107 int i=oldType.length();
3108 while (i>0 && (oldType[i-1]=='*' || oldType[i-1]=='&' || oldType[i-1]==' ')) i--;
3109 current->type = oldType.left(i);
3115 current = new Entry ;
3117 else if (current->groups)
3119 current->groups->clear();
3127 (current->name.isEmpty() ||
3128 current->name=="typedef"
3130 ) // IDL function property
3133 lastSquareContext = YY_START;
3136 current->mtype = mtype;
3137 BEGIN( IDLAttribute );
3139 else if (insideCS &&
3140 current->name.isEmpty())
3143 lastSquareContext = YY_START;
3144 // Skip the C# attribute
3146 current->args.resize(0);
3147 BEGIN( SkipSquare );
3151 current->args += yytext ;
3157 // end of IDL function attribute
3158 if (--squareCount<=0)
3161 if (current->mtype == Property)
3162 BEGIN( IDLPropName );
3164 BEGIN( lastSquareContext );
3167 <IDLAttribute>"propput" {
3168 if (Config_getBool("IDL_PROPERTY_SUPPORT"))
3170 current->mtype = Property;
3172 current->spec |= Entry::Settable;
3174 <IDLAttribute>"propget" {
3175 if (Config_getBool("IDL_PROPERTY_SUPPORT"))
3177 current->mtype = Property;
3179 current->spec |= Entry::Gettable;
3183 <IDLPropName>{BN}*{ID}{BN}* {
3184 // return type (probably HRESULT) - skip it
3186 <IDLPropName>{ID}{BN}*"(" {
3187 current->name = yytext;
3188 current->name = current->name.left(current->name.length()-1).stripWhiteSpace();
3189 current->startLine = yyLineNr;
3192 <IDLProp>{BN}*"["[^\]]*"]"{BN}* { // attribute of a parameter
3194 idlAttr=idlAttr.stripWhiteSpace();
3196 <IDLProp>{ID} { // property type
3199 <IDLProp>{BN}*{ID}{BN}*"," { // Rare: Another parameter ([propput] HRESULT Item(int index, [in] Type theRealProperty);)
3201 current->args = "(";
3203 current->args += ", ";
3204 current->args += idlAttr;
3205 current->args += " ";
3206 current->args += idlProp; // prop was actually type of extra parameter
3207 current->args += " ";
3208 current->args += yytext;
3209 current->args = current->args.left(current->args.length() - 1); // strip comma
3214 <IDLProp>{BN}*{ID}{BN}*")"{BN}* {
3215 // the parameter name for the property - just skip.
3218 current->fileName = yyFileName;
3219 current->type = idlProp;
3220 current->args = current->args.simplifyWhiteSpace();
3222 current->args += ")";
3223 current->name = current->name.stripWhiteSpace();
3224 current->section = Entry::VARIABLE_SEC;
3225 current_root->addSubEntry(current);
3226 current = new Entry;
3228 BEGIN( FindMembers );
3230 <IDLProp>. { // spaces, *, or other stuff
3233 <Array>"]" { current->args += *yytext ;
3234 if (--squareCount<=0)
3235 BEGIN( FindMembers ) ;
3237 <FuncFuncArray>"]" { current->args += *yytext ;
3238 if (--squareCount<=0)
3241 <Array,FuncFuncArray>"[" { current->args += *yytext ;
3244 <Array,FuncFuncArray>. { current->args += *yytext ; }
3245 <SkipSquare>"[" { squareCount++; }
3247 if (--squareCount<=0)
3248 BEGIN( lastSquareContext );
3251 lastStringContext=YY_START;
3252 BEGIN( SkipString );
3254 <SkipSquare>[^\n\[\]\"]+
3255 <FindMembers>"<" { addType( current ) ;
3256 current->type += yytext ;
3259 <Sharp>">" { current->type += *yytext ;
3260 if (--sharpCount<=0)
3261 BEGIN( FindMembers ) ;
3263 <Sharp>"<" { current->type += *yytext ;
3269 <Sharp>. { current->type += *yytext ; }
3271 current->bodyLine = yyLineNr;
3272 current->name = yytext;
3275 // Java enum initializer
3277 lastInitializerContext = YY_START;
3279 current->initializer = "=";
3280 BEGIN(ReadInitializer);
3283 lastInitializerContext = YY_START;
3285 current->initializer = yytext;
3286 BEGIN(ReadInitializer);
3289 if (insideJava) // last enum field in Java class
3291 if (!current->name.isEmpty())
3293 current->fileName = yyFileName;
3294 current->startLine = yyLineNr;
3295 current->type = "@"; // enum marker
3296 current->args = current->args.simplifyWhiteSpace();
3297 current->name = current->name.stripWhiteSpace();
3298 current->section = Entry::VARIABLE_SEC;
3299 current_root->addSubEntry(current);
3300 current = new Entry ;
3304 BEGIN( FindMembers );
3314 <SkipRemainder>[^\n]*
3316 //printf("adding `%s' `%s' `%s' to enum `%s' (mGrpId=%d)\n",
3317 // current->type.data(), current->name.data(),
3318 // current->args.data(), current_root->name.data(),current->mGrpId);
3319 if (!current->name.isEmpty())
3321 current->fileName = yyFileName;
3322 current->startLine = yyLineNr;
3323 if (!(current_root->spec&Entry::Enum))
3325 current->type = "@"; // enum marker
3327 current->args = current->args.simplifyWhiteSpace();
3328 current->name = current->name.stripWhiteSpace();
3329 current->section = Entry::VARIABLE_SEC;
3330 // add to the scope of the enum
3331 current_root->addSubEntry(current);
3332 if (!insideCS && !insideJava &&
3333 !(current_root->spec&Entry::Strong))
3334 // for C# and Java 1.5+ enum values always have to be explicitly qualified,
3335 // same for C++11 style enums (enum class Name {})
3337 current = new Entry(*current);
3338 // add to the scope surrounding the enum (copy!)
3339 current_root->parent()->addSubEntry(current);
3341 current = new Entry ;
3344 else // probably a redundant ,
3350 <FindFields>"[" { // attribute list in IDL
3352 lastSquareContext = YY_START;
3356 <FindFieldArg>"," { unput(*yytext); BEGIN(FindFields); }
3358 <ReadBody,ReadNSBody,ReadBodyIntf>[^\r\n\#{}"@'/<]* { current->program += yytext ; }
3359 <ReadBody,ReadNSBody,ReadBodyIntf>"//".* { current->program += yytext ; }
3360 <ReadBody,ReadNSBody,ReadBodyIntf>"#".* { if (!insidePHP)
3362 // append PHP comment.
3363 current->program += yytext ;
3365 <ReadBody,ReadNSBody,ReadBodyIntf>@\" { current->program += yytext ;
3366 pSkipVerbString = ¤t->program;
3367 lastSkipVerbStringContext=YY_START;
3368 BEGIN( SkipVerbString );
3370 <ReadBody,ReadNSBody,ReadBodyIntf>"<<<" { if (insidePHP)
3372 current->program += yytext ;
3373 pCopyHereDocGString = ¤t->program;
3374 lastHereDocContext=YY_START;
3375 BEGIN( CopyHereDoc );
3382 <ReadBody,ReadNSBody,ReadBodyIntf>\" { current->program += yytext ;
3383 pCopyQuotedGString = ¤t->program;
3384 lastStringContext=YY_START;
3385 BEGIN( CopyGString );
3387 <ReadBody,ReadNSBody,ReadBodyIntf>"/*"{B}* { current->program += yytext ;
3388 lastContext = YY_START ;
3391 <ReadBody,ReadNSBody,ReadBodyIntf>"/*"{BL} { current->program += yytext ;
3393 lastContext = YY_START ;
3396 <ReadBody,ReadNSBody,ReadBodyIntf>"'" {
3399 current->program += yytext;
3402 { // begin of single quoted string
3403 current->program += yytext;
3404 pCopyQuotedGString = ¤t->program;
3405 lastStringContext=YY_START;
3406 BEGIN(CopyPHPGString);
3409 <ReadBody,ReadNSBody,ReadBodyIntf>{CHARLIT} {
3412 REJECT; // for PHP code single quotes
3413 // are used for strings of arbitrary length
3417 current->program += yytext;
3420 <ReadBody,ReadNSBody,ReadBodyIntf>"{" { current->program += yytext ;
3424 current->program += yytext ;
3427 <ReadBody,ReadNSBody>"}" { //err("ReadBody count=%d\n",curlyCount);
3430 current->program += yytext ;
3435 current->endBodyLine = yyLineNr;
3436 QCString &cn = current->name;
3437 QCString rn = current_root->name.copy();
3438 //printf("cn=`%s' rn=`%s' isTypedef=%d\n",cn.data(),rn.data(),isTypedef);
3439 if (!cn.isEmpty() && !rn.isEmpty())
3443 if (isTypedef && cn.isEmpty())
3445 //printf("Typedef Name\n");
3446 BEGIN( TypedefName );
3450 if ((current->section == Entry::ENUM_SEC) || (current->spec&Entry::Enum))
3452 current->program+=','; // add field terminator
3454 // add compound definition to the tree
3455 current->args=removeRedundantWhiteSpace(current->args);
3456 // was: current->args.simplifyWhiteSpace();
3457 current->type = current->type.simplifyWhiteSpace();
3458 current->name = current->name.stripWhiteSpace();
3459 //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);
3461 ((current->spec&Entry::Interface) || (current->spec==Entry::Category))
3462 ) // method definition follows
3464 BEGIN( ReadBodyIntf ) ;
3468 current_root->addSubEntry( current ) ;
3469 memspecEntry = current;
3470 current = new Entry(*current);
3471 if (current->section==Entry::NAMESPACE_SEC ||
3472 (current->spec==Entry::Interface) ||
3473 insideJava || insidePHP || insideCS || insideD || insideJS
3475 { // namespaces and interfaces and java classes ends with a closing bracket without semicolon
3479 BEGIN( FindMembers ) ;
3483 if (!isTypedef) // not typedef
3485 // enabled the next two lines for bug 623424
3486 current->doc.resize(0);
3487 current->brief.resize(0);
3489 BEGIN( MemberSpec ) ;
3495 <ReadBody>"}"{BN}+"typedef"{BN}+ { //err("ReadBody count=%d\n",curlyCount);
3499 current->program += yytext ;
3505 current->endBodyLine = yyLineNr;
3506 QCString &cn = current->name;
3507 QCString rn = current_root->name.copy();
3508 if (!cn.isEmpty() && !rn.isEmpty())
3512 BEGIN( TypedefName );
3515 <TypedefName>("const"|"volatile"){BN} { // late "const" or "volatile" keyword
3517 current->type.prepend(yytext);
3520 if ((current->section == Entry::ENUM_SEC) || (current->spec&Entry::Enum))
3522 current->program+=","; // add field terminator
3524 current->name=yytext;
3526 current->args = current->args.simplifyWhiteSpace();
3527 current->type = current->type.simplifyWhiteSpace();
3528 //printf("Adding compound %s %s %s\n",current->type.data(),current->name.data(),current->args.data());
3529 current_root->addSubEntry( current ) ;
3530 if (!firstTypedefEntry)
3532 firstTypedefEntry = current;
3534 current = new Entry;
3536 isTypedef=TRUE; // to undo reset by initEntry()
3537 BEGIN(MemberSpecSkip);
3539 <TypedefName>";" { /* typedef of anonymous type */
3540 current->name.sprintf("@%d",anonCount++);
3541 if ((current->section == Entry::ENUM_SEC) || (current->spec&Entry::Enum))
3543 current->program+=','; // add field terminator
3545 // add compound definition to the tree
3546 current->args = current->args.simplifyWhiteSpace();
3547 current->type = current->type.simplifyWhiteSpace();
3548 current_root->addSubEntry( current ) ;
3549 memspecEntry = current;
3550 current = new Entry(*current);
3553 BEGIN( MemberSpec ) ;
3555 <MemberSpec>([*&]*{BN}*)*{ID}{BN}*("["[^\]\n]*"]")* { // the [] part could be improved.
3558 while (i<l && (!isId(yytext[i]))) i++;
3559 msName = QCString(yytext).right(l-i).stripWhiteSpace();
3563 msArgs=msName.right(msName.length()-j);
3564 msName=msName.left(j);
3566 msType=QCString(yytext).left(i);
3568 // handle *pName in: typedef { ... } name, *pName;
3569 if (firstTypedefEntry)
3571 if (firstTypedefEntry->spec&Entry::Struct)
3573 msType.prepend("struct "+firstTypedefEntry->name);
3575 else if (firstTypedefEntry->spec&Entry::Union)
3577 msType.prepend("union "+firstTypedefEntry->name);
3579 else if (firstTypedefEntry->section==Entry::ENUM_SEC)
3581 msType.prepend("enum "+firstTypedefEntry->name);
3585 msType.prepend(firstTypedefEntry->name);
3589 <MemberSpec>"(" { // function with struct return type
3591 current->name = msName;
3597 if (msName.isEmpty() && !current->name.isEmpty())
3599 // see if the compound does not have a name or is inside another
3600 // anonymous compound. If so we insert a
3601 // special `anonymous' variable.
3602 //Entry *p=current_root;
3606 // only look for class scopes, not namespace scopes
3607 if ((p->section & Entry::COMPOUND_MASK) && !p->name.isEmpty())
3609 //printf("Trying scope `%s'\n",p->name.data());
3610 int i=p->name.findRev("::");
3611 int pi = (i==-1) ? 0 : i+2;
3612 if (p->name.at(pi)=='@')
3614 // anonymous compound inside -> insert dummy variable name
3615 //printf("Adding anonymous variable for scope %s\n",p->name.data());
3616 msName.sprintf("@%d",anonCount++);
3621 if (p==current) p=current_root; else p=p->parent();
3624 //printf("msName=%s current->name=%s\n",msName.data(),current->name.data());
3625 if (!msName.isEmpty()
3626 /*&& msName!=current->name*/) // skip typedef T {} T;, removed due to bug608493
3628 static bool typedefHidesStruct = Config_getBool("TYPEDEF_HIDES_STRUCT");
3629 // case 1: typedef struct _S { ... } S_t;
3630 // -> omit typedef and use S_t as the struct name
3631 if (typedefHidesStruct &&
3633 ((current->spec&(Entry::Struct|Entry::Union)) ||
3634 current->section==Entry::ENUM_SEC )&&
3635 msType.stripWhiteSpace().isEmpty() &&
3638 memspecEntry->name=msName;
3640 else // case 2: create a typedef field
3642 Entry *varEntry=new Entry;
3643 varEntry->lang = language;
3644 varEntry->protection = current->protection ;
3645 varEntry->mtype = current->mtype;
3646 varEntry->virt = current->virt;
3647 varEntry->stat = current->stat;
3648 varEntry->section = Entry::VARIABLE_SEC;
3649 varEntry->name = msName.stripWhiteSpace();
3650 varEntry->type = current->type.simplifyWhiteSpace()+" ";
3651 varEntry->args = msArgs;
3654 varEntry->type.prepend("typedef ");
3655 // //printf("current->name = %s %s\n",current->name.data(),msName.data());
3657 if (typedefHidesStruct &&
3659 (current->spec&(Entry::Struct|Entry::Union)) &&
3661 ) // case 1: use S_t as type for pS_t in "typedef struct _S {} S_t, *pS_t;"
3663 varEntry->type+=memspecEntry->name+msType;
3665 else // case 2: use _S as type for for pS_t
3667 varEntry->type+=current->name+msType;
3669 varEntry->fileName = yyFileName;
3670 varEntry->startLine = yyLineNr;
3671 varEntry->doc = current->doc.copy();
3672 varEntry->brief = current->brief.copy();
3673 varEntry->mGrpId = current->mGrpId;
3674 varEntry->initializer = current->initializer;
3676 // deep copy group list
3677 QListIterator<Grouping> gli(*current->groups);
3679 for (;(g=gli.current());++gli)
3681 varEntry->groups->append(new Grouping(*g));
3683 if (current->sli) // copy special list items
3685 QListIterator<ListItemInfo> li(*current->sli);
3687 for (li.toFirst();(lii=li.current());++li)
3689 varEntry->addSpecialListItem(lii->type,lii->itemId);
3693 //printf("Add: type=`%s',name=`%s',args=`%s' brief=%s doc=%s\n",
3694 // varEntry->type.data(),varEntry->name.data(),
3695 // varEntry->args.data(),varEntry->brief.data(),varEntry->doc.data());
3696 current_root->addSubEntry(varEntry);
3699 if (*yytext==';') // end of a struct/class ...
3701 if (!isTypedef && msName.isEmpty() && memspecEntry && (current->section&Entry::COMPOUND_MASK))
3702 { // case where a class/struct has a doc block after it
3703 if (!current->doc.isEmpty())
3705 memspecEntry->doc += current->doc;
3707 if (!current->brief.isEmpty())
3709 memspecEntry->brief += current->brief;
3716 firstTypedefEntry=0;
3720 BEGIN( FindMembers );
3724 current->doc.resize(0);
3725 current->brief.resize(0);
3730 lastInitializerContext=YY_START;
3732 current->initializer = yytext;
3733 BEGIN(ReadInitializer);
3734 /* BEGIN(MemberSpecSkip); */
3737 <MemberSpecSkip>"{" {
3739 lastCurlyContext = MemberSpecSkip;
3744 <MemberSpecSkip>"," { BEGIN(MemberSpec); }
3745 <MemberSpecSkip>";" { unput(';'); BEGIN(MemberSpec); }
3746 <ReadBody,ReadNSBody,ReadBodyIntf>{BN}{1,80} { current->program += yytext ;
3749 <ReadBodyIntf>"@end"/[^a-z_A-Z0-9] { // end of Objective C block
3750 current_root->addSubEntry( current ) ;
3754 BEGIN( FindMembers );
3756 <ReadBody,ReadNSBody,ReadBodyIntf>. { current->program += yytext ; }
3758 <FindMembers>"("/{BN}*"::"*{BN}*({TSCOPE}{BN}*"::")*{TSCOPE}{BN}*")"{BN}*"(" | /* typedef void (A<int>::func_t)(args...) */
3759 <FindMembers>("("({BN}*"::"*{BN}*{TSCOPE}{BN}*"::")*({BN}*[*&\^]{BN}*)+)+ { /* typedef void (A::*ptr_t)(args...) or int (*func(int))[], the ^ is for Obj-C blocks */
3760 if (insidePHP) // reference parameter
3766 current->bodyLine = yyLineNr;
3771 //current->type += yytext;
3775 <FuncPtr>{SCOPENAME} {
3776 current->name = yytext;
3777 if (nameIsOperator(current->name))
3779 BEGIN( FuncPtrOperator );
3783 if (current->name=="const" || current->name=="volatile")
3785 funcPtrType += current->name;
3789 BEGIN( EndFuncPtr );
3794 //printf("error: FuncPtr `%c' unexpected at line %d of %s\n",*yytext,yyLineNr,yyFileName);
3796 <FuncPtrOperator>"("{BN}*")"{BN}*/"(" {
3797 current->name += yytext;
3798 current->name = current->name.simplifyWhiteSpace();
3801 <FuncPtrOperator>\n {
3803 current->name += *yytext;
3805 <FuncPtrOperator>"(" {
3807 BEGIN( EndFuncPtr );
3809 <FuncPtrOperator>. {
3810 current->name += *yytext;
3812 <EndFuncPtr>")"{BN}*/";" { // a variable with extra braces
3814 current->type+=funcPtrType.data()+1;
3817 <EndFuncPtr>")"{BN}*/"(" { // a function pointer
3819 current->type+=funcPtrType+")";
3822 <EndFuncPtr>")"{BN}*/"[" { // an array of variables
3824 current->type+=funcPtrType.data();
3825 current->args += ")";
3828 <EndFuncPtr>"(" { // a function returning a function or
3829 // a function returning a pointer to an array
3830 current->args += *yytext ;
3832 //BEGIN( FuncFunc );
3833 current->bodyLine = yyLineNr;
3834 currentArgumentContext = FuncFuncEnd;
3835 fullArgString=current->args.copy();
3836 copyArgString=¤t->args;
3837 BEGIN( ReadFuncArgType ) ;
3839 <EndFuncPtr>"["[^\n\]]*"]" {
3840 funcPtrType+=yytext;
3846 current->args += *yytext ;
3850 current->args += *yytext ;
3858 <FuncFuncEnd>")"{BN}*"(" {
3860 current->type+=funcPtrType+")(";
3861 BEGIN(FuncFuncType);
3863 <FuncFuncEnd>")"{BN}*/[;{] {
3865 current->type+=funcPtrType.data()+1;
3868 <FuncFuncEnd>")"{BN}*/"[" { // function returning a pointer to an array
3870 current->type+=funcPtrType;
3872 BEGIN(FuncFuncArray);
3875 current->args += *yytext;
3878 current->type += *yytext;
3882 current->type += *yytext;
3888 <FuncFuncType>{BN}*","{BN}* { lineCount() ; current->type += ", " ; }
3889 <FuncFuncType>{BN}+ { lineCount() ; current->type += ' ' ; }
3891 current->type += *yytext;
3893 <FindMembers>"("/{BN}*{ID}{BN}*"*"{BN}*{ID}*")(" { // for catching typedef void (__stdcall *f)() like definitions
3894 if (current->type.left(7)=="typedef" && current->bodyLine==-1)
3895 // the bodyLine check is to prevent this guard to be true more than once
3897 current->bodyLine = yyLineNr;
3898 BEGIN( GetCallType );
3900 else if (!current->name.isEmpty()) // normal function
3902 current->args = yytext;
3903 current->bodyLine = yyLineNr;
3904 currentArgumentContext = FuncQual;
3905 fullArgString=current->args.copy();
3906 copyArgString=¤t->args;
3907 BEGIN( ReadFuncArgType ) ;
3908 //printf(">>> Read function arguments!\n");
3911 <GetCallType>{BN}*{ID}{BN}*"*" {
3915 funcPtrType+=yytext;
3920 if (!current->name.isEmpty())
3922 current->args = yytext;
3923 current->bodyLine = yyLineNr;
3924 currentArgumentContext = FuncQual;
3925 fullArgString=current->args.copy();
3926 copyArgString=¤t->args;
3927 BEGIN( ReadFuncArgType ) ;
3928 //printf(">>> Read function arguments current->argList->count()=%d\n",current->argList->count());
3932 <FindMembers>"("{BN}*("void"{BN}*)?")" {
3934 current->args = "()";
3939 /*- Function argument reading rules ---------------------------------------*/
3941 <ReadFuncArgType>[^ \/\r\t\n\)\(\"\'#]+ { *copyArgString+=yytext;
3942 fullArgString+=yytext;
3944 <CopyArgString,CopyArgPHPString>[^\n\\\"\']+ { *copyArgString+=yytext;
3945 fullArgString+=yytext;
3947 <CopyArgRound>[^\/\n\)\(\"\']+ {
3948 *copyArgString+=yytext;
3949 fullArgString+=yytext;
3951 <ReadFuncArgType,ReadTempArgs>{BN}* {
3952 *copyArgString+=" ";
3956 <ReadFuncArgType,CopyArgRound,CopyArgSharp,ReadTempArgs>{RAWBEGIN} {
3957 g_delimiter = yytext+2;
3958 g_delimiter=g_delimiter.left(g_delimiter.length()-1);
3959 lastRawStringContext = YY_START;
3960 pCopyRawString = copyArgString;
3961 *pCopyRawString+=yytext;
3962 fullArgString+=yytext;
3965 <ReadFuncArgType,CopyArgRound,CopyArgSharp,ReadTempArgs>\" {
3966 *copyArgString+=*yytext;
3967 fullArgString+=*yytext;
3968 lastCopyArgStringContext = YY_START;
3969 BEGIN( CopyArgString );
3971 <ReadFuncArgType,ReadTempArgs>"(" {
3972 *copyArgString+=*yytext;
3973 fullArgString+=*yytext;
3975 lastCopyArgContext = YY_START;
3976 BEGIN( CopyArgRound );
3978 <ReadFuncArgType>")" {
3979 *copyArgString+=*yytext;
3980 fullArgString+=*yytext;
3981 stringToArgumentList(fullArgString,current->argList);
3984 fixArgumentListForJavaScript(current->argList);
3986 handleParametersCommentBlocks(current->argList);
3988 /* remember the current documentation block, since
3989 we could overwrite it with the documentation of
3990 a function argument, which we then have to correct later
3993 docBackup = current->doc;
3994 briefBackup = current->brief;
3996 BEGIN( currentArgumentContext );
3998 /* a special comment */
3999 <ReadFuncArgType,ReadTempArgs>("/*"[*!]|"//"[/!])("<"?) {
4000 if (currentArgumentContext==DefineEnd)
4002 // for defines we interpret a comment
4003 // as documentation for the define
4004 int i;for (i=yyleng-1;i>=0;i--)
4008 stringToArgumentList(fullArgString,current->argList);
4009 handleParametersCommentBlocks(current->argList);
4010 BEGIN( currentArgumentContext );
4012 else // not a define
4014 // for functions we interpret a comment
4015 // as documentation for the argument
4016 fullArgString+=yytext;
4018 lastCommentInArgContext=YY_START;
4020 BEGIN( CopyArgCommentLine );
4022 BEGIN( CopyArgComment );
4025 /* a non-special comment */
4026 <ReadFuncArgType,ReadTempArgs>"/**/" { /* empty comment */ }
4027 <ReadFuncArgType,ReadTempArgs>"/*" {
4028 lastCContext = YY_START;
4029 BEGIN( SkipComment );
4031 <ReadFuncArgType,ReadTempArgs>"//" {
4032 lastCContext = YY_START;
4033 BEGIN( SkipCxxComment );
4036 <ReadFuncArgType,ReadTempArgs>"'#" { if (insidePHP)
4038 *copyArgString+=yytext;
4039 fullArgString+=yytext;
4041 <ReadFuncArgType,ReadTempArgs>"#" {
4044 lastCContext = YY_START;
4045 BEGIN( SkipCxxComment );
4048 /* `)' followed by a special comment */
4049 <ReadFuncArgType>")"{BN}*("/*"[*!]|"//"[/!])"<" {
4051 if (currentArgumentContext==DefineEnd)
4053 // for defines we interpret a comment
4054 // as documentation for the define
4055 int i;for (i=yyleng-1;i>0;i--)
4059 *copyArgString+=*yytext;
4060 fullArgString+=*yytext;
4061 stringToArgumentList(fullArgString,current->argList);
4062 handleParametersCommentBlocks(current->argList);
4063 BEGIN( currentArgumentContext );
4067 // for functions we interpret a comment
4068 // as documentation for the last argument
4069 lastCopyArgChar=*yytext;
4070 QCString text=&yytext[1];
4071 text=text.stripWhiteSpace();
4072 lastCommentInArgContext=YY_START;
4073 fullArgString+=text;
4074 if (text.find("//")!=-1)
4075 BEGIN( CopyArgCommentLine );
4077 BEGIN( CopyArgComment );
4080 <CopyArgComment>^{B}*"*"+/{BN}+
4081 <CopyArgComment>[^\n\\\@\*]+ { fullArgString+=yytext; }
4082 <CopyArgComment>"*/" { fullArgString+=yytext;
4083 if (lastCopyArgChar!=0)
4084 unput(lastCopyArgChar);
4085 BEGIN( lastCommentInArgContext );
4087 <CopyArgCommentLine>\n { fullArgString+=yytext;
4089 if (lastCopyArgChar!=0)
4090 unput(lastCopyArgChar);
4091 BEGIN( lastCommentInArgContext );
4093 <CopyArgCommentLine>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9] { // verbatim command (which could contain nested comments!)
4094 docBlockName=&yytext[1];
4095 fullArgString+=yytext;
4096 BEGIN(CopyArgVerbatim);
4098 <CopyArgCommentLine>{CMD}("f$"|"f["|"f{") {
4099 docBlockName=&yytext[1];
4100 if (docBlockName.at(1)=='[')
4102 docBlockName.at(1)='}';
4104 if (docBlockName.at(1)=='{')
4106 docBlockName.at(1)='}';
4108 fullArgString+=yytext;
4109 BEGIN(CopyArgVerbatim);
4111 <CopyArgVerbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"endmanonly"|"enddot"|"endcode"|"f$"|"f]"|"f}")/[^a-z_A-Z0-9] { // end of verbatim block
4112 fullArgString+=yytext;
4113 if (yytext[1]=='f') // end of formula
4115 BEGIN(CopyArgCommentLine);
4117 if (&yytext[4]==docBlockName)
4119 BEGIN(CopyArgCommentLine);
4122 <CopyArgCommentLine>[^\\\@\n]+ { fullArgString+=yytext; }
4123 <CopyArgCommentLine>. { fullArgString+=*yytext; }
4124 <CopyArgComment,CopyArgVerbatim>\n { fullArgString+=*yytext; lineCount(); }
4125 <CopyArgComment,CopyArgVerbatim>. { fullArgString+=*yytext; }
4126 <CopyArgComment>{CMD}("brief"|"short"){B}+ {
4127 warn(yyFileName,yyLineNr,
4128 "warning: Ignoring %cbrief command inside argument documentation",*yytext
4133 *copyArgString+=*yytext;
4134 fullArgString+=*yytext;
4136 BEGIN( CopyArgSharp );
4139 *copyArgString+=*yytext;
4140 fullArgString+=*yytext;
4141 //printf("end template list %s\n",copyArgString->data());
4142 stringToArgumentList(fullArgString,currentArgumentList);
4143 BEGIN( currentArgumentContext );
4147 *copyArgString+=*yytext;
4148 fullArgString+=*yytext;
4151 *copyArgString+=*yytext;
4152 fullArgString+=*yytext;
4153 if (argRoundCount>0)
4156 BEGIN( lastCopyArgContext );
4160 //printf("argSharpCount++=%d copy\n",argSharpCount);
4161 *copyArgString+=*yytext;
4162 fullArgString+=*yytext;
4165 *copyArgString+=*yytext;
4166 fullArgString+=*yytext;
4168 if (argSharpCount>0)
4170 //printf("argSharpCount--=%d copy\n",argSharpCount);
4174 BEGIN( ReadTempArgs );
4175 //printf("end of argSharpCount\n");
4178 <CopyArgString,CopyArgPHPString>\\. {
4179 *copyArgString+=yytext;
4180 fullArgString+=yytext;
4183 *copyArgString+=*yytext;
4184 fullArgString+=*yytext;
4185 BEGIN( lastCopyArgStringContext );
4187 <CopyArgPHPString>\' {
4188 *copyArgString+=*yytext;
4189 fullArgString+=*yytext;
4190 BEGIN( lastCopyArgStringContext );
4192 <ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>{CHARLIT} {
4199 *copyArgString+=yytext;
4200 fullArgString+=yytext;
4203 <ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>\' {
4204 *copyArgString+=yytext;
4205 fullArgString+=yytext;
4208 lastCopyArgStringContext=YY_START;
4209 BEGIN(CopyArgPHPString);
4212 <ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgPHPString,CopyArgRound,CopyArgSharp>\n {
4214 *copyArgString+=*yytext;
4215 fullArgString+=*yytext;
4217 <ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgPHPString,CopyArgRound,CopyArgSharp>. {
4218 *copyArgString+=*yytext;
4219 fullArgString+=*yytext;
4224 /*------------------------------------------------------------------------*/
4227 <FuncRound>"(" { current->args += *yytext ;
4230 <FuncRound>")" { current->args += *yytext ;
4237 <FuncQual>"#" { if (insidePHP)
4239 lastCPPContext = YY_START;
4244 if ( strcmp(yytext,";")==0 &&
4246 !containsWord(current->type,"function") )
4250 BEGIN( FindMembers );
4254 unput(*yytext); BEGIN( Function );
4257 <FuncQual>{BN}*"abstract"{BN}* { // pure virtual member function
4259 current->virt = Pure;
4260 current->args += " override ";
4262 <FuncQual,TrailingReturn>{BN}*"override"{BN}* { // C++11 overridden virtual member function
4264 current->spec |= Entry::Override;
4265 current->args += " override ";
4268 <FuncQual,TrailingReturn>{BN}*"final"{BN}* { // C++11 final method
4270 current->spec |= Entry::Final;
4271 current->args += " final ";
4274 <FuncQual>{BN}*"sealed"{BN}* { // sealed member function
4276 current->spec |= Entry::Sealed;
4277 current->args += " sealed ";
4279 <FuncQual>{BN}*"new"{BN}* { // new member function
4281 current->spec |= Entry::New;
4282 current->args += " new ";
4284 <FuncQual>{BN}*"const"{BN}* { // const member function
4286 current->args += " const ";
4287 current->argList->constSpecifier=TRUE;
4289 <FuncQual>{BN}*"volatile"{BN}* { // volatile member function
4291 current->args += " volatile ";
4292 current->argList->volatileSpecifier=TRUE;
4294 <FuncQual>{BN}*"noexcept"{BN}* { // volatile member function
4296 current->args += " noexcept ";
4297 current->spec |= Entry::NoExcept;
4299 <FuncQual,TrailingReturn>{BN}*"="{BN}*"0"{BN}* { // pure virtual member function
4301 current->args += " = 0";
4302 current->virt = Pure;
4303 current->argList->pureSpecifier=TRUE;
4306 <FuncQual,TrailingReturn>{BN}*"="{BN}*"delete"{BN}* { // C++11 explicitly delete member
4308 current->args += " = delete";
4309 current->spec |= Entry::Delete;
4312 <FuncQual,TrailingReturn>{BN}*"="{BN}*"default"{BN}* { // C++11 explicitly defaulted constructor/assignment operator
4314 current->args += " = default";
4315 current->spec |= Entry::Default;
4318 <FuncQual>{BN}*"->"{BN}* {
4320 current->argList->trailingReturnType = " -> ";
4321 current->args += " -> ";
4322 BEGIN(TrailingReturn);
4324 <TrailingReturn>[{;] {
4329 current->argList->trailingReturnType+=yytext;
4330 current->args+=yytext;
4332 <TrailingReturn>\n {
4334 current->argList->trailingReturnType+=yytext;
4337 <FuncRound,FuncFunc>{BN}*","{BN}* {
4339 current->args += ", " ;
4341 <FuncQual,FuncRound,FuncFunc>{BN}+ {
4343 current->args += ' ' ;
4345 <Function,FuncQual,FuncRound,FuncFunc>"#" { if (insidePHP)
4347 lastCPPContext = YY_START;
4352 (current_root->section&Entry::COMPOUND_MASK)
4359 // typically an initialized function pointer
4360 lastInitializerContext=YY_START;
4362 current->initializer = yytext;
4363 BEGIN(ReadInitializer);
4382 current->args += *yytext;
4383 pCopyQuotedString=¤t->args;
4384 lastStringContext=FuncPtrInit;
4388 current->args += *yytext;
4391 pCopyQuotedString=¤t->args;
4392 lastStringContext=FuncPtrInit;
4393 BEGIN(CopyPHPString);
4396 <FuncPtrInit>{CHARLIT} {
4403 current->args += yytext;
4407 current->args += yytext;
4410 current->args += *yytext;
4413 current->args += *yytext;
4416 <FuncQual>{ID} { // typically a K&R style C function
4417 if (insideCS && strcmp(yytext,"where")==0)
4419 // type contraint for a method
4420 delete current->typeConstr;
4421 current->typeConstr = new ArgumentList;
4422 current->typeConstr->append(new Argument);
4423 lastCSConstraint = YY_START;
4424 BEGIN( CSConstraintName );
4426 else if (checkForKnRstyleC())
4428 //fprintf(stderr,"===> got a K&R style function\n");
4429 current->args = yytext;
4430 oldStyleArgType.resize(0);
4431 BEGIN(OldStyleArgs);
4435 current->args += yytext;
4438 <OldStyleArgs>[,;] {
4439 QCString oldStyleArgPtr;
4440 QCString oldStyleArgName;
4441 splitKnRArg(oldStyleArgPtr,oldStyleArgName);
4443 if (current->doc!=docBackup)
4445 doc=current->doc.copy();
4446 current->doc=docBackup;
4448 if (current->brief!=briefBackup)
4450 brief=current->brief.copy();
4451 current->brief=briefBackup;
4453 addKnRArgInfo(oldStyleArgType+oldStyleArgPtr,
4454 oldStyleArgName,brief,doc);
4455 current->args.resize(0);
4456 if (*yytext==';') oldStyleArgType.resize(0);
4458 <OldStyleArgs>{ID} { current->args += yytext; }
4460 current->args = argListToString(current->argList);
4464 <OldStyleArgs>. { current->args += *yytext; }
4465 <FuncQual,FuncRound,FuncFunc>. { current->args += *yytext; }
4466 <FuncQual>{BN}*"try:" |
4467 <FuncQual>{BN}*"try"{BN}+ { /* try-function-block */
4468 insideTryBlock=TRUE;
4470 if (yytext[yyleng-1]==':')
4476 <FuncQual>{BN}*"throw"{BN}*"(" { // C++ style throw clause
4477 current->exception = " throw (" ;
4480 BEGIN( ExcpRound ) ;
4482 <FuncQual>{BN}*"raises"{BN}*"(" {
4483 current->exception = " raises (" ;
4486 BEGIN( ExcpRound ) ;
4488 <FuncQual>{BN}*"throws"{BN}+ { // Java style throw clause
4489 current->exception = " throws " ;
4493 <ExcpRound>"(" { current->exception += *yytext ;
4496 <ExcpRound>")" { current->exception += *yytext ;
4503 current->exception += *yytext;
4506 unput('{'); BEGIN( FuncQual );
4509 unput(';'); BEGIN( FuncQual );
4512 current->exception += ' ';
4516 current->exception += *yytext;
4518 <Function>"(" { current->type += current->name ;
4519 current->name = current->args ;
4520 current->args = yytext ;
4522 BEGIN( FuncRound ) ;
4525 if (!insidePHP) BEGIN(SkipInits);
4528 current->name=current->name.simplifyWhiteSpace();
4529 current->type=current->type.simplifyWhiteSpace();
4530 current->args=removeRedundantWhiteSpace(current->args);
4531 // was: current->args.simplifyWhiteSpace();
4532 current->fileName = yyFileName;
4533 current->startLine = yyLineNr;
4534 static QRegExp re("([^)]*[*&][^)]*)"); // (...*...)
4535 if (*yytext!=';' || (current_root->section&Entry::COMPOUND_MASK) )
4537 int tempArg=current->name.find('<');
4538 int ts=current->type.find('<');
4539 int te=current->type.findRev('>');
4540 int ti=current->type.find(re,0);
4542 // bug677315: A<int(void *, char *)> get(); is not a function pointer
4543 bool isFunction = ti==-1 || // not a (...*...) pattern
4544 (ts!=-1 && ts<te && ts<ti && ti<te); // (...*...) is part of a template argument list
4546 //printf("type=%s ts=%d te=%d ti=%d isFunction=%d\n",
4547 // current->type.data(),ts,te,ti,isFunction);
4549 if (tempArg==-1) tempName=current->name; else tempName=current->name.left(tempArg);
4550 if (!current->type.isEmpty() &&
4551 (!isFunction || current->type.left(8)=="typedef "))
4553 //printf("Scanner.l: found in class variable: `%s' `%s' `%s'\n", current->type.data(),current->name.data(),current->args.data());
4554 if (isTypedef && current->type.left(8)!="typedef ")
4556 current->type.prepend("typedef ");
4558 current->section = Entry::VARIABLE_SEC ;
4562 //printf("Scanner.l: found in class function: `%s' `%s' `%s'\n", current->type.data(),current->name.data(),current->args.data());
4563 current->section = Entry::FUNCTION_SEC ;
4564 current->proto = *yytext==';';
4567 else // a global function prototype or function variable
4569 //printf("Scanner.l: prototype? type=`%s' name=`%s' args=`%s'\n",current->type.data(),current->name.data(),current->args.data());
4570 if (!current->type.isEmpty() &&
4571 (current->type.find(re,0)!=-1 || current->type.left(8)=="typedef "))
4573 if (isTypedef && current->type.left(8)!="typedef ")
4575 current->type.prepend("typedef ");
4577 //printf("Scanner.l: found function variable!\n");
4578 current->section = Entry::VARIABLE_SEC;
4582 //printf("Scanner.l: found prototype\n");
4583 current->section = Entry::FUNCTION_SEC;
4584 current->proto = TRUE;
4587 //printf("Adding entry `%s'\n",current->name.data());
4590 if (findAndRemoveWord(current->type,"final"))
4592 current->spec |= Entry::Final;
4594 if (findAndRemoveWord(current->type,"abstract"))
4596 current->spec |= Entry::Abstract;
4599 if ( insidePHP && !containsWord(current->type,"function"))
4602 if ( *yytext == '{' )
4604 lastCurlyContext = FindMembers;
4610 BEGIN( FindMembers );
4617 findAndRemoveWord(current->type,"function");
4620 current_root->addSubEntry(current);
4621 current = new Entry ;
4623 // Objective C 2.0: Required/Optional section
4624 if (previous->spec & (Entry::Optional | Entry::Required))
4626 current->spec |= previous->spec & (Entry::Optional|Entry::Required);
4628 lastCurlyContext = FindMembers;
4629 if ( *yytext == ',' )
4631 current->type = previous->type;
4632 // we need to strip any trailing * and & (see bugs 623023 and 649103 for test cases)
4633 int i=current->type.length();
4634 while (i>0 && (current->type[i-1]=='*' || current->type[i-1]=='&' || current->type[i-1]==' ')) i--;
4635 current->type = current->type.left(i);
4637 if ( *yytext == '{' )
4639 if ( !insidePHP && (current_root->section & Entry::COMPOUND_MASK) )
4641 previous->spec |= Entry::Inline;
4643 //addToBody(yytext);
4645 BEGIN( SkipCurly ) ;
4649 if (previous->section!=Entry::VARIABLE_SEC)
4650 previous->bodyLine=-1; // a function/member declaration
4651 BEGIN( FindMembers ) ;
4655 <SkipInits>"{" { // C++11 style initializer
4656 //addToBody(yytext);
4657 //lastCurlyContext = FindMembers;
4659 //BEGIN( SkipCurly ) ;
4664 //addToBody(yytext);
4668 //addToBody(yytext);
4676 if (!Config_getBool("HIDE_IN_BODY_DOCS") &&
4677 !current->doc.isEmpty())
4679 // copy documentation found inside the body
4680 // to the previous item
4681 if (previous->inbodyLine==-1)
4683 previous->inbodyLine = current->docLine;
4684 previous->inbodyFile = current->docFile;
4686 //printf("*** inbodyDocs+=%s\n",current->doc.data());
4687 previous->inbodyDocs += current->doc;
4688 current->doc.resize(0);
4691 if (current->sli && previous) // copy special list items
4693 QListIterator<ListItemInfo> li(*current->sli);
4695 for (li.toFirst();(lii=li.current());++li)
4697 previous->addSpecialListItem(lii->type,lii->itemId);
4699 delete current->sli;
4702 if (previous) previous->endBodyLine=yyLineNr;
4703 BEGIN( lastCurlyContext ) ;
4706 <SkipCurly>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" {
4710 //addToBody(yytext);
4715 current->endBodyLine=yyLineNr;
4717 tempEntry = current; // temporarily switch to the previous entry
4720 docBlockContext = SkipCurlyEndDoc;
4721 docBlockInBody = FALSE;
4722 docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF") ) ||
4723 ( yytext[yyleng-2]=='!' && Config_getBool("QT_AUTOBRIEF") );
4726 if (yytext[yyleng-3]=='/')
4728 startCommentBlock(TRUE);
4733 startCommentBlock(FALSE);
4738 <SkipCurlyEndDoc>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { // desc is followed by another one
4739 docBlockContext = SkipCurlyEndDoc;
4740 docBlockInBody = FALSE;
4741 docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool("JAVADOC_AUTOBRIEF") ) ||
4742 ( yytext[yyleng-2]=='!' && Config_getBool("QT_AUTOBRIEF") );
4745 if (yytext[yyleng-3]=='/')
4747 startCommentBlock(TRUE);
4752 startCommentBlock(FALSE);
4756 <SkipCurlyEndDoc>"}" {
4758 current = tempEntry;
4759 BEGIN( lastCurlyContext );
4762 //addToBody(yytext);
4763 lastStringContext=SkipCurly;
4764 BEGIN( SkipString );
4766 <SkipCurly>^{B}*"#" {
4769 //addToBody(yytext);
4770 BEGIN( SkipCurlyCpp );
4772 <SkipCurly,SkipInits>\n {
4774 //addToBody(yytext);
4776 <SkipCurly,SkipCurlyCpp>"<<<" {
4783 lastHereDocContext = YY_START;
4787 <SkipCurly,SkipCurlyCpp>[^\n#"'@\\/{}<]+ {
4788 lineCount(); // for g_column updates
4789 //addToBody(yytext);
4792 //addToBody(yytext);
4794 lastCurlyContext = FindMembers;
4797 <SkipCurlyCpp>\\[\r]*"\n"[\r]* {
4798 //addToBody(yytext);
4801 <SkipInits,SkipCurly,SkipCurlyCpp>"/*" {
4802 //addToBody(yytext);
4803 lastCContext = YY_START;
4806 <SkipInits,SkipCurly,SkipCurlyCpp>"//" {
4807 //addToBody(yytext);
4808 lastCContext = YY_START;
4809 BEGIN(SkipCxxComment);
4812 lastStringContext=YY_START;
4813 BEGIN( SkipString );
4816 warn(yyFileName,yyLineNr,
4817 "warning: Found ';' while parsing initializer list! "
4818 "(doxygen could be confused by a macro call without semicolon)"
4820 BEGIN( FindMembers );
4822 <SkipInits,SkipCurly,SkipCurlyCpp>"#" {
4825 //addToBody(yytext);
4826 lastCContext = YY_START;
4827 BEGIN(SkipCxxComment);
4829 <SkipInits,SkipCurly,SkipCurlyCpp>@\" {
4830 if (!insideCS) REJECT;
4831 // C# verbatim string
4832 lastSkipVerbStringContext=YY_START;
4833 pSkipVerbString=¤t->initializer;
4834 BEGIN(SkipVerbString);
4836 <SkipInits,SkipCurly,SkipCurlyCpp>{CHARLIT} {
4837 if (insidePHP) REJECT;
4839 <SkipInits,SkipCurly,SkipCurlyCpp>\' {
4842 lastStringContext=YY_START;
4843 BEGIN(SkipPHPString);
4846 <SkipInits,SkipCurly,SkipCurlyCpp>. { }
4847 <SkipString,SkipPHPString>\\. { }
4849 BEGIN( lastStringContext );
4852 BEGIN( lastStringContext );
4854 <SkipString,SkipPHPString>"/*"|"*/"|"//" { }
4855 <SkipString,SkipPHPString>\n {
4858 <SkipString,SkipPHPString>. { }
4859 <CompoundName>":" { // for "class : public base {} var;" construct, see bug 608359
4863 <Bases,CompoundName>";" {
4864 current->section = Entry::EMPTY_SEC ;
4865 current->type.resize(0) ;
4866 current->name.resize(0) ;
4867 current->args.resize(0) ;
4868 current->argList->clear();
4869 BEGIN( FindMembers ) ;
4871 <CompoundName>{SCOPENAME}{BN}*/"<" {
4873 current->name = yytext ;
4874 if (current->spec & Entry::Protocol)
4876 current->name+="-p";
4879 lastClassTemplSpecContext = ClassVar;
4880 if (insideObjC) // protocol list
4882 BEGIN( ObjCProtocolList );
4884 else if (insideCS) // C# generic class
4886 //current->name+="-g";
4889 else // C++ template specialization
4892 BEGIN( ClassTemplSpec );
4896 if (current->tArgLists==0)
4898 current->tArgLists = new QList<ArgumentList>;
4899 current->tArgLists->setAutoDelete(TRUE);
4901 ArgumentList *al = new ArgumentList;
4902 // check bug 612858 before enabling the next line
4903 //current->spec |= Entry::Template;
4904 current->tArgLists->append(al);
4905 currentArgumentList = al;
4907 current->name += "<";
4908 fullArgString = templateStr;
4909 copyArgString = ¤t->name;
4910 //copyArgString = &templateStr;
4911 currentArgumentContext = ClassVar;
4912 BEGIN( ReadTempArgs );
4914 <ObjCProtocolList>"<" {
4915 insideProtocolList=TRUE;
4918 <ClassTemplSpec>">"({BN}*"::"{BN}*{SCOPENAME})? {
4919 current->name += yytext;
4921 if (--sharpCount<=0)
4923 current->name = removeRedundantWhiteSpace(current->name);
4924 if (current->spec & Entry::Protocol)
4925 { // Objective-C protocol
4926 unput('{'); // fake start of body
4931 BEGIN( lastClassTemplSpecContext );
4935 <ClassTemplSpec>"<" {
4936 current->name += yytext;
4940 current->name += yytext;
4942 <CompoundName>{SCOPENAME}{BN}*";" { // forward declaration
4943 if (current->tArgLists && current->tArgLists->count()>0)
4945 // found a forward template declaration, this has
4946 // a purpose of its own
4947 current->name = yytext;
4948 current->name=current->name.left(current->name.length()-1).stripWhiteSpace();
4949 //printf("template class declaration for %s!\n",current->name.data());
4950 current_root->addSubEntry(current);
4951 current = new Entry;
4957 if (isTypedef) // typedef of a class, put typedef keyword back
4959 current->type.prepend("typedef");
4961 BEGIN( FindMembers );
4963 <CompoundName>{SCOPENAME}/{BN}*"(" {
4964 current->name = yytext ;
4966 if (current->spec & Entry::Protocol)
4968 current->name += "-p";
4972 <CompoundName>{SCOPENAME}/{BN}*"," { // multiple forward declarations on one line
4973 // e.g. @protocol A,B;
4977 <CompoundName>{SCOPENAME} {
4978 current->name = yytext ;
4980 if (current->spec & Entry::Protocol)
4982 current->name += "-p";
4984 if ((current->spec & Entry::Protocol) ||
4985 current->section == Entry::OBJCIMPL_SEC)
4987 unput('{'); // fake start of body
4991 <CompoundName>{CSSCOPENAME} { // C# style scope
4992 current->name = substitute(yytext,".","::");
4996 <ClassVar>{SCOPENAME}{BN}*/"(" {
4997 if (insideIDL && strncmp(yytext,"switch",6)==0 && !isId(yytext[6]))
4999 // Corba IDL style union
5001 BEGIN(SkipUnionSwitch);
5006 current->name = yytext;
5007 current->name = current->name.stripWhiteSpace();
5009 BEGIN( FindMembers );
5015 // multiple types in one typedef
5017 current->type.prepend("typedef ");
5022 // Multiple class forward declaration
5025 <ClassVar>("sealed"|"abstract")/{BN}*(":"|"{") {
5028 if (yytext[0]=='s') // sealed
5029 current->spec |= Entry::SealedClass;
5031 current->spec |= Entry::AbstractClass;
5040 if (insideIDL && strcmp(yytext,"switch")==0)
5042 // Corba IDL style union
5044 BEGIN(SkipUnionSwitch);
5046 else if ((insideJava || insidePHP || insideJS) && (strcmp(yytext,"implements")==0 || strcmp(yytext,"extends")==0))
5048 current->type.resize(0);
5052 BEGIN( BasesProt ) ;
5054 else if (insideCS && strcmp(yytext,"where")==0) // C# type contraint
5056 delete current->typeConstr;
5057 current->typeConstr = new ArgumentList;
5058 current->typeConstr->append(new Argument);
5059 lastCSConstraint = YY_START;
5060 BEGIN( CSConstraintName );
5062 else if (insideCli && strcmp(yytext,"abstract")==0)
5064 current->spec|=Entry::Abstract;
5066 else if (insideCli && strcmp(yytext,"sealed")==0)
5068 current->spec|=Entry::Sealed;
5070 else if (strcmp(yytext,"final")==0)
5072 current->spec|=Entry::Final;
5076 if (current->section == Entry::ENUM_SEC)
5077 { // found "enum a b" -> variable
5078 current->section = Entry::VARIABLE_SEC ;
5080 current->type += ' ' ;
5081 current->type += current->name ;
5082 current->name = yytext ;
5084 if (nameIsOperator(current->name))
5091 if (insideObjC && *yytext=='(') // class category
5094 //if (current->section!=Entry::OBJCIMPL_SEC)
5096 current->spec|=Entry::Category;
5098 BEGIN( ClassCategory );
5102 // probably a function anyway
5104 BEGIN( FindMembers );
5107 <CSConstraintType,CSConstraintName>"/**/" { /* empty comment */ }
5108 <CSConstraintType,CSConstraintName>("/*"[*!]|"//"[/!])("<"?) { // special comment
5109 fullArgString.resize(0);
5110 lastCopyArgChar='#'; // end marker
5111 lastCommentInArgContext=YY_START;
5113 BEGIN( CopyArgCommentLine );
5115 BEGIN( CopyArgComment );
5117 <CSConstraintType,CSConstraintName>"#" { // artificially inserted token to signal end of comment block
5118 current->typeConstr->last()->docs = fullArgString;
5120 <CSConstraintType>"{" { // end of type constraint reached
5121 // parse documentation of the constraints
5122 handleParametersCommentBlocks(current->typeConstr);
5124 BEGIN( lastCSConstraint );
5126 <CSConstraintType,CSConstraintName>";" {
5127 handleParametersCommentBlocks(current->typeConstr);
5129 BEGIN( lastCSConstraint );
5131 <CSConstraintName>":" {
5132 BEGIN( CSConstraintType );
5134 <CSConstraintName>{ID} {
5136 current->typeConstr->last()->name=yytext;
5138 <CSConstraintType>"where" { // another constraint for a different param
5139 current->typeConstr->append(new Argument);
5140 BEGIN( CSConstraintName );
5142 <CSConstraintType>({ID}".")*{ID}("<"{ID}">")?("()")? {
5143 if (current->typeConstr->last()->type.isEmpty())
5144 // first type constraint for this parameter
5146 current->typeConstr->last()->type=yytext;
5148 else // new type constraint for same parameter
5150 QCString name = current->typeConstr->last()->name;
5151 current->typeConstr->append(new Argument);
5152 current->typeConstr->last()->name=name;
5153 current->typeConstr->last()->type=yytext;
5156 <CSConstraintName,CSConstraintType>\n {
5159 <CSConstraintName,CSConstraintType>. {
5161 <ClassCategory>{ID} {
5162 current->name+=yytext;
5164 <ClassCategory>")"/{BN}*"{" {
5168 <ClassCategory>")"/{BN}*"<" {
5170 BEGIN( ObjCProtocolList );
5172 <ClassCategory>")" {
5174 if ((current->section & Entry::Protocol) ||
5175 current->section == Entry::OBJCIMPL_SEC)
5177 unput('{'); // fake start of body
5179 else // category has no variables so push back an empty body
5187 if (current->section==Entry::ENUM_SEC) // enum E:2, see bug 313527,
5188 // or C++11 style enum: 'E : unsigned int {...}'
5190 current->args.resize(0);
5191 BEGIN(EnumBaseType);
5195 current->type.resize(0);
5196 if ((current->spec & Entry::Interface) ||
5197 (current->spec & Entry::Struct) ||
5198 (current->spec & Entry::Ref) ||
5199 (current->spec & Entry::Value) ||
5200 insidePHP || insideCS || insideD || insideObjC
5207 BEGIN( BasesProt ) ;
5212 if (isTypedef) // typedef of a class, put typedef keyword back
5214 current->type.prepend("typedef");
5216 if ((yytext[0]=='*' || yytext[0]=='&') &&
5217 current->section == Entry::ENUM_SEC)
5218 { // found "enum a *b" -> variable
5219 current->section = Entry::VARIABLE_SEC ;
5221 BEGIN( FindMembers );
5223 <Bases,ClassVar>"///"/[^/] {
5231 current->program+=yytext;
5232 current->fileName = yyFileName ;
5233 current->startLine = yyLineNr ;
5235 BEGIN( ReadBodyIntf );
5238 <Bases,ClassVar>("//"{B}*)?"/**"/[^/*] |
5239 <Bases,ClassVar>("//"{B}*)?"/*!" |
5240 <Bases,ClassVar>"//!" |
5241 <Bases,ClassVar>[\-+]{BN}* {
5249 current->program+=yytext;
5250 current->fileName = yyFileName ;
5251 current->startLine = yyLineNr ;
5253 BEGIN( ReadBodyIntf );
5256 <CompoundName,ClassVar>{B}*"{"{B}* {
5257 current->fileName = yyFileName ;
5258 current->startLine = yyLineNr ;
5259 current->name = removeRedundantWhiteSpace(current->name);
5260 if (current->name.isEmpty() && !isTypedef) // anonymous compound
5262 if (current->section==Entry::NAMESPACE_SEC) // allow reopening of anonymous namespaces
5264 if (Config_getBool("EXTRACT_ANON_NSPACES")) // use visible name
5266 current->name="anonymous_namespace{"+stripPath(current->fileName)+"}";
5268 else // use invisible name
5270 current->name.sprintf("@%d",anonNSCount);
5275 current->name.sprintf("@%d",anonCount++);
5279 if (current_root && // not a nested struct inside an @interface section
5280 !(current_root->spec & Entry::Interface) &&
5281 ((current->spec & (Entry::Interface | Entry::Protocol | Entry::Category) ||
5282 current->section==Entry::OBJCIMPL_SEC)
5286 { // ObjC body that ends with @end
5287 BEGIN( ReadBodyIntf );
5289 else if (current->section==Entry::NAMESPACE_SEC)
5291 BEGIN( ReadNSBody );
5298 <BasesProt>"virtual"{BN}+ { lineCount(); baseVirt = Virtual; }
5299 <BasesProt>"public"{BN}+ { lineCount(); baseProt = Public; }
5300 <BasesProt>"protected"{BN}+ { lineCount(); baseProt = Protected; }
5301 <BasesProt>"internal"{BN}+ { lineCount(); baseProt = Package; }
5302 <BasesProt>"private"{BN}+ { lineCount(); baseProt = Private; }
5303 <BasesProt>{BN} { lineCount(); }
5304 <BasesProt>. { unput(*yytext); BEGIN(Bases); }
5305 <Bases>("\\")?({ID}"\\")*{ID} { // PHP namespace token, not sure if interspacing is allowed but it gives problems (see bug 640847)
5310 else // PHP base class of the form \Ns\Cl or Ns\Cl
5314 bn = substitute(bn,"\\","::");
5316 current->args += ' ';
5317 current->args += yytext;
5320 <Bases>("::")?{BN}*({ID}{BN}*"::"{BN}*)*{ID} {
5322 QCString baseScope = yytext;
5323 if (insideCS && baseScope.stripWhiteSpace()=="where")
5325 // type contraint for a class
5326 delete current->typeConstr;
5327 current->typeConstr = new ArgumentList;
5328 current->typeConstr->append(new Argument);
5329 lastCSConstraint = YY_START;
5330 BEGIN( CSConstraintName );
5335 current->args += ' ';
5336 current->args += yytext;
5339 <Bases>{BN}*{ID}("."{ID})* { // Java style class
5340 QCString name = substitute(yytext,".","::");
5342 current->args += ' ';
5343 current->args += name;
5345 <ClassVar,Bases>\n/{BN}*[^{, \t\n] {
5356 <ClassVar,Bases>"@end" { // empty ObjC interface
5357 unput('d'); // insert fake body: {}@end
5364 <ClassVar>"<" { current->name += *yytext;
5367 lastSkipSharpContext = YY_START;
5368 specName = ¤t->name;
5369 BEGIN ( Specialization );
5374 lastSkipSharpContext = YY_START;
5375 if (insideObjC) // start of protocol list
5379 else // template specialization
5381 //if (insideCS) // generic
5385 templateStr = yytext;
5386 specName = &templateStr;
5387 BEGIN ( Specialization );
5390 <Specialization>"<" { *specName += *yytext;
5391 if (roundCount==0) sharpCount++;
5393 <Specialization>">" {
5394 *specName += *yytext;
5395 if (roundCount==0 && --sharpCount<=0)
5397 if (1 /*!insideCS*/)
5399 baseName+=*specName;
5403 if (current->tArgLists==0)
5405 current->tArgLists = new QList<ArgumentList>;
5406 current->tArgLists->setAutoDelete(TRUE);
5408 ArgumentList *al = new ArgumentList;
5409 current->tArgLists->append(al);
5410 stringToArgumentList(*specName,al);
5412 BEGIN(lastSkipSharpContext);
5415 <Specialization>{BN}+ { lineCount(); *specName +=' '; }
5416 <Specialization>"<<" { *specName += yytext; }
5417 <Specialization>">>"/{B}*"::" { // M$ C++ extension to allow >> to close a template...
5422 <Specialization>">>" {
5423 if (insideCS) // for C# >> ends a nested template
5427 else // for C++ >> is a bitshift
5428 // operator and > > would end
5429 // a nested template.
5430 // We require the bitshift to be enclosed in braces.
5431 // See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html
5435 *specName += yytext;
5445 <Specialization>"typename"{BN}+ { lineCount(); }
5446 <Specialization>"(" { *specName += *yytext; roundCount++; }
5447 <Specialization>")" { *specName += *yytext; roundCount--; }
5449 *specName += *yytext;
5451 <SkipSharp>"<" { ++sharpCount; }
5452 <SkipSharp>">" { if (--sharpCount<=0)
5453 BEGIN ( lastSkipSharpContext );
5455 <SkipRound>"(" { ++roundCount; }
5456 <SkipRound>")" { if (--roundCount<=0)
5457 BEGIN ( lastSkipRoundContext );
5460 lastStringContext=SkipRound;
5463 <Bases>","|(">"({BN}*"{")?)|({BN}+"implements"{BN}*) { lineCount();
5464 if (insideProtocolList)
5470 current->args += ',' ;
5472 current->name = removeRedundantWhiteSpace(current->name);
5473 if (!baseName.isEmpty())
5475 current->extends->append(
5476 new BaseInfo(baseName,baseProt,baseVirt)
5479 if ((current->spec & (Entry::Interface|Entry::Struct)) ||
5480 insideJava || insidePHP || insideCS ||
5481 insideD || insideObjC)
5492 { // end of a ObjC protocol list
5493 insideProtocolList=FALSE;
5496 unput('{'); // dummy start body
5505 if (*yytext==',' && insideObjC) // Begin of protocol list
5507 insideProtocolList=TRUE;
5512 <Bases>{B}*"{"{B}* { current->fileName = yyFileName ;
5513 current->startLine = yyLineNr ;
5514 current->name = removeRedundantWhiteSpace(current->name);
5515 if (!baseName.isEmpty())
5516 current->extends->append(
5517 new BaseInfo(baseName,baseProt,baseVirt)
5522 BEGIN( ReadBodyIntf );
5529 <SkipUnionSwitch>{B}*"(" {
5532 <SkipUnionSwitch>")" {
5533 if (--roundCount==0)
5538 <SkipUnionSwitch>\n { lineCount(); }
5540 <Comment>{BN}+ { current->program += yytext ;
5543 <Comment>"/*" { current->program += yytext ; }
5544 <Comment>"//" { current->program += yytext ; }
5545 <Comment>{CMD}("code"|"verbatim") {
5547 current->program += yytext ;
5549 <Comment>{CMD}("endcode"|"endverbatim") {
5551 current->program += yytext ;
5553 <Comment>[^ \.\t\r\n\/\*]+ { current->program += yytext ; }
5554 <Comment>"*/" { current->program += yytext ;
5555 if (!insideCode) BEGIN( lastContext ) ;
5557 <Comment>. { current->program += *yytext ; }
5559 <FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>("//"{B}*)?"/*!" {
5560 //printf("Start doc block at %d\n",yyLineNr);
5561 removeSlashes=(yytext[1]=='/');
5563 if (!current->doc.isEmpty())
5565 current->doc+="\n\n";
5569 current->docLine = yyLineNr;
5570 current->docFile = yyFileName;
5573 lastDocContext = YY_START;
5574 if (current_root->section & Entry::SCOPE_MASK)
5576 current->inside = current_root->name+"::";
5578 docBlockContext = YY_START;
5579 docBlockInBody = YY_START==SkipCurly;
5580 docBlockAutoBrief = Config_getBool("QT_AUTOBRIEF");
5582 if (docBlockAutoBrief)
5584 current->briefLine = yyLineNr;
5585 current->briefFile = yyFileName;
5587 startCommentBlock(FALSE);
5590 <FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>("//"{B}*)?"/**"/[^/*] {
5591 removeSlashes=(yytext[1]=='/');
5592 lastDocContext = YY_START;
5594 //printf("Found comment block at %s:%d\n",yyFileName,yyLineNr);
5595 if (current_root->section & Entry::SCOPE_MASK)
5597 current->inside = current_root->name+"::";
5599 current->docLine = yyLineNr;
5600 current->docFile = yyFileName;
5601 docBlockContext = YY_START;
5602 docBlockInBody = YY_START==SkipCurly;
5603 static bool javadocAutoBrief = Config_getBool("JAVADOC_AUTOBRIEF");
5604 docBlockAutoBrief = javadocAutoBrief;
5608 indent.fill(' ',computeIndent(yytext,g_column));
5611 if (docBlockAutoBrief)
5613 current->briefLine = yyLineNr;
5614 current->briefFile = yyFileName;
5616 startCommentBlock(FALSE);
5619 <FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"//!" {
5621 lastDocContext = YY_START;
5622 if (current_root->section & Entry::SCOPE_MASK)
5624 current->inside = current_root->name+"::";
5626 docBlockContext = YY_START;
5627 docBlockInBody = YY_START==SkipCurly;
5628 docBlockAutoBrief = FALSE;
5630 startCommentBlock(current->brief.isEmpty());
5633 <FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"///"/[^/] {
5635 lastDocContext = YY_START;
5636 if (current_root->section & Entry::SCOPE_MASK)
5638 current->inside = current_root->name+"::";
5640 docBlockContext = YY_START;
5641 docBlockInBody = YY_START==SkipCurly;
5642 docBlockAutoBrief = FALSE;
5644 startCommentBlock(current->brief.isEmpty());
5647 <FindMembers>"extern"{BN}*"\"C"("++")?"\""{BN}*("{")? {
5656 else if (insideCS &&
5657 !current->name.isEmpty() &&
5658 !current->type.isEmpty())
5660 if (containsWord(current->type,"event")) // event
5662 current->mtype = mtype = Event;
5666 current->mtype = mtype = Property;
5668 current->bodyLine = yyLineNr;
5670 BEGIN( CSAccessorDecl );
5674 if ((insideJava || insideCS || insideD) &&
5675 current->name.isEmpty()
5678 // static Java initializer
5682 current->name="[static initializer]";
5683 current->type.resize(0);
5687 current->name="[instance initializer]";
5694 // pre C++11 code -> ignore the initializer
5696 //current->type.resize(0);
5697 //current->name.resize(0);
5698 //current->args.resize(0);
5699 //current->argList->clear();
5701 //BEGIN( SkipCurlyBlock );
5703 // C++11 style initializer list
5704 current->bodyLine = yyLineNr;
5705 current->initializer = yytext;
5706 lastInitializerContext = YY_START;
5708 BEGIN(ReadInitializer);
5712 <CSAccessorDecl>"{" { curlyCount++; }
5713 <CSAccessorDecl>"}" {
5725 <CSAccessorDecl>"set" { if (curlyCount==0) current->spec |= Entry::Settable; }
5726 <CSAccessorDecl>"get" { if (curlyCount==0) current->spec |= Entry::Gettable; }
5727 <CSAccessorDecl>"add" { if (curlyCount==0) current->spec |= Entry::Addable; }
5728 <CSAccessorDecl>"remove" { if (curlyCount==0) current->spec |= Entry::Removable; }
5729 <CSAccessorDecl>"raise" { if (curlyCount==0) current->spec |= Entry::Raisable; }
5730 <CSAccessorDecl>. {}
5731 <CSAccessorDecl>\n { lineCount(); }
5736 /**********************************************************************************/
5737 /******************** Documentation block related rules ***************************/
5738 /**********************************************************************************/
5740 /* ---- Single line comments ------ */
5741 <DocLine>[^\n]*"\n"[ \t]*"//"[/!] { // continuation of multiline C++-style comment
5743 docBlock.resize(docBlock.length() - 3);
5746 <DocLine>[^\n]*/"\n" { // whole line
5748 handleCommentBlock(docBlock.data(),current->brief.isEmpty());
5749 BEGIN( docBlockContext );
5752 /* ---- Comments blocks ------ */
5754 <DocBlock>"*"*"*/" { // end of comment block
5755 handleCommentBlock(docBlock.data(),FALSE);
5756 BEGIN(docBlockContext);
5758 <DocBlock>^{B}*("//")?{B}*"*"+/[^//a-z_A-Z0-9*] { // start of a comment line
5760 indent.fill(' ',computeIndent(yytext,g_column));
5763 <DocBlock>^{B}*("//"){B}* { // strip embedded C++ comments if at the start of a line
5765 <DocBlock>"//" { // slashes in the middle of a comment block
5768 <DocBlock>"/*" { // start of a new comment in the
5769 // middle of a comment block
5772 <DocBlock>("@@"|"\\\\"){ID}/[^a-z_A-Z0-9] { // escaped command
5775 <DocBlock>{CMD}("f$"|"f["|"f{") {
5777 docBlockName=&yytext[1];
5778 if (docBlockName.at(1)=='{')
5780 docBlockName.at(1)='}';
5782 BEGIN(DocCopyBlock);
5784 <DocBlock>"<"{PRE}">" {
5786 docBlockName="<pre>";
5787 BEGIN(DocCopyBlock);
5789 <DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9] { // verbatim command (which could contain nested comments!)
5791 docBlockName=&yytext[1];
5792 BEGIN(DocCopyBlock);
5794 <DocBlock>{B}*"<code>" {
5798 docBlockName="<code>";
5799 BEGIN(DocCopyBlock);
5806 <DocBlock>[^@*\/\\\n]+ { // any character that isn't special
5809 <DocBlock>\n { // newline
5813 <DocBlock>. { // command block
5817 /* ---- Copy verbatim sections ------ */
5819 <DocCopyBlock>"</"{PRE}">" { // end of a <pre> block
5821 if (docBlockName=="<pre>")
5826 <DocCopyBlock>"</"{CODE}">" { // end of a <code> block
5828 if (docBlockName=="<code>")
5833 <DocCopyBlock>[\\@]("f$"|"f]"|"f}") {
5837 <DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"endmanonly"|"enddot"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block
5839 if (&yytext[4]==docBlockName)
5844 <DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line
5845 if (docBlockName=="verbatim")
5852 indent.fill(' ',computeIndent(yytext,0));
5856 <DocCopyBlock>[^\<@/*\]\$\\\n]+ { // any character that is not special
5859 <DocCopyBlock>"/*"|"*/"|"//" {
5862 <DocCopyBlock>\n { // newline
5866 <DocCopyBlock>. { // any other character
5869 <DocCopyBlock><<EOF>> {
5870 warn(yyFileName,yyLineNr,
5871 "warning: reached end of file while inside a %s block!\n"
5872 "The command that should end the block seems to be missing!\n",
5873 docBlockName.data());
5878 /* ------------- Prototype parser -------------- */
5880 <Prototype>"operator"{B}*"("{B}*")" {
5881 current->name+=yytext;
5884 current->args+=*yytext;
5885 currentArgumentContext = PrototypeQual;
5886 fullArgString = current->args.copy();
5887 copyArgString = ¤t->args;
5888 BEGIN( ReadFuncArgType ) ;
5890 <Prototype>"("({ID}"::")*({B}*[&*])+ {
5891 current->type+=current->name+yytext;
5892 current->name.resize(0);
5893 BEGIN( PrototypePtr );
5895 <PrototypePtr>{SCOPENAME} {
5896 current->name+=yytext;
5899 current->args+=*yytext;
5900 currentArgumentContext = PrototypeQual;
5901 fullArgString = current->args.copy();
5902 copyArgString = ¤t->args;
5903 BEGIN( ReadFuncArgType ) ;
5910 current->name+=yytext;
5912 <PrototypeQual>"{" {
5913 BEGIN( PrototypeSkipLine);
5915 <PrototypeQual>{B}*"const"{B}* {
5916 current->args += " const ";
5917 current->argList->constSpecifier=TRUE;
5919 <PrototypeQual>{B}*"volatile"{B}* {
5920 current->args += " volatile ";
5921 current->argList->volatileSpecifier=TRUE;
5923 <PrototypeQual>{B}*"="{B}*"0"{B}* {
5924 current->args += " = 0";
5925 current->virt = Pure;
5926 current->argList->pureSpecifier=TRUE;
5928 <PrototypeQual>"throw"{B}*"(" {
5929 current->exception = "throw(";
5930 BEGIN(PrototypeExc);
5933 current->exception += ')';
5934 BEGIN(PrototypeQual);
5937 current->exception += *yytext;
5940 current->args += *yytext;
5943 current->name += *yytext;
5945 <PrototypeSkipLine>. {
5949 /* ------------ Generic rules -------------- */
5952 <SkipCxxComment>.*"\\\n" { // line continuation
5962 <SkipCxxComment>.*/\n {
5963 BEGIN( lastCContext ) ;
5965 <SkipComment>[^\*\n]+
5966 <*>\n { lineCount(); }
5968 if (insideIDL && insideCppQuote)
5976 lastCContext = YY_START ;
5977 BEGIN( SkipCxxComment ) ;
5982 lastStringContext=YY_START;
5983 BEGIN(SkipPHPString);
5989 lastStringContext=YY_START;
5994 <SkipComment>"//"|"/*"
5995 <*>"/*" { lastCContext = YY_START ;
5996 BEGIN( SkipComment ) ;
5998 <SkipComment>{B}*"*/" { BEGIN( lastCContext ) ; }
6000 lastCContext = YY_START ;
6001 BEGIN( SkipCxxComment ) ;
6005 //----------------------------------------------------------------------------
6007 static void startCommentBlock(bool brief)
6011 current->briefFile = yyFileName;
6012 current->briefLine = yyLineNr;
6016 current->docFile = yyFileName;
6017 current->docLine = yyLineNr;
6021 //----------------------------------------------------------------------------
6023 static void newEntry()
6025 current_root->addSubEntry(current);
6027 current = new Entry ;
6031 static void handleCommentBlock(const QCString &doc,bool brief)
6033 static bool hideInBodyDocs = Config_getBool("HIDE_IN_BODY_DOCS");
6035 bool needsEntry=FALSE;
6036 if (docBlockInBody && hideInBodyDocs) return;
6037 //printf("parseCommentBlock [%s] brief=%d\n",doc.data(),brief);
6038 int lineNr = brief ? current->briefLine : current->docLine; // line of block start
6040 // fill in inbodyFile && inbodyLine the first time, see bug 633891
6041 Entry *docEntry = docBlockInBody && previous ? previous : current;
6042 if (docBlockInBody && docEntry && docEntry->inbodyLine==-1)
6044 docEntry->inbodyFile = yyFileName;
6045 docEntry->inbodyLine = lineNr;
6048 while (parseCommentBlock(
6050 docBlockInBody && previous ? previous : current,
6051 stripIndentation(doc), // text
6053 lineNr, // line of block start
6054 docBlockInBody ? FALSE : brief, // isBrief
6055 docBlockInBody ? FALSE : docBlockAutoBrief, // isJavaDocStyle
6056 docBlockInBody, // isInBody
6063 //printf("parseCommentBlock position=%d [%s]\n",position,doc.data()+position);
6066 QCString docFile = current->docFile;
6068 current->docFile = docFile;
6069 current->docLine = lineNr;
6079 unput(docBlockTerm);
6084 static void handleParametersCommentBlocks(ArgumentList *al)
6086 //printf(">>>>>>> handleParametersCommentBlocks()\n");
6087 ArgumentListIterator ali(*al);
6089 for (ali.toFirst();(a=ali.current());++ali)
6091 //printf(" Param %s docs=%s\n",a->name.data(),a->docs.data());
6092 if (!a->docs.isEmpty())
6098 QCString orgDoc = current->doc;
6099 QCString orgBrief = current->brief;
6100 int orgDocLine = current->docLine;
6101 int orgBriefLine = current->briefLine;
6103 current->doc.resize(0);
6104 current->brief.resize(0);
6106 //printf("handleParametersCommentBlock [%s]\n",doc.data());
6107 while (parseCommentBlock(
6112 current->docLine, // line of block start
6122 //printf("handleParametersCommentBlock position=%d [%s]\n",position,doc.data()+position);
6123 if (needsEntry) newEntry();
6129 a->docs = current->doc;
6132 current->doc = orgDoc;
6133 current->brief = orgBrief;
6134 current->docLine = orgDocLine;
6135 current->briefLine = orgBriefLine;
6141 //----------------------------------------------------------------------------
6143 static void parseCompounds(Entry *rt)
6145 //printf("parseCompounds(%s)\n",rt->name.data());
6146 g_inputFromFile = FALSE;
6147 EntryListIterator eli(*rt->children());
6149 for (;(ce=eli.current());++eli)
6151 if (!ce->program.isEmpty())
6153 //printf("-- %s ---------\n%s\n---------------\n",
6154 // ce->name.data(),ce->program.data());
6155 // init scanner state
6159 inputString = ce->program;
6161 scanYYrestart( scanYYin ) ;
6162 if (ce->section==Entry::ENUM_SEC || (ce->spec&Entry::Enum))
6163 BEGIN( FindFields ) ;
6165 BEGIN( FindMembers ) ;
6167 yyFileName = ce->fileName;
6169 yyLineNr = ce->startLine ;
6170 insideObjC = ce->lang==SrcLangExt_ObjC;
6171 //printf("---> Inner block starts at line %d objC=%d\n",yyLineNr,insideObjC);
6173 if (current) delete current;
6174 current = new Entry;
6177 int ni=ce->name.findRev("::"); if (ni==-1) ni=0; else ni+=2;
6178 // set default protection based on the compound type
6179 if( ce->section==Entry::CLASS_SEC ) // class
6182 if (insidePHP || insideD || insideJS)
6184 current->protection = protection = Public ;
6186 else if (insideJava)
6188 current->protection = protection = (ce->spec & (Entry::Interface|Entry::Enum)) ? Public : Package;
6190 else if (ce->spec&(Entry::Interface | Entry::Ref | Entry::Value | Entry::Struct | Entry::Union))
6192 if (ce->lang==SrcLangExt_ObjC)
6194 current->protection = protection = Protected ;
6198 current->protection = protection = Public ;
6203 current->protection = protection = Private ;
6206 else if (ce->section == Entry::ENUM_SEC ) // enum
6208 current->protection = protection = ce->protection;
6210 else if (!ce->name.isEmpty() && ce->name.at(ni)=='@') // unnamed union or namespace
6212 if (ce->section == Entry::NAMESPACE_SEC ) // unnamed namespace
6214 current->stat = gstat = TRUE;
6216 current->protection = protection = ce->protection;
6218 else // named struct, union, protocol, category
6220 current->protection = protection = Public ;
6224 //printf("name=%s current->stat=%d gstat=%d\n",ce->name.data(),current->stat,gstat);
6226 //memberGroupId = DOX_NOGROUP;
6227 //memberGroupRelates.resize(0);
6228 //memberGroupInside.resize(0);
6229 groupEnterCompound(yyFileName,yyLineNr,ce->name);
6235 groupLeaveCompound(yyFileName,yyLineNr,ce->name);
6237 delete current; current=0;
6238 ce->program.resize(0);
6243 // warn(yyFileName,yyLineNr,"Documentation block ended in the middle of a conditional section!");
6250 //----------------------------------------------------------------------------
6252 static void parseMain(const char *fileName,const char *fileBuf,Entry *rt)
6255 //g_inputFromFile = TRUE;
6257 inputString = fileBuf;
6259 g_inputFromFile = FALSE;
6262 //anonCount = 0; // don't reset per file
6264 protection = Public;
6270 inputFile.setName(fileName);
6271 if (inputFile.open(IO_ReadOnly))
6274 yyFileName = fileName;
6276 rt->lang = language;
6277 msg("Parsing file %s...\n",yyFileName.data());
6281 groupEnterFile(yyFileName,yyLineNr);
6282 current = new Entry;
6283 //printf("current=%p current_root=%p\n",current,current_root);
6284 int sec=guessSection(yyFileName);
6287 current->name = yyFileName;
6288 current->section = sec;
6289 current_root->addSubEntry(current);
6290 current = new Entry;
6294 scanYYrestart( scanYYin );
6297 BEGIN( FindMembersPHP );
6301 BEGIN( FindMembers );
6307 if (YY_START==Comment)
6309 warn(yyFileName,yyLineNr,"warning: File ended in the middle of a comment block! Perhaps a missing \\endcode?");
6313 groupLeaveFile(yyFileName,yyLineNr);
6317 // warn(yyFileName,yyLineNr,"Documentation block ended in the middle of a conditional section!");
6320 rt->program.resize(0);
6321 if (rt->children()->contains(current)==0)
6322 // it could be that current is already added as a child to rt, so we
6323 // only delete it if this is not the case. See bug 635317.
6325 delete current; current=0;
6336 //----------------------------------------------------------------------------
6338 static void parsePrototype(const QCString &text)
6340 //printf("**** parsePrototype(%s) begin\n",text.data());
6343 warn(yyFileName,yyLineNr,"Empty prototype found!");
6347 const char *orgInputString;
6348 int orgInputPosition;
6349 YY_BUFFER_STATE orgState;
6350 bool orgInputFromFile;
6352 // save scanner state
6353 orgState = YY_CURRENT_BUFFER;
6354 yy_switch_to_buffer(yy_create_buffer(scanYYin, YY_BUF_SIZE));
6355 orgInputString = inputString;
6356 orgInputPosition = inputPosition;
6357 orgInputFromFile = g_inputFromFile;
6363 g_inputFromFile = FALSE;
6364 scanYYrestart( scanYYin );
6369 current->name = current->name.stripWhiteSpace();
6370 if (current->section == Entry::MEMBERDOC_SEC && current->args.isEmpty())
6371 current->section = Entry::VARIABLEDOC_SEC;
6373 // restore original scanner state
6374 YY_BUFFER_STATE tmpState = YY_CURRENT_BUFFER;
6375 yy_switch_to_buffer(orgState);
6376 yy_delete_buffer(tmpState);
6377 inputString = orgInputString;
6378 inputPosition = orgInputPosition;
6379 g_inputFromFile = orgInputFromFile;
6381 //printf("**** parsePrototype end\n");
6384 void scanFreeScanner()
6386 #if defined(YY_FLEX_SUBMINOR_VERSION)
6389 scanYYlex_destroy();
6394 //static void handleGroupStartCommand(const char *header)
6396 // memberGroupHeader=header;
6397 // startGroupInDoc();
6400 //static void handleGroupEndCommand()
6406 //----------------------------------------------------------------------------
6408 void CLanguageScanner::parseInput(const char *fileName,const char *fileBuf,Entry *root)
6410 g_thisParser = this;
6411 ::parseMain(fileName,fileBuf,root);
6414 void CLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf,
6415 const char * scopeName,
6416 const QCString & input,
6417 bool isExampleBlock,
6418 const char * exampleName,
6422 bool inlineFragment,
6423 MemberDef *memberDef,
6424 bool showLineNumbers,
6425 Definition *searchCtx
6428 ::parseCCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName,
6429 fileDef,startLine,endLine,inlineFragment,memberDef,
6430 showLineNumbers,searchCtx);
6433 bool CLanguageScanner::needsPreprocessing(const QCString &extension)
6435 QCString fe=extension.lower();
6437 !( fe==".java" || fe==".as" || fe==".d" || fe==".php" ||
6438 fe==".php4" || fe==".inc" || fe==".phtml"
6442 void CLanguageScanner::resetCodeParserState()
6444 ::resetCCodeParserState();
6447 void CLanguageScanner::parsePrototype(const char *text)
6449 ::parsePrototype(text);
6452 //----------------------------------------------------------------------------
6454 #if !defined(YY_FLEX_SUBMINOR_VERSION)
6455 //----------------------------------------------------------------------------
6456 extern "C" { // some bogus code to keep the compiler happy
6457 void scannerYYdummy() { yy_flex_realloc(0,0); }