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