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