9c21d41026c660a6963b1b6d14f49c5d2414e899
[platform/upstream/doxygen.git] / src / pyscanner.l
1 /******************************************************************************
2  *
3  * 
4  *
5  * Copyright (C) 1997-2015 by Dimitri van Heesch.
6  *
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.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17 /*  This code is based on the work done by the MoxyPyDoxy team
18  *  (Linda Leong, Mike Rivera, Kim Truong, and Gabriel Estrada)
19  *  in Spring 2005 as part of CS 179E: Compiler Design Project
20  *  at the University of California, Riverside; the course was
21  *  taught by Peter H. Froehlich <phf@acm.org>.
22  */
23
24 %option never-interactive
25 %option prefix="pyscannerYY"
26
27 %{
28
29 /*
30  *      includes
31  */
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <assert.h>
35 #include <ctype.h>
36
37 #include <qarray.h>
38 #include <qstack.h>
39 #include <qregexp.h>
40 #include <qfile.h>
41 #include <qfileinfo.h>
42   
43 #include "pyscanner.h"
44 #include "entry.h"
45 #include "message.h"
46 #include "config.h"
47 #include "doxygen.h"
48 #include "util.h"
49 #include "defargs.h"
50 #include "language.h"
51 #include "commentscan.h"
52 #include "pycode.h"
53 #include "arguments.h"
54
55 // Toggle for some debugging info
56 //#define DBG_CTX(x) fprintf x
57 #define DBG_CTX(x) do { } while(0)
58
59 #define YY_NO_INPUT 1
60 #define YY_NO_UNISTD_H 1
61
62 /* -----------------------------------------------------------------
63  *
64  *      statics
65  */
66
67   
68 static ParserInterface *g_thisParser;
69 static const char *     inputString;
70 static int              inputPosition;
71 static QFile            inputFile;
72
73 static Protection       protection;
74
75 static Entry*           current_root = 0 ;
76 static Entry*           current      = 0 ;
77 static Entry*           previous     = 0 ;
78 static Entry*           bodyEntry    = 0 ;
79 static int              yyLineNr     = 1 ;
80 static QCString         yyFileName;
81 static MethodTypes      mtype;
82 static bool             gstat;
83 static Specifier        virt;
84
85 static int              docBlockContext;
86 static QCString         docBlock;
87 static bool             docBlockInBody;
88 static bool             docBlockJavaStyle;
89 static bool             docBrief;
90 static bool             docBlockSpecial;
91
92 static bool             g_doubleQuote;
93 static bool             g_specialBlock;
94 static int              g_stringContext;
95 static QGString *       g_copyString;
96 static int              g_indent = 0;
97 static int              g_curIndent = 0;
98
99 static QDict<QCString>  g_packageNameCache(257);
100
101 static char             g_atomStart;
102 static char             g_atomEnd;
103 static int              g_atomCount;
104
105 //static bool             g_insideConstructor;
106
107 static QCString         g_moduleScope;
108 static QCString         g_packageName;
109
110 //static bool             g_hideClassDocs;
111
112 static QCString         g_defVal;
113 static int              g_braceCount;
114
115 static bool             g_lexInit = FALSE;
116 static bool             g_packageCommentAllowed;
117
118 static bool             g_start_init = FALSE;
119 static int              g_search_count = 0;
120
121 //-----------------------------------------------------------------------------
122
123
124 static void initParser()
125 {
126   protection = Public;
127   mtype = Method;
128   gstat = FALSE;
129   virt = Normal;
130   previous = 0;
131   g_packageCommentAllowed = TRUE;
132   g_packageNameCache.setAutoDelete(TRUE);
133 }
134
135 static void initEntry()
136 {
137   //current->python = TRUE;
138   current->protection = protection ;
139   current->mtype      = mtype;
140   current->virt       = virt;
141   current->stat       = gstat;
142   current->lang       = SrcLangExt_Python; 
143   current->setParent(current_root);
144   initGroupInfo(current);
145   gstat = FALSE;
146 }
147
148 static void newEntry()
149 {
150   previous = current;
151   current_root->addSubEntry(current);
152   current = new Entry ;
153   initEntry();
154 }
155
156 static void newVariable()
157 {
158   if (!current->name.isEmpty() && current->name.at(0)=='_') // mark as private
159   {
160     current->protection=Private;
161   }
162   if (current_root->section&Entry::COMPOUND_MASK) // mark as class variable
163   {
164     current->stat = TRUE;
165   }
166   newEntry();
167 }
168
169 static void newFunction()
170 {
171   if (current->name.left(2)=="__" && current->name.right(2)=="__")
172   {
173     // special method name, see
174     // http://docs.python.org/ref/specialnames.html
175     current->protection=Public;
176   }
177   else if (current->name.at(0)=='_')
178   {
179     current->protection=Private;
180   }
181 }
182
183 static inline int computeIndent(const char *s)
184 {
185   int col=0;
186   static int tabSize=Config_getInt(TAB_SIZE);
187   const char *p=s;
188   char c;
189   while ((c=*p++))
190   {
191     if (c==' ') col++;
192     else if (c=='\t') col+=tabSize-(col%tabSize);
193     else break;
194   }
195   return col;
196 }
197
198 static QCString findPackageScopeFromPath(const QCString &path)
199 {
200   QCString *pScope = g_packageNameCache.find(path);
201   if (pScope)
202   {
203     return *pScope;
204   }
205   QFileInfo pf(path+"/__init__.py"); // found package initialization file
206   if (pf.exists())
207   {
208     int i=path.findRev('/');
209     if (i!=-1)
210     {
211       QCString scope = findPackageScopeFromPath(path.left(i));
212       if (!scope.isEmpty())
213       {
214         scope+="::";
215       }
216       scope+=path.mid(i+1);
217       g_packageNameCache.insert(path,new QCString(scope));
218       return scope;
219     }
220   }
221   return "";
222 }
223   
224 static QCString findPackageScope(const char *fileName)
225 {
226   if (fileName==0) return "";
227   QFileInfo fi(fileName);
228   return findPackageScopeFromPath(fi.dirPath(TRUE).data());
229 }
230
231 //-----------------------------------------------------------------------------
232
233 static void lineCount()
234 {
235   DBG_CTX((stderr,"yyLineNr=%d\n",yyLineNr));
236   for (const char *p = yytext; *p; ++p)
237   {
238     yyLineNr += (*p == '\n') ;
239   }
240 }
241
242 static void incLineNr()
243 {
244   DBG_CTX((stderr,"yyLineNr=%d\n",yyLineNr));
245   yyLineNr++;
246 }
247
248 #if 0
249 // Appends the current-name to current-type;
250 // Destroys current-name.
251 // Destroys current->args and current->argList
252 static void addType( Entry* current )
253 {
254     uint tl=current->type.length();
255     if ( tl>0 && !current->name.isEmpty() && current->type.at(tl-1)!='.') 
256     {
257       current->type += ' ' ;
258     }
259     current->type += current->name ;
260     current->name.resize(0) ;
261     tl=current->type.length();
262     if ( tl>0 && !current->args.isEmpty() && current->type.at(tl-1)!='.') 
263     {
264       current->type += ' ' ;
265     }
266     current->type += current->args ;
267     current->args.resize(0) ;
268     current->argList->clear();
269 }
270
271 static QCString stripQuotes(const char *s)
272 {
273   QCString name;
274   if (s==0 || *s==0) return name;
275   name=s;
276   if (name.at(0)=='"' && name.at(name.length()-1)=='"')
277   {
278     name=name.mid(1,name.length()-2);
279   }
280   return name;
281 }
282 #endif
283 //-----------------------------------------------------------------
284
285 //-----------------------------------------------------------------
286 static void startCommentBlock(bool brief)
287 {
288   if (brief)
289   {
290     current->briefFile = yyFileName;
291     current->briefLine = yyLineNr;
292   }
293   else
294   {
295     current->docFile = yyFileName;
296     current->docLine = yyLineNr;
297   }
298 }
299
300 /*
301 static void appendDocBlock() {
302   previous = current;
303   current_root->addSubEntry(current);
304   current = new Entry;
305   initEntry();
306 }
307 */
308
309 static void handleCommentBlock(const QCString &doc,bool brief)
310 {
311   //printf("handleCommentBlock(doc=[%s] brief=%d docBlockInBody=%d docBlockJavaStyle=%d\n",
312   //    doc.data(),brief,docBlockInBody,docBlockJavaStyle);
313
314   // TODO: Fix me
315   docBlockInBody=FALSE;
316   
317   if (docBlockInBody && previous && !previous->doc.isEmpty())
318   {
319     previous->doc=previous->doc.stripWhiteSpace()+"\n\n";
320   }
321
322   int position = 0;
323   bool needsEntry;
324   int lineNr = brief ? current->briefLine : current->docLine;
325   while (parseCommentBlock(
326         g_thisParser,
327         (docBlockInBody && previous) ? previous : current,
328         doc,     // text
329         yyFileName, // file
330         lineNr,
331         docBlockInBody ? FALSE : brief, 
332     docBlockJavaStyle, // javadoc style // or FALSE,
333         docBlockInBody,
334         protection,
335         position,
336         needsEntry)
337      ) // need to start a new entry
338   {
339     if (needsEntry)
340     {
341       newEntry();
342     }
343   }
344   if (needsEntry)
345   {
346     newEntry();
347   }
348
349 }
350
351 static void endOfDef(int correction=0)
352 {
353   //printf("endOfDef at=%d\n",yyLineNr);
354   if (bodyEntry)
355   {
356     bodyEntry->endBodyLine  = yyLineNr-correction;
357     bodyEntry = 0;
358   }
359   newEntry();
360   //g_insideConstructor = FALSE;
361 }
362
363 static inline void addToString(const char *s)
364 {
365   if (g_copyString) (*g_copyString)+=s;
366 }
367
368 static void initTriDoubleQuoteBlock()
369 {
370   docBlockContext   = YY_START;
371   docBlockInBody    = FALSE;
372   docBlockJavaStyle = TRUE;
373   docBlockSpecial   = yytext[strlen(yytext) - 1]=='!';
374   docBlock.resize(0);
375   g_doubleQuote = TRUE;
376   startCommentBlock(FALSE);
377 }
378
379 static void initTriSingleQuoteBlock()
380 {
381   docBlockContext   = YY_START;
382   docBlockInBody    = FALSE;
383   docBlockJavaStyle = TRUE;
384   docBlockSpecial   = yytext[strlen(yytext) - 1]=='!';
385   docBlock.resize(0);
386   g_doubleQuote = FALSE;
387   startCommentBlock(FALSE);
388 }
389
390 static void initSpecialBlock()
391 {
392   docBlockContext   = YY_START;
393   docBlockInBody    = FALSE;
394   docBlockJavaStyle = TRUE;
395   docBrief = TRUE;
396   docBlock.resize(0);
397   startCommentBlock(TRUE);
398 }
399
400 static void searchFoundDef()
401 {
402   current->fileName  = yyFileName;
403   current->startLine = yyLineNr;
404   current->bodyLine  = yyLineNr;
405   current->section = Entry::FUNCTION_SEC;
406   current->lang = SrcLangExt_Python;
407   current->virt = Normal;
408   current->stat = gstat;
409   current->mtype = mtype = Method;
410   current->type.resize(0);
411   current->name.resize(0);
412   current->args.resize(0);
413   current->argList->clear();
414   g_packageCommentAllowed = FALSE;
415   gstat=FALSE;
416   //printf("searchFoundDef at=%d\n",yyLineNr);
417 }
418
419 static void searchFoundClass()
420 {
421   current->section = Entry::CLASS_SEC;
422   current->argList->clear();
423   current->type += "class" ;
424   current->fileName  = yyFileName;
425   current->startLine  = yyLineNr;
426   current->bodyLine  = yyLineNr;
427   g_packageCommentAllowed = FALSE;
428 }
429
430 //-----------------------------------------------------------------------------
431 /* ----------------------------------------------------------------- */
432 #undef  YY_INPUT
433 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
434
435 static int yyread(char *buf,int max_size)
436 {
437   int c=0;
438   while ( c < max_size && inputString[inputPosition] )
439   {
440     *buf = inputString[inputPosition++] ;
441     //printf("%d (%c)\n",*buf,*buf);
442     c++; buf++;
443   }
444   return c;
445 }
446
447 %}
448
449        /* start command character */
450
451
452
453 BB                [ \t]+
454 B                 [ \t]*
455 NEWLINE           \n
456 BN                [ \t\n]
457
458 DIGIT             [0-9]
459
460 HEXNUMBER         "0"[xX][0-9a-fA-F]+[lL]?
461 OCTNUMBER         "0"[0-7]+[lL]?
462 NUMBER            {DIGIT}+[lLjJ]?
463 INTNUMBER         {HEXNUMBER}|{OCTNUMBER}|{NUMBER}
464 FLOATNUMBER       {DIGIT}+"."{DIGIT}+([eE][+\-]?{DIGIT}+)?[jJ]?
465 BOOL              ("True"|"False")
466 LETTER            [A-Za-z\x80-\xFF]
467 NONEMPTY          [A-Za-z0-9_\x80-\xFF]
468 EXPCHAR           [#(){}\[\],:.%/\\=`*~|&<>!;+-]
469 NONEMPTYEXP       [^ \t\n:]
470 PARAMNONEMPTY     [^ \t\n():]
471 IDENTIFIER        ({LETTER}|"_")({LETTER}|{DIGIT}|"_")*  
472 SCOPE             {IDENTIFIER}("."{IDENTIFIER})*
473 BORDER            ([^A-Za-z0-9])
474
475 TRISINGLEQUOTE    {STRINGPREFIX}?"'''"(!)?
476 TRIDOUBLEQUOTE    {STRINGPREFIX}?"\"\"\""(!)?
477 ENDTRISINGLEQUOTE "'''"
478 ENDTRIDOUBLEQUOTE "\"\"\""
479 LONGSTRINGCHAR    [^\\"']
480 ESCAPESEQ         ("\\")(.)
481 LONGSTRINGITEM    ({LONGSTRINGCHAR}|{ESCAPESEQ})
482 SMALLQUOTE        ("\"\""|"\""|"'"|"''")
483 LONGSTRINGBLOCK   ({LONGSTRINGITEM}+|{SMALLQUOTE})
484
485 SHORTSTRING       ("'"{SHORTSTRINGITEM}*"'"|'"'{SHORTSTRINGITEM}*'"')
486 SHORTSTRINGITEM   ({SHORTSTRINGCHAR}|{ESCAPESEQ})
487 SHORTSTRINGCHAR   [^\\\n"]
488 STRINGLITERAL     {STRINGPREFIX}?( {SHORTSTRING} | {LONGSTRING})  
489 STRINGPREFIX      ("r"|"u"|"ur"|"R"|"U"|"UR"|"Ur"|"uR")
490 KEYWORD           ("lambda"|"import"|"class"|"assert"|"as"|"from"|"global"|"def"|"True"|"False")
491 FLOWKW            ("or"|"and"|"is"|"not"|"print"|"for"|"in"|"if"|"try"|"except"|"yield"|"raise"|"break"|"continue"|"pass"|"if"|"return"|"while"|"elif"|"else"|"finally")
492 POUNDCOMMENT      "#"[^#\n][^\n]* 
493 SCRIPTCOMMENT      "#!".* 
494
495 STARTDOCSYMS      "##"
496
497 %option noyywrap
498
499   /* Main start state */
500
501 %x Search
502 %x SearchMemVars
503
504   /* Mid-comment states */
505
506   /* %x FuncDoubleComment */
507   /* %x ClassDoubleComment */
508 %x TryClassDocString
509 %x TripleComment
510 %x SpecialComment
511
512   /* Function states */
513
514 %x FunctionDec
515 %x FunctionParams
516 %x FunctionBody
517 %x FunctionParamDefVal
518
519   /* Class states */
520
521 %x ClassDec
522 %x ClassInheritance
523 %x ClassCaptureIndent
524 %x ClassBody
525
526   /* Variable states */
527 %x VariableDec
528 %x VariableEnd
529 %x VariableAtom
530
531   /* String states */
532
533 %x SingleQuoteString
534 %x DoubleQuoteString
535 %x TripleString
536
537   /* import */
538 %x FromMod
539 %x FromModItem
540 %x Import
541
542 %%
543
544   /* ------------ Function recognition rules -------------- */
545
546 <Search>{
547
548     ^{B}"def"{BB}       { // start of a function/method definition with indent
549                           DBG_CTX((stderr,"Found def at %d\n",yyLineNr));
550                           g_indent=computeIndent(yytext);
551                           searchFoundDef();
552                           BEGIN( FunctionDec );
553                         }
554     "def"{BB}           { // start of a function/method definition
555                           searchFoundDef();
556                           BEGIN( FunctionDec );
557                         }
558
559      ^{B}"class"{BB}    { // start of a class definition with indent
560                           DBG_CTX((stderr,"Found class at %d\n",yyLineNr));
561                           g_indent=computeIndent(yytext);
562                           searchFoundClass();
563                           BEGIN( ClassDec ) ;
564                         }
565      "class"{BB}        {  // start of a class definition
566                           searchFoundClass();
567                           BEGIN( ClassDec ) ;
568                        }
569      ^{B}"from"{BB}    |
570      "from"{BB}        { // start of an from import
571                           g_packageCommentAllowed = FALSE;
572                           BEGIN( FromMod );
573                        }
574
575      ^{B}"import"{BB}  |
576      "import"{BB}      { // start of an import statement
577                           g_packageCommentAllowed = FALSE;
578                           BEGIN( Import );
579                        }
580      ^{B}{IDENTIFIER}/{B}"="{B}"property" { // property
581                         current->section   = Entry::VARIABLE_SEC;
582                         current->mtype     = Property;
583                         current->name      = QCString(yytext).stripWhiteSpace();
584                         current->fileName  = yyFileName;
585                         current->startLine = yyLineNr;
586                         current->bodyLine  = yyLineNr;
587                         g_packageCommentAllowed = FALSE;
588                         BEGIN(VariableDec);
589                       }
590      ^{B}{IDENTIFIER}/{B}"="[^=] { // variable
591                         if (g_search_count) REJECT;
592                         g_indent=computeIndent(yytext);
593                         current->section   = Entry::VARIABLE_SEC;
594                         current->name      = QCString(yytext).stripWhiteSpace();
595                         current->fileName  = yyFileName;
596                         current->startLine = yyLineNr;
597                         current->bodyLine  = yyLineNr;
598                         g_packageCommentAllowed = FALSE;
599                         BEGIN(VariableDec);
600                       }
601      {B}{IDENTIFIER}/({B},{B}{IDENTIFIER})*{B}")"*{B}"="[^=] { // list of variables, we cannot place the default value
602                                                                // so we will skip it later on in a general rule
603                                                                // Also note ")" this is to catch also (a,b). the "("
604                                                                // is caught in the rule: [(], the ")" will be handled in [)]
605                         if (g_search_count > 1) REJECT;
606                         g_indent=computeIndent(yytext);
607                         current->section   = Entry::VARIABLE_SEC;
608                         current->name      = QCString(yytext).stripWhiteSpace();
609                         current->fileName  = yyFileName;
610                         current->startLine = yyLineNr;
611                         current->bodyLine  = yyLineNr;
612                         g_packageCommentAllowed = FALSE;
613                         newVariable();
614                       }
615      "'"              { // start of a single quoted string
616                         g_stringContext=YY_START;
617                         g_copyString=0;
618                         g_packageCommentAllowed = FALSE;
619                         BEGIN( SingleQuoteString );
620                       }
621      "\""             { // start of a double quoted string
622                         g_stringContext=YY_START;
623                         g_copyString=0;
624                         g_packageCommentAllowed = FALSE;
625                         BEGIN( DoubleQuoteString );
626                       }
627     "@staticmethod"  {
628                         gstat=TRUE;
629                       }
630     {SCRIPTCOMMENT}   { // Unix type script comment
631                         if (yyLineNr != 1) REJECT;
632                       }
633     {POUNDCOMMENT}    { // normal comment 
634                         g_packageCommentAllowed = FALSE;
635                       }
636     {IDENTIFIER}      { // some other identifier
637                         g_packageCommentAllowed = FALSE;
638                       }
639     ^{BB}             {
640                         g_curIndent=computeIndent(yytext);
641                       }
642
643     {NEWLINE}+        { // new line
644                         lineCount();
645                       }
646
647     {TRIDOUBLEQUOTE}  { // start of a comment block
648                         initTriDoubleQuoteBlock();
649                         BEGIN(TripleComment);
650                       }
651
652     {TRISINGLEQUOTE}  { // start of a comment block
653                         initTriSingleQuoteBlock();
654                         BEGIN(TripleComment);
655                       }
656
657     {STARTDOCSYMS}/[^#]    {  // start of a special comment
658                         g_curIndent=computeIndent(yytext);
659                         g_packageCommentAllowed = FALSE;
660                         initSpecialBlock();
661                         BEGIN(SpecialComment);
662                       }
663     [(]               { // we have to do something with (
664                         g_search_count += 1;
665                       }
666     [)]               { // we have to do something with )
667                         g_search_count -= 1;
668                       }
669     [^\n]             { // any other character...
670                         // This is the major default
671                         // that should catch everything
672                         // else in Body.
673                       }
674 }
675
676 <FromMod>{
677   "."                 { // python3 style imports
678                       }
679   {IDENTIFIER}({B}"."{B}{IDENTIFIER})* { // from package import 
680                         g_packageName=yytext;
681                       }
682   "import"{B}         {
683                         BEGIN(FromModItem);
684                       }
685   \n                  {
686                         incLineNr();
687                         BEGIN(Search);
688                       }
689   {B}                 {
690                       }
691   .                   {
692                         unput(*yytext);
693                         BEGIN(Search);
694                       }
695 }
696
697 <FromModItem>{
698   "*"           { // import all
699                   QCString item=g_packageName;
700                   current->name=removeRedundantWhiteSpace(substitute(item,".","::"));
701                   current->fileName = yyFileName; 
702                   //printf("Adding using directive: found:%s:%d name=%s\n",yyFileName.data(),yyLineNr,current->name.data());
703                   current->section=Entry::USINGDIR_SEC;
704                   current_root->addSubEntry(current);
705                   current = new Entry ;
706                   initEntry();
707                   BEGIN(Search);
708                 }
709   {IDENTIFIER}/{B}","{B} {
710                   QCString item=g_packageName+"."+yytext;
711                   current->name=removeRedundantWhiteSpace(substitute(item,".","::"));
712                   current->fileName = yyFileName; 
713                   //printf("Adding using declaration: found:%s:%d name=%s\n",yyFileName.data(),yyLineNr,current->name.data());
714                   current->section=Entry::USINGDECL_SEC;
715                   current_root->addSubEntry(current);
716                   current = new Entry ;
717                   initEntry();
718                 }
719   {IDENTIFIER}  {
720                   QCString item=g_packageName+"."+yytext;
721                   current->name=removeRedundantWhiteSpace(substitute(item,".","::"));
722                   current->fileName = yyFileName; 
723                   //printf("Adding using declaration: found:%s:%d name=%s\n",yyFileName.data(),yyLineNr,current->name.data());
724                   current->section=Entry::USINGDECL_SEC;
725                   current_root->addSubEntry(current);
726                   current = new Entry ;
727                   initEntry();
728                   BEGIN(Search);
729                 }
730   \n            {
731                   incLineNr();
732                   BEGIN(Search);
733                 }
734   {B}           {
735                 }
736   ","           { 
737                 }
738   .             {
739                   unput(*yytext);
740                   BEGIN(Search);
741                 }
742 }
743
744 <Import>{
745   {IDENTIFIER}({B}"."{B}{IDENTIFIER})* {
746                         current->name=removeRedundantWhiteSpace(substitute(yytext,".","::"));
747                         current->fileName = yyFileName; 
748                         //printf("Adding using declaration: found:%s:%d name=%s\n",yyFileName.data(),yyLineNr,current->name.data());
749                         current->section=Entry::USINGDECL_SEC;
750                         current_root->addSubEntry(current);
751                         current = new Entry ;
752                         initEntry();
753                         BEGIN(Search);
754                       }
755   \n            {
756                   incLineNr();
757                   BEGIN(Search);
758                 }
759   {B}           {
760                 }
761   .             {
762                   unput(*yytext);
763                   BEGIN(Search);
764                 }
765 }
766
767 <SearchMemVars>{
768     "self."{IDENTIFIER}/{B}"=" {
769                         DBG_CTX((stderr,"Found instance method variable %s in %s at %d\n",&yytext[5],current_root->name.data(),yyLineNr));
770                         current->name=&yytext[5];
771                         current->section=Entry::VARIABLE_SEC;
772                         current->fileName  = yyFileName;
773                         current->startLine = yyLineNr;
774                         current->bodyLine  = yyLineNr;
775                         current->type.resize(0);
776                         if (current->name.at(0)=='_') // mark as private
777                         {
778                           current->protection=Private;
779                         }
780                         newEntry();
781                       }
782     "cls."{IDENTIFIER}/{B}"=" {
783                         DBG_CTX((stderr,"Found class method variable %s in %s at %d\n",&yytext[4],current_root->name.data(),yyLineNr));
784                         current->name=&yytext[4];
785                         current->section=Entry::VARIABLE_SEC;
786                         current->fileName  = yyFileName;
787                         current->startLine = yyLineNr;
788                         current->bodyLine  = yyLineNr;
789                         current->type.resize(0);
790                         if (current->name.at(0)=='_') // mark as private
791                         {
792                           current->protection=Private;
793                         }
794                         newEntry();
795                       }
796     {TRIDOUBLEQUOTE}  { // start of a comment block
797                         initTriDoubleQuoteBlock();
798                         BEGIN(TripleComment);
799                       }
800
801     {TRISINGLEQUOTE}  { // start of a comment block
802                         initTriSingleQuoteBlock();
803                         BEGIN(TripleComment);
804                       }
805
806     {STARTDOCSYMS}/[^#]    {  // start of a special comment
807                         initSpecialBlock();
808                         BEGIN(SpecialComment);
809                       }
810     {POUNDCOMMENT}    { // #
811                       }
812     "'"               { // start of a single quoted string
813                         g_stringContext=YY_START;
814                         g_copyString=0;
815                         BEGIN( SingleQuoteString );
816                       }
817     "\""              { // start of a double quoted string
818                         g_stringContext=YY_START;
819                         g_copyString=0;
820                         BEGIN( DoubleQuoteString );
821                       }
822     \n                { incLineNr(); }
823     {IDENTIFIER}      // identifiers
824     [^'"\.#a-z_A-Z\n]+  // other uninteresting stuff
825     .                 // anything else
826 }
827
828 <FunctionBody>{
829     \n{B}/{IDENTIFIER}{BB}  {
830                         DBG_CTX((stderr,"indent %d<=%d\n",computeIndent(&yytext[1]),g_indent));
831                         if (computeIndent(&yytext[1])<=g_indent) 
832                         {
833                           int i;
834                           for (i=(int)yyleng-1;i>=0;i--)
835                           {
836                             unput(yytext[i]);
837                           }
838                           endOfDef();
839                           //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
840                           BEGIN(Search);
841                         }
842                         else
843                         {
844                           incLineNr();
845                           current->program+=yytext;
846                         }
847                       }
848     \n{B}/"##"        {
849                         if (computeIndent(&yytext[1])<=g_indent)
850                         {
851                           int i;
852                           for (i=(int)yyleng-1;i>=0;i--)
853                           {
854                             unput(yytext[i]);
855                           }
856                           endOfDef();
857                           //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
858                           BEGIN(Search);
859                         }
860                         else
861                         {
862                           incLineNr();
863                           current->program+=yytext;
864                         }
865                       }
866     <<EOF>>           {
867                         endOfDef();
868                         yyterminate();
869                       }
870     ^{BB}/\n          { // skip empty line
871                         current->program+=yytext;
872                       }
873     ^{BB}             { // something at indent >0
874                         current->program+=yytext;
875                         g_curIndent = computeIndent(yytext);
876                         if (g_curIndent<=g_indent) 
877                           // jumped out of the function
878                         {
879                           endOfDef(1);
880                           BEGIN(Search);
881                         }
882                       }
883     "'"               { // start of a single quoted string
884                         current->program+=yytext;
885                         g_stringContext=YY_START;
886                         g_specialBlock = FALSE; 
887                         g_copyString=&current->program;
888                         BEGIN( SingleQuoteString );
889                       }
890     "\""              { // start of a double quoted string
891                         current->program+=yytext;
892                         g_stringContext=YY_START;
893                         g_specialBlock = FALSE; 
894                         g_copyString=&current->program;
895                         BEGIN( DoubleQuoteString );
896                       }
897     [^ \t\n#'".]+     { // non-special stuff
898                         current->program+=yytext;
899                         g_specialBlock = FALSE; 
900                       }
901     ^{POUNDCOMMENT}   { // normal comment 
902                         current->program+=yytext;
903                       }
904     "#".*             { // comment half way
905                         current->program+=yytext;
906                       }
907     {NEWLINE}         { 
908                         incLineNr(); 
909                         current->program+=yytext;
910                       }
911     .                 { // any character
912                         current->program+=*yytext;
913                         g_specialBlock = FALSE; 
914                       }
915
916     {TRIDOUBLEQUOTE}  { // start of a comment block
917                         current->program+=yytext;
918                         initTriDoubleQuoteBlock();
919                         BEGIN(TripleComment);
920                       }
921
922     {TRISINGLEQUOTE}  { // start of a comment block
923                         current->program+=yytext;
924                         initTriSingleQuoteBlock();
925                         BEGIN(TripleComment);
926                       }
927
928     {STARTDOCSYMS}/[^#]  {  // start of a special comment
929                         initSpecialBlock();
930                         BEGIN(SpecialComment);
931                       }
932     
933 }
934
935 <FunctionDec>{
936
937     {IDENTIFIER}            {
938                               //found function name
939                               if (current->type.isEmpty()) 
940                               {
941                                   current->type = "def";
942                               }
943                               current->name = yytext;
944                               current->name = current->name.stripWhiteSpace();
945                               newFunction();
946                             }
947     {B}":"                  { // function without arguments
948                               g_specialBlock = TRUE; // expecting a docstring
949                               bodyEntry = current;
950                               current->bodyLine  = yyLineNr;
951                               BEGIN( FunctionBody );
952                             }
953
954     {B}"("                  {
955                                BEGIN( FunctionParams );
956                             }
957 }
958
959 <FunctionParams>{
960     ({BB}|",")          {
961                         }
962
963     {IDENTIFIER}        { // Name of parameter
964                           lineCount();
965                           Argument *a = new Argument;
966                           current->argList->append(a);
967                           current->argList->getLast()->name = QCString(yytext).stripWhiteSpace();
968                           current->argList->getLast()->type = "";
969                         }
970     "="                 { // default value
971                           // TODO: this rule is too simple, need to be able to
972                           // match things like =")" as well!
973                           g_defVal.resize(0);
974                           g_braceCount=0;
975                           BEGIN(FunctionParamDefVal);
976                         }
977
978      ")"                { // end of parameter list
979                           current->args = argListToString(current->argList);
980                         }
981
982      ":"{B}             {
983                           g_specialBlock = TRUE; // expecting a docstring
984                           bodyEntry = current;
985                           current->bodyLine  = yyLineNr;
986                           BEGIN( FunctionBody );
987                         }
988     {POUNDCOMMENT}      { // a comment
989                         }
990     {PARAMNONEMPTY}     { // Default rule inside arguments.
991                         }
992
993 }
994
995 <FunctionParamDefVal>{
996      "("                { // internal opening brace
997                           g_braceCount++;
998                           g_defVal+=*yytext;
999                         }
1000      ","                | 
1001      ")"                {
1002                           if (g_braceCount==0)  // end of default argument
1003                           {
1004                             if (current->argList->getLast())
1005                             {
1006                               current->argList->getLast()->defval=g_defVal.stripWhiteSpace();
1007                             }
1008                             if (*yytext == ')')
1009                               current->args = argListToString(current->argList);
1010                             BEGIN(FunctionParams);
1011                           }
1012                           else // continue
1013                           {
1014                             if (*yytext == ')')g_braceCount--;
1015                             g_defVal+=*yytext;
1016                           }
1017                         }
1018      .                  {
1019                             g_defVal+=*yytext;
1020                         }
1021      \n                 {
1022                             g_defVal+=*yytext;
1023                             incLineNr();
1024                         }
1025 }
1026
1027
1028 <ClassBody>{
1029     \n/{IDENTIFIER}{BB}  { // new def at indent 0
1030                         incLineNr();
1031                         endOfDef();
1032                         //g_hideClassDocs = FALSE;
1033                         //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
1034                         BEGIN(Search);
1035                       }
1036     \n/"##"[^#]       {  // start of a special comment at indent 0
1037                         incLineNr();
1038                         endOfDef();
1039                         //g_hideClassDocs = FALSE;
1040                         //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
1041                         BEGIN(Search);
1042                       }
1043     ^{BB}/\n          { // skip empty line
1044                         current->program+=yytext;
1045                       }
1046     <<EOF>>           {
1047                         endOfDef();
1048                         yyterminate();
1049                       }
1050     ^{BB}             { // something at indent >0
1051                         g_curIndent=computeIndent(yytext);
1052                         DBG_CTX((stderr,"g_curIndent=%d g_indent=%d\n",g_curIndent,g_indent));
1053                         if (g_curIndent<=g_indent) 
1054                           // jumped out of the class/method
1055                         {
1056                           endOfDef(1);
1057                           g_indent=g_curIndent;
1058                           // make sure the next rule matches ^...
1059                           //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
1060                           //g_hideClassDocs = FALSE;
1061                           BEGIN(Search);
1062                         }
1063                         else
1064                         {
1065                           current->program+=yytext;
1066                         }
1067                       }
1068     "'"               { // start of a single quoted string
1069                         current->program+=*yytext;
1070                         g_stringContext=YY_START;
1071                         g_specialBlock = FALSE; 
1072                         g_copyString=&current->program;
1073                         BEGIN( SingleQuoteString );
1074                       }
1075     "\""              { // start of a double quoted string
1076                         current->program+=*yytext;
1077                         g_stringContext=YY_START;
1078                         g_specialBlock = FALSE; 
1079                         g_copyString=&current->program;
1080                         BEGIN( DoubleQuoteString );
1081                       }
1082     [^ \t\n#'"]+      { // non-special stuff
1083                         current->program+=yytext;
1084                         g_specialBlock = FALSE; 
1085                         //g_hideClassDocs = FALSE;
1086                       }
1087     {NEWLINE}         { 
1088                         current->program+=*yytext;
1089                         incLineNr(); 
1090                       }
1091     {POUNDCOMMENT}    { // normal comment
1092                         current->program+=yytext;
1093                       }
1094     .                 { // any character
1095                         g_specialBlock = FALSE; 
1096                         current->program+=*yytext;
1097                       }
1098     {TRIDOUBLEQUOTE}  { // start of a comment block
1099                         //if (!g_hideClassDocs) 
1100                         current->program+=yytext;
1101                         initTriDoubleQuoteBlock();
1102                         BEGIN(TripleComment);
1103                       }
1104
1105     {TRISINGLEQUOTE}  { // start of a comment block
1106                         //if (!g_hideClassDocs) 
1107                         current->program+=yytext;
1108                         initTriSingleQuoteBlock();
1109                         BEGIN(TripleComment);
1110                       }
1111 }
1112
1113 <ClassDec>{IDENTIFIER} {
1114                           if (current->type.isEmpty()) 
1115                           {
1116                               current->type = "class";
1117                           }
1118
1119                           current->section = Entry::CLASS_SEC;
1120                           current->name = yytext;
1121
1122                           // prepend scope in case of nested classes
1123                           if (current_root->section&Entry::SCOPE_MASK)
1124                           {
1125                             //printf("*** Prepending scope %s to class %s\n",current_root->name.data(),current->name.data());
1126                             current->name.prepend(current_root->name+"::");
1127                           }
1128                           
1129                           current->name = current->name.stripWhiteSpace();
1130                           current->fileName = yyFileName;        
1131                           docBlockContext   = YY_START;
1132                           docBlockInBody    = FALSE;
1133                           docBlockJavaStyle = FALSE;
1134                           docBlock.resize(0);
1135
1136                           BEGIN(ClassInheritance);                 
1137                         }
1138
1139 <ClassInheritance>{
1140    ({BB}|[\(,\)])      { // syntactic sugar for the list
1141                        }
1142
1143     ":"                { // begin of the class definition
1144                          g_specialBlock = TRUE; // expecting a docstring
1145                          current->bodyLine  = yyLineNr;
1146                          current->program.resize(0);
1147                          BEGIN(ClassCaptureIndent);
1148                        }
1149
1150     {SCOPE}            {
1151                          current->extends->append(
1152                                               new BaseInfo(substitute(yytext,".","::"),Public,Normal)
1153                                             );
1154                          //Has base class-do stuff
1155                        }
1156 }
1157
1158
1159 <ClassCaptureIndent>{
1160     "\n"|({BB}"\n")            {
1161                                  // Blankline - ignore, keep looking for indentation.
1162                                  lineCount();
1163                                  current->program+=yytext;
1164                                }
1165
1166     {TRIDOUBLEQUOTE}           { // start of a comment block
1167                                  initTriDoubleQuoteBlock();
1168                                  current->program+=yytext;
1169                                  BEGIN(TripleComment);
1170                                }
1171
1172     {TRISINGLEQUOTE}           { // start of a comment block
1173                                  initTriSingleQuoteBlock();
1174                                  current->program+=yytext;
1175                                  BEGIN(TripleComment);
1176                                }
1177
1178     ^{BB}                      {
1179                                  current->program+=yytext;
1180                                  //current->startLine = yyLineNr;
1181                                  g_curIndent=computeIndent(yytext);
1182                                  bodyEntry = current;
1183                                  DBG_CTX((stderr,"setting indent %d\n",g_curIndent));
1184                                  //printf("current->program=[%s]\n",current->program.data());
1185                                  //g_hideClassDocs = TRUE;
1186                                  BEGIN(ClassBody);
1187                                }
1188
1189     ""/({NONEMPTY}|{EXPCHAR})  {
1190                                  
1191                                  // Just pushback an empty class, and
1192                                  // resume parsing the body.
1193                                  newEntry();
1194                                  current->program+=yytext;
1195
1196                                  // printf("Failed to find indent - skipping!");
1197                                  BEGIN( Search );
1198                                }
1199 }
1200
1201
1202 <VariableDec>{
1203    "="                { // the assignment operator
1204                         //printf("====== VariableDec at line %d\n",yyLineNr);
1205                         g_start_init = TRUE;
1206                         current->initializer = yytext;
1207                         current->initializer += " ";
1208                       }
1209    {B}                { // spaces
1210                         current->initializer += yytext;
1211                       }
1212    {INTNUMBER}        { // integer value
1213                         if (current-> type.isEmpty()) current->type = "int";
1214                         current->initializer += yytext;
1215                       }
1216    {FLOATNUMBER}      { // floating point value
1217                         if (current->type.isEmpty()) current->type = "float";
1218                         current->initializer += yytext;
1219                       }
1220    {BOOL}             { // boolean value
1221                         if (current->type.isEmpty()) current->type = "bool";
1222                         current->initializer += yytext;
1223                       }
1224    {STRINGPREFIX}?"'" { // string
1225                         if (current->type.isEmpty()) current->type = "string";
1226                         current->initializer += yytext;
1227                         g_copyString=&current->initializer;
1228                         g_stringContext=VariableDec;
1229                         BEGIN( SingleQuoteString );
1230                       }
1231    {STRINGPREFIX}?"\"" { // string
1232                         if (current->type.isEmpty()) current->type = "string";
1233                         current->initializer += yytext;
1234                         g_copyString=&current->initializer;
1235                         g_stringContext=VariableDec;
1236                         BEGIN( DoubleQuoteString );
1237                       }
1238    {TRIDOUBLEQUOTE}   { // start of a comment block
1239                         if (current->type.isEmpty()) current->type = "string";
1240                         current->initializer += yytext;
1241                         g_doubleQuote=TRUE;
1242                         g_copyString=&current->initializer;
1243                         g_stringContext=VariableDec;
1244                         BEGIN(TripleString);
1245                       }
1246
1247    {TRISINGLEQUOTE}   { // start of a comment block
1248                         if (current->type.isEmpty()) current->type = "string";
1249                         current->initializer += yytext;
1250                         g_doubleQuote=FALSE;
1251                         g_copyString=&current->initializer;
1252                         g_stringContext=VariableDec;
1253                         BEGIN(TripleString);
1254                       }
1255    "("                { // tuple, only when direct after =
1256                         if (current->mtype!=Property && g_start_init)
1257                         {
1258                           current->type = "tuple";
1259                         }
1260                         current->initializer+=*yytext;
1261                         g_atomStart='(';
1262                         g_atomEnd=')';
1263                         g_atomCount=1;
1264                         BEGIN( VariableAtom );
1265                       }
1266    "["                { // list
1267                         if (g_start_init) current->type = "list";
1268                         current->initializer+=*yytext;
1269                         g_atomStart='[';
1270                         g_atomEnd=']';
1271                         g_atomCount=1;
1272                         BEGIN( VariableAtom );
1273                       }
1274    "{"                { // dictionary
1275                         if (g_start_init) current->type = "dictionary";
1276                         current->initializer+=*yytext;
1277                         g_atomStart='{';
1278                         g_atomEnd='}';
1279                         g_atomCount=1;
1280                         BEGIN( VariableAtom );
1281                       }
1282    "#".*              { // comment
1283                         BEGIN( VariableEnd ); 
1284                       }
1285    {IDENTIFIER}       {
1286                         // do something based on the type of the IDENTIFIER
1287                         if (current->type.isEmpty())
1288                         {
1289                           QListIterator<Entry> eli(*(current_root->children()));
1290                           Entry *child;
1291                           for (eli.toFirst();(child=eli.current());++eli)
1292                           {
1293                             if (child->name == QCString(yytext))
1294                             {
1295                                current->type = child->type;
1296                                break;
1297                             }
1298                           }
1299                         }
1300                         g_start_init = FALSE;
1301                         current->initializer+=yytext;
1302                       }
1303    .                  {
1304                         g_start_init = FALSE;
1305                         current->initializer+=*yytext;
1306                       }
1307    \n                 {
1308                         unput('\n');
1309                         BEGIN( VariableEnd );
1310                       }
1311 }
1312
1313 <VariableAtom>{
1314     [\(\[\{]          {
1315                         current->initializer+=*yytext;
1316                         if (g_atomStart==*yytext)
1317                         {
1318                           g_atomCount++;
1319                         }
1320                       }
1321     [\)\]\}]          {
1322                         current->initializer+=*yytext;
1323                         if (g_atomEnd==*yytext)
1324                         {
1325                           g_atomCount--;
1326                         }
1327                         if (g_atomCount==0)
1328                         {
1329                           g_start_init = FALSE;
1330                           BEGIN(VariableDec);
1331                         }
1332                       }
1333     {TRIDOUBLEQUOTE}  { // start of a comment block
1334                         g_specialBlock = FALSE;
1335                         current->program+=yytext;
1336                         initTriDoubleQuoteBlock();
1337                         BEGIN(TripleComment);
1338                       }
1339
1340     {TRISINGLEQUOTE}  { // start of a comment block
1341                         g_specialBlock = FALSE;
1342                         current->program+=yytext;
1343                         initTriSingleQuoteBlock();
1344                         BEGIN(TripleComment);
1345                       }
1346    "'"                {
1347                         g_stringContext=YY_START;
1348                         current->initializer+="'";
1349                         g_copyString=&current->initializer;
1350                         BEGIN( SingleQuoteString );
1351                       }
1352    "\""               {
1353                         g_stringContext=YY_START;
1354                         current->initializer+="\"";
1355                         g_copyString=&current->initializer;
1356                         BEGIN( DoubleQuoteString );
1357                       }
1358    {IDENTIFIER}       {
1359                         current->initializer+=yytext;
1360                       }
1361    .                  {
1362                         current->initializer+=*yytext;
1363                       }
1364    \n                 {
1365                         current->initializer+=*yytext;
1366                         incLineNr();
1367                       }
1368
1369 }
1370
1371 <VariableEnd>{
1372     \n                {
1373                         incLineNr();
1374                         newVariable();
1375                         BEGIN(Search);
1376                       }
1377     .                 { 
1378                         unput(*yytext);
1379                         newVariable();
1380                         BEGIN(Search);
1381                       }
1382     <<EOF>>           { yyterminate();
1383                         newEntry();
1384                       }
1385 }
1386
1387 <TripleComment>{
1388     {ENDTRIDOUBLEQUOTE}   | 
1389     {ENDTRISINGLEQUOTE}   {
1390                           // printf("Expected module block %d special=%d\n",g_expectModuleDocs,g_specialBlock);
1391                           if (g_doubleQuote==(yytext[0]=='"')) 
1392                           {
1393                             if (g_specialBlock) // expecting a docstring
1394                             {
1395                               QCString actualDoc=docBlock;
1396                               if (!docBlockSpecial) // legacy unformatted docstring
1397                               {
1398                                 actualDoc.prepend("\\verbatim ");
1399                                 actualDoc.append("\\endverbatim ");
1400                               }
1401                               //printf("-------> current=%p bodyEntry=%p\n",current,bodyEntry);
1402                               handleCommentBlock(actualDoc, FALSE);
1403                             }
1404                             else if (g_packageCommentAllowed) // expecting module docs
1405                             {
1406                               QCString actualDoc=docBlock;
1407                               if (!docBlockSpecial) // legacy unformatted docstring
1408                               {
1409                                 actualDoc.prepend("\\verbatim ");
1410                                 actualDoc.append("\\endverbatim ");
1411                               }
1412                               actualDoc.prepend("\\namespace "+g_moduleScope+"\\_linebr ");
1413                               handleCommentBlock(actualDoc, FALSE);
1414                             }
1415                             if ((docBlockContext==ClassBody /*&& !g_hideClassDocs*/) ||
1416                                 docBlockContext==FunctionBody)
1417                             {
1418                               current->program+=docBlock;
1419                               current->program+=yytext;
1420                             }
1421                             //if (g_hideClassDocs)
1422                             //{
1423                             //  current->startLine = yyLineNr;
1424                             //}
1425                             //g_hideClassDocs=FALSE;
1426                             BEGIN(docBlockContext);
1427                           }
1428                           else 
1429                           {
1430                             docBlock += yytext;
1431                           }
1432                           g_packageCommentAllowed = FALSE;
1433                         }
1434
1435
1436     ^{BB}               { // leading whitespace
1437                           int indent = computeIndent(yytext);
1438                           if (indent>=g_curIndent)
1439                           { // strip g_curIndent amount of whitespace
1440                             int i;
1441                             for (i=0;i<indent-g_curIndent;i++) docBlock+=' ';
1442                             DBG_CTX((stderr,"stripping indent %d\n",g_curIndent));
1443                           }
1444                           else
1445                           {
1446                             DBG_CTX((stderr,"not stripping: %d<%d\n",indent,g_curIndent));
1447                             docBlock += yytext;
1448                           }
1449                         }
1450     [^"'\n \t\\]+       {
1451                           docBlock += yytext;
1452                         }
1453     \n                  {
1454                           incLineNr();
1455                           docBlock += yytext;
1456                         }
1457     \\.                 { // espaced char
1458                           docBlock += yytext;
1459                         }
1460     .                   {
1461                           docBlock += yytext;
1462                         }
1463 }
1464
1465 <SpecialComment>{
1466     ^{B}"#"("#")*       { // skip leading hashes
1467                         }
1468     \n/{B}"#"           { // continuation of the comment on the next line
1469                           docBlock+='\n';
1470                           docBrief = FALSE;
1471                           startCommentBlock(FALSE);
1472                           incLineNr();
1473                         }
1474     [^#\n]+             { // any other stuff
1475                           docBlock+=yytext;
1476                         }
1477     \n                  { // new line that ends the comment
1478                           handleCommentBlock(docBlock, docBrief);
1479                           incLineNr();
1480                           BEGIN(docBlockContext);
1481                         }
1482     .                   { // anything we missed
1483                           docBlock+=*yytext;
1484                         }
1485 }
1486
1487 <SingleQuoteString>{
1488     \\{B}\n                    { // line continuation
1489                                  addToString(yytext);
1490                                  incLineNr();
1491                                }
1492     \\.                        { // espaced char
1493                                  addToString(yytext);
1494                                }
1495     "\"\"\""                   { // tripple double quotes
1496                                  addToString(yytext);
1497                                }
1498     "'"                        { // end of the string
1499                                  addToString(yytext);
1500                                  BEGIN(g_stringContext);
1501                                }
1502     [^"'\n\\]+                 { // normal chars
1503                                  addToString(yytext);
1504                                }
1505     .                          { // normal char
1506                                  addToString(yytext);
1507                                }
1508 }
1509
1510 <DoubleQuoteString>{
1511     \\{B}\n                    { // line continuation
1512                                  addToString(yytext);
1513                                  incLineNr();
1514                                }
1515     \\.                        { // espaced char
1516                                  addToString(yytext);
1517                                }
1518     "'''"                      { // tripple single quotes
1519                                  addToString(yytext);
1520                                }
1521     "\""                       { // end of the string
1522                                  addToString(yytext);
1523                                  BEGIN(g_stringContext);
1524                                }
1525     [^"'\n\\]+                 { // normal chars
1526                                  addToString(yytext);
1527                                }
1528     .                          { // normal char
1529                                  addToString(yytext);
1530                                }
1531 }
1532
1533 <TripleString>{
1534     {ENDTRIDOUBLEQUOTE}    | 
1535     {ENDTRISINGLEQUOTE}    {
1536                           *g_copyString += yytext;
1537                           if (g_doubleQuote==(yytext[0]=='"')) 
1538                           {
1539                             BEGIN(g_stringContext);
1540                           }
1541                         }
1542
1543
1544     ({LONGSTRINGBLOCK}) {
1545                           lineCount();
1546                           *g_copyString += yytext;
1547                         }
1548     \n                  {
1549                           incLineNr();
1550                           *g_copyString += yytext;
1551                         }
1552     .                   {
1553                           *g_copyString += *yytext;
1554                         }
1555 }
1556
1557   /* ------------ End rules -------------- */
1558
1559   /*
1560 <*>({NONEMPTY}|{EXPCHAR}|{BB})           { // This should go one character at a time.
1561                                  // printf("[pyscanner] '%s' [ state %d ]  [line %d] no match\n",
1562                                  //       yytext, YY_START, yyLineNr);
1563
1564                                }
1565   */
1566
1567 <*>{NEWLINE}                   {
1568                                  //printf("[pyscanner] %d NEWLINE [line %d] no match\n",
1569                                  //       YY_START, yyLineNr);
1570
1571                                  lineCount();
1572                                }
1573
1574 <*>.                           {
1575                                  //printf("[pyscanner] '%s' [ state %d ]  [line %d] no match\n",
1576                                  //       yytext, YY_START, yyLineNr);
1577
1578                                }
1579
1580
1581 %%
1582
1583 //----------------------------------------------------------------------------
1584
1585 static void parseCompounds(Entry *rt)
1586 {
1587   //printf("parseCompounds(%s)\n",rt->name.data());
1588   EntryListIterator eli(*rt->children());
1589   Entry *ce;
1590   for (;(ce=eli.current());++eli)
1591   {
1592     if (!ce->program.isEmpty())
1593     {
1594       //printf("-- %s ---------\n%s\n---------------\n",
1595       //  ce->name.data(),ce->program.data());
1596       // init scanner state
1597       inputString = ce->program;
1598       inputPosition = 0;
1599       pyscannerYYrestart( pyscannerYYin ) ;
1600       if (ce->section&Entry::COMPOUND_MASK)
1601       {
1602         current_root = ce ;
1603         BEGIN( Search );
1604       }
1605       else if (ce->parent())
1606       {
1607         current_root = ce->parent();
1608         //printf("Searching for member variables in %s parent=%s\n",
1609         //    ce->name.data(),ce->parent->name.data());
1610         BEGIN( SearchMemVars );
1611       }
1612       yyFileName = ce->fileName;
1613       yyLineNr   = ce->bodyLine ;
1614       if (current) delete current;
1615       current = new Entry;
1616       initEntry();
1617
1618       groupEnterCompound(yyFileName,yyLineNr,ce->name);
1619       
1620       pyscannerYYlex() ;
1621       g_lexInit=TRUE;
1622       delete current; current=0;
1623       ce->program.resize(0);
1624
1625       groupLeaveCompound(yyFileName,yyLineNr,ce->name);
1626
1627     }
1628     parseCompounds(ce);
1629   }
1630 }
1631
1632 //----------------------------------------------------------------------------
1633
1634
1635 static void parseMain(const char *fileName,const char *fileBuf,Entry *rt)
1636 {
1637   initParser();
1638
1639   inputString = fileBuf;
1640   inputPosition = 0;
1641
1642   protection    = Public;
1643   mtype         = Method;
1644   gstat         = FALSE;
1645   virt          = Normal;
1646   current_root  = rt;
1647   g_specialBlock = FALSE;
1648
1649
1650   inputFile.setName(fileName);
1651   if (inputFile.open(IO_ReadOnly))
1652   {
1653     yyLineNr= 1 ; 
1654     yyFileName = fileName;
1655     //setContext();
1656     msg("Parsing file %s...\n",yyFileName.data());
1657
1658     QFileInfo fi(fileName);
1659     g_moduleScope = findPackageScope(fileName);
1660     QCString baseName=fi.baseName().utf8();
1661     if (baseName!="__init__") // package initializer file is not a package itself
1662     {
1663       if (!g_moduleScope.isEmpty())
1664       {
1665         g_moduleScope+="::";
1666       }
1667       g_moduleScope+=baseName;
1668     }
1669
1670     current            = new Entry;
1671     initEntry();
1672     current->name      = g_moduleScope;
1673     current->section   = Entry::NAMESPACE_SEC;
1674     current->type      = "namespace";
1675     current->fileName  = yyFileName;
1676     current->startLine = yyLineNr;
1677     current->bodyLine  = yyLineNr;
1678
1679     rt->addSubEntry(current);
1680
1681     current_root  = current ;
1682     initParser();
1683     current       = new Entry;
1684
1685     groupEnterFile(yyFileName,yyLineNr);
1686     
1687     current->reset();
1688     initEntry();
1689     pyscannerYYrestart( pyscannerYYin );
1690     BEGIN( Search );
1691     pyscannerYYlex();
1692     g_lexInit=TRUE;
1693
1694     groupLeaveFile(yyFileName,yyLineNr);
1695
1696     current_root->program.resize(0);
1697     delete current; current=0;
1698
1699     parseCompounds(current_root);
1700
1701     inputFile.close();
1702   }
1703   
1704 }
1705
1706 //----------------------------------------------------------------------------
1707
1708 static void parsePrototype(const QCString &text)
1709 {
1710   //printf("**** parsePrototype(%s) begin\n",text.data());
1711   if (text.isEmpty()) 
1712   {
1713     warn(yyFileName,yyLineNr,"Empty prototype found!");
1714     return;
1715   }
1716
1717   g_specialBlock = FALSE;
1718   g_packageCommentAllowed = FALSE;
1719
1720   const char *orgInputString;
1721   int orgInputPosition;
1722   YY_BUFFER_STATE orgState;
1723   
1724   // save scanner state
1725   orgState = YY_CURRENT_BUFFER;
1726   yy_switch_to_buffer(yy_create_buffer(pyscannerYYin, YY_BUF_SIZE));
1727   orgInputString = inputString; 
1728   orgInputPosition = inputPosition;
1729
1730   // set new string
1731   inputString = text;
1732   inputPosition = 0;
1733   pyscannerYYrestart( pyscannerYYin );
1734
1735   BEGIN( FunctionDec );
1736
1737   pyscannerYYlex();
1738   g_lexInit=TRUE;
1739
1740   current->name = current->name.stripWhiteSpace();
1741   if (current->section == Entry::MEMBERDOC_SEC && current->args.isEmpty())
1742     current->section = Entry::VARIABLEDOC_SEC;
1743
1744   // restore original scanner state
1745
1746   YY_BUFFER_STATE tmpBuf = YY_CURRENT_BUFFER;
1747   yy_switch_to_buffer(orgState);
1748   yy_delete_buffer(tmpBuf);
1749
1750   inputString = orgInputString; 
1751   inputPosition = orgInputPosition;
1752
1753   //printf("**** parsePrototype end\n");
1754 }
1755
1756 void pyscanFreeScanner()
1757 {
1758 #if defined(YY_FLEX_SUBMINOR_VERSION) 
1759   if (g_lexInit)
1760   {
1761     pyscannerYYlex_destroy();
1762   }
1763 #endif
1764 }
1765
1766 //----------------------------------------------------------------------------
1767
1768 void PythonLanguageScanner::parseInput(const char *fileName,
1769                                        const char *fileBuf,
1770                                        Entry *root,
1771                                        bool /*sameTranslationUnit*/,
1772                                        QStrList & /*filesInSameTranslationUnit*/)
1773 {
1774   g_thisParser = this;
1775   printlex(yy_flex_debug, TRUE, __FILE__, fileName);
1776   ::parseMain(fileName,fileBuf,root);
1777   printlex(yy_flex_debug, FALSE, __FILE__, fileName);
1778
1779   // May print the AST for debugging purposes
1780   // printAST(global_root);
1781 }
1782
1783 bool PythonLanguageScanner::needsPreprocessing(const QCString &)
1784 {
1785   return FALSE;
1786 }
1787
1788 void PythonLanguageScanner::parseCode(CodeOutputInterface &codeOutIntf,
1789     const char *scopeName,
1790     const QCString &input,
1791     SrcLangExt /*lang*/,
1792     bool isExampleBlock,
1793     const char *exampleName,
1794     FileDef *fileDef,
1795     int startLine,
1796     int endLine,
1797     bool inlineFragment,
1798     MemberDef *memberDef,
1799     bool showLineNumbers,
1800     Definition *searchCtx,
1801     bool collectXRefs
1802     )
1803 {
1804   ::parsePythonCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName,
1805                     fileDef,startLine,endLine,inlineFragment,memberDef,
1806                     showLineNumbers,searchCtx,collectXRefs);
1807 }
1808
1809 void PythonLanguageScanner::parsePrototype(const char *text)
1810 {
1811   ::parsePrototype(text);
1812
1813 }
1814
1815 void PythonLanguageScanner::resetCodeParserState()
1816 {
1817   ::resetPythonCodeParserState();
1818 }
1819
1820 //----------------------------------------------------------------------------
1821
1822 #if !defined(YY_FLEX_SUBMINOR_VERSION) 
1823 //----------------------------------------------------------------------------
1824 extern "C" { // some bogus code to keep the compiler happy
1825   void pyscannerYYdummy() { yy_flex_realloc(0,0); } 
1826 }
1827 #endif
1828