Blame src/pycode.l

Packit 1c1d7e
/******************************************************************************
Packit 1c1d7e
 *
Packit 1c1d7e
 * 
Packit 1c1d7e
 *
Packit 1c1d7e
 * Copyright (C) 1997-2015 by Dimitri van Heesch.
Packit 1c1d7e
 *
Packit 1c1d7e
 * Permission to use, copy, modify, and distribute this software and its
Packit 1c1d7e
 * documentation under the terms of the GNU General Public License is hereby 
Packit 1c1d7e
 * granted. No representations are made about the suitability of this software 
Packit 1c1d7e
 * for any purpose. It is provided "as is" without express or implied warranty.
Packit 1c1d7e
 * See the GNU General Public License for more details.
Packit 1c1d7e
 *
Packit 1c1d7e
 * Documents produced by Doxygen are derivative works derived from the
Packit 1c1d7e
 * input used in their production; they are not affected by this license.
Packit 1c1d7e
 *
Packit 1c1d7e
 */
Packit 1c1d7e
/*  This code is based on the work done by the MoxyPyDoxy team
Packit 1c1d7e
 *  (Linda Leong, Mike Rivera, Kim Truong, and Gabriel Estrada)
Packit 1c1d7e
 *  in Spring 2005 as part of CS 179E: Compiler Design Project
Packit 1c1d7e
 *  at the University of California, Riverside; the course was
Packit 1c1d7e
 *  taught by Peter H. Froehlich <phf@acm.org>.
Packit 1c1d7e
 */
Packit 1c1d7e
Packit 1c1d7e
%option never-interactive
Packit 1c1d7e
%option prefix="pycodeYY"
Packit 1c1d7e
Packit 1c1d7e
%{
Packit 1c1d7e
Packit 1c1d7e
#include <stdio.h>
Packit 1c1d7e
#include <qvaluestack.h>
Packit 1c1d7e
Packit 1c1d7e
#include "pycode.h"
Packit 1c1d7e
#include "message.h"
Packit 1c1d7e
Packit 1c1d7e
#include "scanner.h"
Packit 1c1d7e
#include "entry.h"
Packit 1c1d7e
#include "doxygen.h"
Packit 1c1d7e
#include "outputlist.h"
Packit 1c1d7e
#include "util.h"
Packit 1c1d7e
#include "membername.h"
Packit 1c1d7e
#include "searchindex.h"
Packit 1c1d7e
#include "config.h"
Packit 1c1d7e
#include "groupdef.h"
Packit 1c1d7e
#include "classlist.h"
Packit 1c1d7e
#include "filedef.h"
Packit 1c1d7e
#include "namespacedef.h"
Packit 1c1d7e
#include "tooltip.h"
Packit 1c1d7e
Packit 1c1d7e
// Toggle for some debugging info
Packit 1c1d7e
//#define DBG_CTX(x) fprintf x
Packit 1c1d7e
#define DBG_CTX(x) do { } while(0)
Packit 1c1d7e
Packit 1c1d7e
#define YY_NO_INPUT 1
Packit 1c1d7e
#define YY_NO_UNISTD_H 1
Packit 1c1d7e
Packit 1c1d7e
static ClassSDict    g_codeClassSDict(17);
Packit 1c1d7e
static QCString      g_curClassName;
Packit 1c1d7e
static QStrList      g_curClassBases;
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
static CodeOutputInterface * g_code;
Packit 1c1d7e
static const char *  g_inputString;     //!< the code fragment as text
Packit 1c1d7e
static int	     g_inputPosition;   //!< read offset during parsing 
Packit 1c1d7e
static const char *  g_currentFontClass;
Packit 1c1d7e
static bool          g_needsTermination;
Packit 1c1d7e
static Definition   *g_searchCtx;
Packit 1c1d7e
static bool          g_collectXRefs;
Packit 1c1d7e
static int           g_inputLines;      //!< number of line in the code fragment
Packit 1c1d7e
static int	     g_yyLineNr;        //!< current line number
Packit 1c1d7e
static FileDef *     g_sourceFileDef;
Packit 1c1d7e
static Definition *  g_currentDefinition;
Packit 1c1d7e
static MemberDef *   g_currentMemberDef;
Packit 1c1d7e
static bool          g_includeCodeFragment;
Packit 1c1d7e
static QCString      g_realScope;
Packit 1c1d7e
//static bool          g_insideBody;
Packit 1c1d7e
static int           g_bodyCurlyCount;
Packit 1c1d7e
static bool          g_searchingForBody;
Packit 1c1d7e
static QCString      g_classScope;
Packit 1c1d7e
static int           g_paramParens;
Packit 1c1d7e
//static int           g_anchorCount;
Packit 1c1d7e
Packit 1c1d7e
static bool          g_exampleBlock;
Packit 1c1d7e
static QCString      g_exampleName;
Packit 1c1d7e
Packit 1c1d7e
static QCString      g_type;
Packit 1c1d7e
static QCString      g_name;
Packit 1c1d7e
Packit 1c1d7e
static bool          g_doubleStringIsDoc;
Packit 1c1d7e
static bool          g_doubleQuote;
Packit 1c1d7e
static bool          g_noSuiteFound;
Packit 1c1d7e
static int           g_stringContext;
Packit 1c1d7e
Packit 1c1d7e
static QValueStack<uint> g_indents;  //!< Tracks indentation levels for scoping in python
Packit 1c1d7e
Packit 1c1d7e
static QCString      g_docBlock;     //!< contents of all lines of a documentation block
Packit 1c1d7e
static bool          g_endComment;
Packit 1c1d7e
Packit 1c1d7e
static void endFontClass();
Packit 1c1d7e
static void adjustScopesAndSuites(unsigned indentLength);
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*! Represents a stack of variable to class mappings as found in the
Packit 1c1d7e
 *  code. Each scope is enclosed in pushScope() and popScope() calls.
Packit 1c1d7e
 *  Variables are added by calling addVariables() and one can search
Packit 1c1d7e
 *  for variable using findVariable().
Packit 1c1d7e
 */
Packit 1c1d7e
class PyVariableContext 
Packit 1c1d7e
{
Packit 1c1d7e
  public:
Packit 1c1d7e
    static const ClassDef *dummyContext;    
Packit 1c1d7e
    class Scope : public SDict<ClassDef> 
Packit 1c1d7e
    {
Packit 1c1d7e
      public:
Packit 1c1d7e
	Scope() : SDict<ClassDef>(17) {}
Packit 1c1d7e
    };
Packit 1c1d7e
    
Packit 1c1d7e
    PyVariableContext() 
Packit 1c1d7e
    {
Packit 1c1d7e
      m_scopes.setAutoDelete(TRUE);
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    virtual ~PyVariableContext() 
Packit 1c1d7e
    {
Packit 1c1d7e
    }
Packit 1c1d7e
    
Packit 1c1d7e
    void pushScope() 
Packit 1c1d7e
    {
Packit 1c1d7e
      m_scopes.append(new Scope);
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    void popScope() 
Packit 1c1d7e
    {
Packit 1c1d7e
      if (m_scopes.count()>0) 
Packit 1c1d7e
      {
Packit 1c1d7e
	m_scopes.remove(m_scopes.count()-1);
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    void clear() 
Packit 1c1d7e
    {
Packit 1c1d7e
      m_scopes.clear();
Packit 1c1d7e
      m_globalScope.clear();
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    void clearExceptGlobal() 
Packit 1c1d7e
    {
Packit 1c1d7e
      m_scopes.clear();
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    void addVariable(const QCString &type,const QCString &name);
Packit 1c1d7e
    ClassDef *findVariable(const QCString &name);
Packit 1c1d7e
    
Packit 1c1d7e
  private:
Packit 1c1d7e
    Scope        m_globalScope;
Packit 1c1d7e
    QList<Scope> m_scopes;
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
void PyVariableContext::addVariable(const QCString &type,const QCString &name)
Packit 1c1d7e
{
Packit 1c1d7e
  //printf("PyVariableContext::addVariable(%s,%s)\n",type.data(),name.data());
Packit 1c1d7e
  QCString ltype = type.simplifyWhiteSpace();
Packit 1c1d7e
  QCString lname = name.simplifyWhiteSpace();
Packit 1c1d7e
Packit 1c1d7e
  Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast();
Packit 1c1d7e
  ClassDef *varType;
Packit 1c1d7e
  if (
Packit 1c1d7e
      (varType=g_codeClassSDict[ltype]) ||  // look for class definitions inside the code block
Packit 1c1d7e
      (varType=getResolvedClass(g_currentDefinition,g_sourceFileDef,ltype)) // look for global class definitions
Packit 1c1d7e
     ) 
Packit 1c1d7e
  {
Packit 1c1d7e
    scope->append(lname,varType); // add it to a list
Packit 1c1d7e
  }
Packit 1c1d7e
  else 
Packit 1c1d7e
  {
Packit 1c1d7e
    if (m_scopes.count()>0) // for local variables add a dummy entry so the name 
Packit 1c1d7e
                            // is hidden to avoid FALSE links to global variables with the same name
Packit 1c1d7e
                            // TODO: make this work for namespaces as well!
Packit 1c1d7e
    {
Packit 1c1d7e
      scope->append(lname,dummyContext);
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
ClassDef *PyVariableContext::findVariable(const QCString &name)
Packit 1c1d7e
{
Packit 1c1d7e
  if (name.isEmpty()) return 0;
Packit 1c1d7e
  ClassDef *result = 0;
Packit 1c1d7e
  QListIterator<Scope> sli(m_scopes);
Packit 1c1d7e
  Scope *scope;
Packit 1c1d7e
  // search from inner to outer scope
Packit 1c1d7e
  for (sli.toLast();(scope=sli.current());--sli)
Packit 1c1d7e
  {
Packit 1c1d7e
    result = scope->find(name);
Packit 1c1d7e
    if (result) 
Packit 1c1d7e
    {
Packit 1c1d7e
      return result;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  // nothing found -> also try the global scope
Packit 1c1d7e
  result=m_globalScope.find(name);
Packit 1c1d7e
  return result;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static PyVariableContext g_theVarContext;
Packit 1c1d7e
const ClassDef *PyVariableContext::dummyContext = (ClassDef*)0x8;
Packit 1c1d7e
Packit 1c1d7e
class PyCallContext
Packit 1c1d7e
{
Packit 1c1d7e
  public:
Packit 1c1d7e
    struct Ctx
Packit 1c1d7e
    {
Packit 1c1d7e
      Ctx() : name(g_name), type(g_type), cd(0) {}
Packit 1c1d7e
      QCString name;
Packit 1c1d7e
      QCString type;
Packit 1c1d7e
      ClassDef *cd;
Packit 1c1d7e
    };
Packit 1c1d7e
Packit 1c1d7e
    PyCallContext() 
Packit 1c1d7e
    {
Packit 1c1d7e
      m_classList.append(new Ctx);
Packit 1c1d7e
      m_classList.setAutoDelete(TRUE);
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    virtual ~PyCallContext() {}
Packit 1c1d7e
Packit 1c1d7e
    void setClass(ClassDef *cd)
Packit 1c1d7e
    {
Packit 1c1d7e
      Ctx *ctx = m_classList.getLast();
Packit 1c1d7e
      if (ctx) 
Packit 1c1d7e
      {
Packit 1c1d7e
        ctx->cd=cd;
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
    void pushScope()
Packit 1c1d7e
    {
Packit 1c1d7e
      m_classList.append(new Ctx);
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    void popScope()
Packit 1c1d7e
    {
Packit 1c1d7e
      if (m_classList.count()>1)
Packit 1c1d7e
      {
Packit 1c1d7e
	Ctx *ctx = m_classList.getLast();
Packit 1c1d7e
	if (ctx)
Packit 1c1d7e
	{
Packit 1c1d7e
	  g_name = ctx->name;
Packit 1c1d7e
	  g_type = ctx->type;
Packit 1c1d7e
	}
Packit 1c1d7e
	m_classList.removeLast();
Packit 1c1d7e
      }
Packit 1c1d7e
      else
Packit 1c1d7e
      {
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    void clear()
Packit 1c1d7e
    {
Packit 1c1d7e
      m_classList.clear();
Packit 1c1d7e
      m_classList.append(new Ctx);
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    ClassDef *getClass() const
Packit 1c1d7e
    {
Packit 1c1d7e
      Ctx *ctx = m_classList.getLast();
Packit 1c1d7e
Packit 1c1d7e
      if (ctx)
Packit 1c1d7e
        return ctx->cd;
Packit 1c1d7e
      else
Packit 1c1d7e
        return 0;
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
  private:
Packit 1c1d7e
    QList<Ctx> m_classList;    
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
static PyCallContext g_theCallContext;
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*! counts the number of lines in the input */
Packit 1c1d7e
static int countLines()
Packit 1c1d7e
{
Packit 1c1d7e
  const char *p=g_inputString;
Packit 1c1d7e
  char c;
Packit 1c1d7e
  int count=1;
Packit 1c1d7e
  while ((c=*p)) 
Packit 1c1d7e
  { 
Packit 1c1d7e
    p++ ; 
Packit 1c1d7e
    if (c=='\n') count++;  
Packit 1c1d7e
  }
Packit 1c1d7e
  if (p>g_inputString && *(p-1)!='\n') 
Packit 1c1d7e
  { // last line does not end with a \n, so we add an extra
Packit 1c1d7e
    // line and explicitly terminate the line after parsing.
Packit 1c1d7e
    count++, 
Packit 1c1d7e
    g_needsTermination=TRUE; 
Packit 1c1d7e
  } 
Packit 1c1d7e
  return count;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void setCurrentDoc(const QCString &anchor)
Packit 1c1d7e
{
Packit 1c1d7e
  if (Doxygen::searchIndex)
Packit 1c1d7e
  {
Packit 1c1d7e
    if (g_searchCtx)
Packit 1c1d7e
    {
Packit 1c1d7e
      Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE);
Packit 1c1d7e
    }
Packit 1c1d7e
    else
Packit 1c1d7e
    {
Packit 1c1d7e
      Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE);
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void addToSearchIndex(const char *text)
Packit 1c1d7e
{
Packit 1c1d7e
  if (Doxygen::searchIndex)
Packit 1c1d7e
  {
Packit 1c1d7e
    Doxygen::searchIndex->addWord(text,FALSE);
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition)
Packit 1c1d7e
{
Packit 1c1d7e
  int pos=0;
Packit 1c1d7e
  QCString type = s;
Packit 1c1d7e
  QCString className;
Packit 1c1d7e
  QCString templSpec;
Packit 1c1d7e
  while (extractClassNameFromType(type,pos,className,templSpec)!=-1)
Packit 1c1d7e
  {
Packit 1c1d7e
    QCString clName=className+templSpec;
Packit 1c1d7e
Packit 1c1d7e
    ClassDef *cd=0;
Packit 1c1d7e
    if (!g_classScope.isEmpty())
Packit 1c1d7e
    {
Packit 1c1d7e
      cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName);
Packit 1c1d7e
    }
Packit 1c1d7e
    if (cd==0)
Packit 1c1d7e
    {
Packit 1c1d7e
      cd=getResolvedClass(d,g_sourceFileDef,clName);
Packit 1c1d7e
    }
Packit 1c1d7e
    if (cd)
Packit 1c1d7e
    {
Packit 1c1d7e
      return cd;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  return 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*! start a new line of code, inserting a line number if g_sourceFileDef
Packit 1c1d7e
 * is TRUE. If a definition starts at the current line, then the line
Packit 1c1d7e
 * number is linked to the documentation of that definition.
Packit 1c1d7e
 */
Packit 1c1d7e
static void startCodeLine()
Packit 1c1d7e
{
Packit 1c1d7e
  //if (g_currentFontClass) { g_code->endFontClass(); }
Packit 1c1d7e
  if (g_sourceFileDef)
Packit 1c1d7e
  {
Packit 1c1d7e
    //QCString lineNumber,lineAnchor;
Packit 1c1d7e
    //lineNumber.sprintf("%05d",g_yyLineNr);
Packit 1c1d7e
    //lineAnchor.sprintf("l%05d",g_yyLineNr);
Packit 1c1d7e
   
Packit 1c1d7e
    Definition *d   = g_sourceFileDef->getSourceDefinition(g_yyLineNr);
Packit 1c1d7e
    //printf("startCodeLine %d d=%p\n",g_yyLineNr,d);
Packit 1c1d7e
    //g_code->startLineNumber();
Packit 1c1d7e
Packit 1c1d7e
    if (!g_includeCodeFragment && d && d->isLinkableInProject())
Packit 1c1d7e
    {
Packit 1c1d7e
      g_currentDefinition = d;
Packit 1c1d7e
      g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr);
Packit 1c1d7e
      //g_insideBody = FALSE;
Packit 1c1d7e
      g_endComment = FALSE;
Packit 1c1d7e
      g_searchingForBody = TRUE;
Packit 1c1d7e
      g_realScope = d->name().copy();
Packit 1c1d7e
      g_classScope = d->name().copy();
Packit 1c1d7e
      //printf("Real scope: `%s'\n",g_realScope.data());
Packit 1c1d7e
      g_bodyCurlyCount = 0;
Packit 1c1d7e
      QCString lineAnchor;
Packit 1c1d7e
      lineAnchor.sprintf("l%05d",g_yyLineNr);
Packit 1c1d7e
      if (g_currentMemberDef)
Packit 1c1d7e
      {
Packit 1c1d7e
        g_code->writeLineNumber(g_currentMemberDef->getReference(),
Packit 1c1d7e
	                        g_currentMemberDef->getOutputFileBase(),
Packit 1c1d7e
	                        g_currentMemberDef->anchor(),g_yyLineNr);
Packit 1c1d7e
        setCurrentDoc(lineAnchor);
Packit 1c1d7e
      }
Packit 1c1d7e
      else
Packit 1c1d7e
      {
Packit 1c1d7e
        g_code->writeLineNumber(d->getReference(),
Packit 1c1d7e
	                        d->getOutputFileBase(),
Packit 1c1d7e
	                        0,g_yyLineNr);
Packit 1c1d7e
        setCurrentDoc(lineAnchor);
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
    else
Packit 1c1d7e
    {
Packit 1c1d7e
      //g_code->codify(lineNumber);
Packit 1c1d7e
      g_code->writeLineNumber(0,0,0,g_yyLineNr);
Packit 1c1d7e
    }
Packit 1c1d7e
    //g_code->endLineNumber();
Packit 1c1d7e
  }
Packit 1c1d7e
  g_code->startCodeLine(g_sourceFileDef); 
Packit 1c1d7e
  if (g_currentFontClass)
Packit 1c1d7e
  {
Packit 1c1d7e
    g_code->startFontClass(g_currentFontClass);
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void codify(const char* text) 
Packit 1c1d7e
{ 
Packit 1c1d7e
  g_code->codify(text);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void endCodeLine()
Packit 1c1d7e
{
Packit 1c1d7e
  endFontClass();
Packit 1c1d7e
  g_code->endCodeLine();
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void nextCodeLine()
Packit 1c1d7e
{
Packit 1c1d7e
  const char *fc = g_currentFontClass;
Packit 1c1d7e
  endCodeLine();
Packit 1c1d7e
  if (g_yyLineNr
Packit 1c1d7e
  {
Packit 1c1d7e
    g_currentFontClass = fc;
Packit 1c1d7e
    startCodeLine();
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*! writes a link to a fragment \a text that may span multiple lines, inserting
Packit 1c1d7e
 * line numbers for each line. If \a text contains newlines, the link will be 
Packit 1c1d7e
 * split into multiple links with the same destination, one for each line.
Packit 1c1d7e
 */
Packit 1c1d7e
static void writeMultiLineCodeLink(CodeOutputInterface &ol,
Packit 1c1d7e
                  Definition *d,
Packit 1c1d7e
                  const char *text)
Packit 1c1d7e
{
Packit 1c1d7e
  static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS);
Packit 1c1d7e
  TooltipManager::instance()->addTooltip(d);
Packit 1c1d7e
  QCString ref  = d->getReference();
Packit 1c1d7e
  QCString file = d->getOutputFileBase();
Packit 1c1d7e
  QCString anchor = d->anchor();
Packit 1c1d7e
  QCString tooltip; 
Packit 1c1d7e
  if (!sourceTooltips) // fall back to simple "title" tooltips
Packit 1c1d7e
  {
Packit 1c1d7e
    tooltip = d->briefDescriptionAsTooltip();
Packit 1c1d7e
  }
Packit 1c1d7e
  bool done=FALSE;
Packit 1c1d7e
  char *p=(char *)text;
Packit 1c1d7e
  while (!done)
Packit 1c1d7e
  {
Packit 1c1d7e
    char *sp=p;
Packit 1c1d7e
    char c;
Packit 1c1d7e
    while ((c=*p++) && c!='\n') { }
Packit 1c1d7e
    if (c=='\n')
Packit 1c1d7e
    {
Packit 1c1d7e
      g_yyLineNr++;
Packit 1c1d7e
      *(p-1)='\0';
Packit 1c1d7e
      //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
Packit 1c1d7e
      ol.writeCodeLink(ref,file,anchor,sp,tooltip);
Packit 1c1d7e
      nextCodeLine();
Packit 1c1d7e
    }
Packit 1c1d7e
    else
Packit 1c1d7e
    {
Packit 1c1d7e
      //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
Packit 1c1d7e
      ol.writeCodeLink(ref,file,anchor,sp,tooltip);
Packit 1c1d7e
      done=TRUE;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void startFontClass(const char *s)
Packit 1c1d7e
{
Packit 1c1d7e
  // if font class is already set don't stop and start it.
Packit 1c1d7e
  // strcmp does not like null pointers as input.
Packit 1c1d7e
  if (!g_currentFontClass || !s || strcmp(g_currentFontClass,s))
Packit 1c1d7e
  {
Packit 1c1d7e
    endFontClass();
Packit 1c1d7e
    g_code->startFontClass(s);
Packit 1c1d7e
    g_currentFontClass=s;
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void endFontClass()
Packit 1c1d7e
{
Packit 1c1d7e
  if (g_currentFontClass)
Packit 1c1d7e
  {
Packit 1c1d7e
    g_code->endFontClass();
Packit 1c1d7e
    g_currentFontClass=0;
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void codifyLines(char *text)
Packit 1c1d7e
{
Packit 1c1d7e
  //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text);
Packit 1c1d7e
  char *p=text,*sp=p;
Packit 1c1d7e
  char c;
Packit 1c1d7e
  bool done=FALSE;
Packit 1c1d7e
  const char *  tmp_currentFontClass = g_currentFontClass;
Packit 1c1d7e
  while (!done)
Packit 1c1d7e
  {
Packit 1c1d7e
    sp=p;
Packit 1c1d7e
    while ((c=*p++) && c!='\n') { }
Packit 1c1d7e
    if (c=='\n')
Packit 1c1d7e
    {
Packit 1c1d7e
      g_yyLineNr++;
Packit 1c1d7e
      *(p-1)='\0';
Packit 1c1d7e
      g_code->codify(sp);
Packit 1c1d7e
      endCodeLine();
Packit 1c1d7e
      if (g_yyLineNr
Packit 1c1d7e
      {
Packit 1c1d7e
        startCodeLine();
Packit 1c1d7e
      }
Packit 1c1d7e
      if (tmp_currentFontClass)
Packit 1c1d7e
      {
Packit 1c1d7e
        startFontClass(tmp_currentFontClass);
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
    else
Packit 1c1d7e
    {
Packit 1c1d7e
      g_code->codify(sp);
Packit 1c1d7e
      done=TRUE;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void codifyLines(const QCString &str)
Packit 1c1d7e
{
Packit 1c1d7e
  char *tmp= (char *)malloc(str.length()+1);
Packit 1c1d7e
  qstrcpy(tmp, str);
Packit 1c1d7e
  codifyLines(tmp);
Packit 1c1d7e
  free(tmp);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static bool getLinkInScope(const QCString &c,  // scope
Packit 1c1d7e
                           const QCString &m,  // member
Packit 1c1d7e
			   const char *memberText, // exact text
Packit 1c1d7e
			   CodeOutputInterface &ol,
Packit 1c1d7e
			   const char *text
Packit 1c1d7e
			  )
Packit 1c1d7e
{
Packit 1c1d7e
  MemberDef    *md;
Packit 1c1d7e
  ClassDef     *cd;
Packit 1c1d7e
  FileDef      *fd;
Packit 1c1d7e
  NamespaceDef *nd;
Packit 1c1d7e
  GroupDef     *gd;
Packit 1c1d7e
  //printf("Trying `%s'::`%s'\n",c.data(),m.data());
Packit 1c1d7e
  if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef) && 
Packit 1c1d7e
      md->isLinkable())
Packit 1c1d7e
  {
Packit 1c1d7e
    //Definition *d=0;
Packit 1c1d7e
    //if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd;
Packit 1c1d7e
Packit 1c1d7e
    Definition *d = md->getOuterScope()==Doxygen::globalScope ?
Packit 1c1d7e
	            md->getBodyDef() : md->getOuterScope();
Packit 1c1d7e
    //printf("Found! d=%s\n",d?d->name().data():"<none>");
Packit 1c1d7e
    if (md->getGroupDef()) d = md->getGroupDef();
Packit 1c1d7e
    if (d && d->isLinkable())
Packit 1c1d7e
    {
Packit 1c1d7e
      g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
Packit 1c1d7e
      //printf("g_currentDefinition=%p g_currentMemberDef=%p\n",
Packit 1c1d7e
      //        g_currentDefinition,g_currentMemberDef);
Packit 1c1d7e
Packit 1c1d7e
      if (g_currentDefinition && g_currentMemberDef &&
Packit 1c1d7e
	  md!=g_currentMemberDef && g_collectXRefs)
Packit 1c1d7e
      {
Packit 1c1d7e
	addDocCrossReference(g_currentMemberDef,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      //printf("d->getReference()=`%s' d->getOutputBase()=`%s' name=`%s' member name=`%s'\n",d->getReference().data(),d->getOutputFileBase().data(),d->name().data(),md->name().data());
Packit 1c1d7e
     
Packit 1c1d7e
      writeMultiLineCodeLink(ol,md, text ? text : memberText);
Packit 1c1d7e
      addToSearchIndex(text ? text : memberText);
Packit 1c1d7e
      return TRUE;
Packit 1c1d7e
    } 
Packit 1c1d7e
  }
Packit 1c1d7e
  return FALSE;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static bool getLink(const char *className,
Packit 1c1d7e
                    const char *memberName,
Packit 1c1d7e
		    CodeOutputInterface &ol,
Packit 1c1d7e
		    const char *text=0)
Packit 1c1d7e
{
Packit 1c1d7e
  QCString m=removeRedundantWhiteSpace(memberName);
Packit 1c1d7e
  QCString c=className;
Packit 1c1d7e
  if (!getLinkInScope(c,m,memberName,ol,text))
Packit 1c1d7e
  {
Packit 1c1d7e
    if (!g_curClassName.isEmpty())
Packit 1c1d7e
    {
Packit 1c1d7e
      if (!c.isEmpty()) c.prepend("::");
Packit 1c1d7e
      c.prepend(g_curClassName);
Packit 1c1d7e
      return getLinkInScope(c,m,memberName,ol,text);
Packit 1c1d7e
    }
Packit 1c1d7e
    return FALSE;
Packit 1c1d7e
  }
Packit 1c1d7e
  return TRUE;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*
Packit 1c1d7e
  For a given string in the source code,
Packit 1c1d7e
  finds its class or global id and links to it.
Packit 1c1d7e
*/
Packit 1c1d7e
static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
Packit 1c1d7e
                                      bool typeOnly=FALSE)
Packit 1c1d7e
{
Packit 1c1d7e
  QCString className=clName;
Packit 1c1d7e
Packit 1c1d7e
  // Don't do anything for empty text
Packit 1c1d7e
  if (className.isEmpty()) return;
Packit 1c1d7e
Packit 1c1d7e
  DBG_CTX((stderr,"generateClassOrGlobalLink(className=%s)\n",className.data()));
Packit 1c1d7e
Packit 1c1d7e
  ClassDef *cd=0,*lcd=0;  /** Class def that we may find */
Packit 1c1d7e
  MemberDef *md=0;        /** Member def that we may find */
Packit 1c1d7e
  //bool isLocal=FALSE;
Packit 1c1d7e
Packit 1c1d7e
  if ((lcd=g_theVarContext.findVariable(className))==0) // not a local variable
Packit 1c1d7e
  {
Packit 1c1d7e
    Definition *d = g_currentDefinition;
Packit 1c1d7e
    QCString scope = substitute(className,".","::");
Packit 1c1d7e
Packit 1c1d7e
    cd = getResolvedClass(d,g_sourceFileDef,substitute(className,".","::"),&md);
Packit 1c1d7e
Packit 1c1d7e
    DBG_CTX((stderr,"d=%s g_sourceFileDef=%s\n",
Packit 1c1d7e
        d?d->displayName().data():"<null>",
Packit 1c1d7e
        g_currentDefinition?g_currentDefinition->displayName().data():"<null>"));
Packit 1c1d7e
    DBG_CTX((stderr,"is found as a type %s\n",cd?cd->name().data():"<null>"));
Packit 1c1d7e
Packit 1c1d7e
    if (cd==0 && md==0) // also see if it is variable or enum or enum value
Packit 1c1d7e
    {
Packit 1c1d7e
      NamespaceDef *nd = getResolvedNamespace(scope);
Packit 1c1d7e
      if (nd)
Packit 1c1d7e
      {
Packit 1c1d7e
        writeMultiLineCodeLink(ol,nd,clName);
Packit 1c1d7e
        addToSearchIndex(className);
Packit 1c1d7e
        return;
Packit 1c1d7e
      }
Packit 1c1d7e
      else if (getLink(g_classScope,clName,ol,clName))
Packit 1c1d7e
      {
Packit 1c1d7e
	return;
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  else
Packit 1c1d7e
  {
Packit 1c1d7e
    if (lcd!=PyVariableContext::dummyContext) 
Packit 1c1d7e
    {
Packit 1c1d7e
      g_theCallContext.setClass(lcd);
Packit 1c1d7e
    }
Packit 1c1d7e
    //isLocal=TRUE;
Packit 1c1d7e
    DBG_CTX((stderr,"is a local variable cd=%p!\n",cd));
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  if (cd && cd->isLinkable()) // is it a linkable class
Packit 1c1d7e
  {
Packit 1c1d7e
    writeMultiLineCodeLink(ol,cd,clName);
Packit 1c1d7e
    addToSearchIndex(className);
Packit 1c1d7e
    if (md)
Packit 1c1d7e
    {
Packit 1c1d7e
      Definition *d = md->getOuterScope()==Doxygen::globalScope ?
Packit 1c1d7e
                      md->getBodyDef() : md->getOuterScope();
Packit 1c1d7e
      if (md->getGroupDef()) d = md->getGroupDef();
Packit 1c1d7e
      if (d && d->isLinkable() && md->isLinkable() && 
Packit 1c1d7e
          g_currentMemberDef && g_collectXRefs)
Packit 1c1d7e
      {
Packit 1c1d7e
        addDocCrossReference(g_currentMemberDef,md);
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  else // not a class, maybe a global member
Packit 1c1d7e
  {
Packit 1c1d7e
    int scopeEnd = className.findRev(".");
Packit 1c1d7e
    if (scopeEnd!=-1 && !typeOnly) // name with explicit scope
Packit 1c1d7e
    {
Packit 1c1d7e
      QCString scope = substitute(className.left(scopeEnd),".","::");
Packit 1c1d7e
      QCString locName = className.right(className.length()-scopeEnd-1);
Packit 1c1d7e
      ClassDef *mcd = getClass(scope);
Packit 1c1d7e
      DBG_CTX((stderr,"scope=%s locName=%s mcd=%p\n",scope.data(),locName.data(),mcd));
Packit 1c1d7e
      if (mcd)
Packit 1c1d7e
      {
Packit 1c1d7e
	MemberDef *md = mcd->getMemberByName(locName);
Packit 1c1d7e
	if (md)
Packit 1c1d7e
	{
Packit 1c1d7e
          g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
Packit 1c1d7e
          writeMultiLineCodeLink(ol,md,clName);
Packit 1c1d7e
          addToSearchIndex(className);
Packit 1c1d7e
	  Definition *d = md->getOuterScope()==Doxygen::globalScope ?
Packit 1c1d7e
	                  md->getBodyDef() : md->getOuterScope();
Packit 1c1d7e
	  if (md->getGroupDef()) d = md->getGroupDef();
Packit 1c1d7e
	  if (d && d->isLinkable() && md->isLinkable() && 
Packit 1c1d7e
              g_currentMemberDef && g_collectXRefs)
Packit 1c1d7e
	  {
Packit 1c1d7e
	    addDocCrossReference(g_currentMemberDef,md);
Packit 1c1d7e
	  }
Packit 1c1d7e
	  return;
Packit 1c1d7e
	}
Packit 1c1d7e
      }
Packit 1c1d7e
      else // check namespace as well
Packit 1c1d7e
      {
Packit 1c1d7e
        NamespaceDef *mnd = getResolvedNamespace(scope);
Packit 1c1d7e
        if (mnd)
Packit 1c1d7e
        {
Packit 1c1d7e
  	  MemberDef *md=mnd->getMemberByName(locName);
Packit 1c1d7e
	  if (md)
Packit 1c1d7e
          {
Packit 1c1d7e
	    //printf("name=%s scope=%s\n",locName.data(),scope.data());
Packit 1c1d7e
	    g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
Packit 1c1d7e
            writeMultiLineCodeLink(ol,md,clName);
Packit 1c1d7e
            addToSearchIndex(className);
Packit 1c1d7e
	    Definition *d = md->getOuterScope()==Doxygen::globalScope ?
Packit 1c1d7e
	                    md->getBodyDef() : md->getOuterScope();
Packit 1c1d7e
	    if (md->getGroupDef()) d = md->getGroupDef();
Packit 1c1d7e
	    if (d && d->isLinkable() && md->isLinkable() && 
Packit 1c1d7e
                g_currentMemberDef && g_collectXRefs)
Packit 1c1d7e
	    {
Packit 1c1d7e
	      addDocCrossReference(g_currentMemberDef,md);
Packit 1c1d7e
	    }
Packit 1c1d7e
	    return;
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
    
Packit 1c1d7e
    // nothing found, just write out the word
Packit 1c1d7e
    codifyLines(clName);
Packit 1c1d7e
    addToSearchIndex(clName);
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*
Packit 1c1d7e
   As of June 1, this function seems to work
Packit 1c1d7e
   for file members, but scopes are not
Packit 1c1d7e
   being correctly tracked for classes
Packit 1c1d7e
   so it doesn't work for classes yet.
Packit 1c1d7e
Packit 1c1d7e
*/
Packit 1c1d7e
static void generateFunctionLink(CodeOutputInterface &ol,char *funcName)
Packit 1c1d7e
{
Packit 1c1d7e
  //CodeClassDef *ccd=0;
Packit 1c1d7e
  ClassDef *ccd=0;
Packit 1c1d7e
  QCString locScope=g_classScope.copy();
Packit 1c1d7e
  QCString locFunc=removeRedundantWhiteSpace(funcName);
Packit 1c1d7e
  DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data()));
Packit 1c1d7e
  int i=locFunc.findRev("::");
Packit 1c1d7e
  if (i>0)
Packit 1c1d7e
  {
Packit 1c1d7e
    locScope=locFunc.left(i);
Packit 1c1d7e
    locFunc=locFunc.right(locFunc.length()-i-2).stripWhiteSpace();
Packit 1c1d7e
  }
Packit 1c1d7e
  //printf("generateFunctionLink(%s) classScope=`%s'\n",locFunc.data(),locScope.data());
Packit 1c1d7e
  if (!locScope.isEmpty() && (ccd=g_codeClassSDict[locScope]))
Packit 1c1d7e
  {
Packit 1c1d7e
    //printf("using classScope %s\n",g_classScope.data());
Packit 1c1d7e
    if (ccd->baseClasses())
Packit 1c1d7e
    {
Packit 1c1d7e
      BaseClassListIterator bcli(*ccd->baseClasses());
Packit 1c1d7e
      for ( ; bcli.current() ; ++bcli)
Packit 1c1d7e
      {
Packit 1c1d7e
	if (getLink(bcli.current()->classDef->name(),locFunc,ol,funcName)) 
Packit 1c1d7e
	{
Packit 1c1d7e
	  return;
Packit 1c1d7e
	}
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  if (!getLink(locScope,locFunc,ol,funcName))
Packit 1c1d7e
  {
Packit 1c1d7e
    generateClassOrGlobalLink(ol,funcName);
Packit 1c1d7e
  }
Packit 1c1d7e
  return;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static bool findMemberLink(CodeOutputInterface &ol,Definition *sym,const char *symName)
Packit 1c1d7e
{
Packit 1c1d7e
  //printf("sym %s outerScope=%s equal=%d\n",
Packit 1c1d7e
  //    sym->name().data(),sym->getOuterScope()->name().data(),
Packit 1c1d7e
  //    sym->getOuterScope()==g_currentDefinition);
Packit 1c1d7e
Packit 1c1d7e
  if (sym->getOuterScope() &&
Packit 1c1d7e
      sym->getOuterScope()->definitionType()==Definition::TypeClass &&
Packit 1c1d7e
      g_currentDefinition->definitionType()==Definition::TypeClass)
Packit 1c1d7e
  {
Packit 1c1d7e
    ClassDef *cd = (ClassDef*)sym->getOuterScope();
Packit 1c1d7e
    ClassDef *thisCd = (ClassDef *)g_currentDefinition;
Packit 1c1d7e
    if (sym->definitionType()==Definition::TypeMember)
Packit 1c1d7e
    {
Packit 1c1d7e
      if (g_currentMemberDef && g_collectXRefs)
Packit 1c1d7e
      {
Packit 1c1d7e
	addDocCrossReference(g_currentMemberDef,(MemberDef*)sym);
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
    DBG_CTX((stderr,"cd=%s thisCd=%s\n",cd?cd->name().data():"<none>",thisCd?thisCd->name().data():"<none>"));
Packit 1c1d7e
Packit 1c1d7e
    // TODO: find the nearest base class in case cd is a base class of
Packit 1c1d7e
    // thisCd 
Packit 1c1d7e
    if (cd==thisCd || (thisCd && thisCd->isBaseClass(cd,TRUE)))
Packit 1c1d7e
    {
Packit 1c1d7e
      writeMultiLineCodeLink(ol,sym,symName);
Packit 1c1d7e
      return TRUE;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  return FALSE;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void findMemberLink(CodeOutputInterface &ol,char *symName)
Packit 1c1d7e
{
Packit 1c1d7e
  //printf("Member reference: %s scope=%s member=%s\n",
Packit 1c1d7e
  //    yytext,
Packit 1c1d7e
  //    g_currentDefinition?g_currentDefinition->name().data():"<none>",
Packit 1c1d7e
  //    g_currentMemberDef?g_currentMemberDef->name().data():"<none>"
Packit 1c1d7e
  //    );
Packit 1c1d7e
  if (g_currentDefinition)
Packit 1c1d7e
  {
Packit 1c1d7e
    DefinitionIntf *di = Doxygen::symbolMap->find(symName);
Packit 1c1d7e
    if (di)
Packit 1c1d7e
    {
Packit 1c1d7e
      if (di->definitionType()==DefinitionIntf::TypeSymbolList) // multiple symbols
Packit 1c1d7e
      {
Packit 1c1d7e
	DefinitionListIterator dli(*(DefinitionList*)di);
Packit 1c1d7e
	Definition *sym;
Packit 1c1d7e
	for (dli.toFirst();(sym=dli.current());++dli)
Packit 1c1d7e
	{
Packit 1c1d7e
	  if (findMemberLink(ol,sym,symName)) return;
Packit 1c1d7e
	}
Packit 1c1d7e
      }
Packit 1c1d7e
      else // single symbol
Packit 1c1d7e
      {
Packit 1c1d7e
	if (findMemberLink(ol,(Definition*)di,symName)) return;
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  //printf("sym %s not found\n",&yytext[5]);
Packit 1c1d7e
  codify(symName);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
#undef YY_INPUT
Packit 1c1d7e
#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
Packit 1c1d7e
Packit 1c1d7e
static int yyread(char *buf,int max_size)
Packit 1c1d7e
{
Packit 1c1d7e
  int c=0;
Packit 1c1d7e
  while( c < max_size && g_inputString[g_inputPosition] )
Packit 1c1d7e
  {
Packit 1c1d7e
    *buf = g_inputString[g_inputPosition++] ;
Packit 1c1d7e
    c++; buf++;
Packit 1c1d7e
  }
Packit 1c1d7e
  return c;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
%}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
BB                [ \t]+
Packit 1c1d7e
B                 [ \t]*
Packit 1c1d7e
NEWLINE           \n
Packit 1c1d7e
Packit 1c1d7e
DIGIT             [0-9]
Packit 1c1d7e
LETTER            [A-Za-z\x80-\xFF]
Packit 1c1d7e
NONEMPTY          [A-Za-z0-9_\x80-\xFF]
Packit 1c1d7e
EXPCHAR           [#(){}\[\],:.%/\\=`*~|&<>!;+-]
Packit 1c1d7e
NONEMPTYEXP       [^ \t\n:]
Packit 1c1d7e
PARAMNONEMPTY     [^ \t\n():]
Packit 1c1d7e
IDENTIFIER        ({LETTER}|"_")({LETTER}|{DIGIT}|"_")*  
Packit 1c1d7e
BORDER            ([^A-Za-z0-9])
Packit 1c1d7e
Packit 1c1d7e
POUNDCOMMENT      "##"
Packit 1c1d7e
Packit 1c1d7e
TRISINGLEQUOTE    "'''"
Packit 1c1d7e
TRIDOUBLEQUOTE    "\"\"\""
Packit 1c1d7e
LONGSTRINGCHAR    [^\\"']
Packit 1c1d7e
ESCAPESEQ         ("\\")(.)
Packit 1c1d7e
LONGSTRINGITEM    ({LONGSTRINGCHAR}|{ESCAPESEQ})
Packit 1c1d7e
SMALLQUOTE        ("\"\""|"\""|"'"|"''")
Packit 1c1d7e
LONGSTRINGBLOCK   ({LONGSTRINGITEM}+|{SMALLQUOTE})
Packit 1c1d7e
Packit 1c1d7e
SHORTSTRING       ("'"{SHORTSTRINGITEM}*"'"|'"'{SHORTSTRINGITEM}*'"')
Packit 1c1d7e
SHORTSTRINGITEM   ({SHORTSTRINGCHAR}|{ESCAPESEQ})
Packit 1c1d7e
SHORTSTRINGCHAR   [^\\\n"]
Packit 1c1d7e
STRINGLITERAL     {STRINGPREFIX}?( {SHORTSTRING} | {LONGSTRING})  
Packit 1c1d7e
STRINGPREFIX      ("r"|"u"|"ur"|"R"|"U"|"UR"|"Ur"|"uR")
Packit 1c1d7e
KEYWORD ("lambda"|"import"|"class"|"assert"|"as"|"from"|"global"|"def"|"True"|"False")
Packit 1c1d7e
FLOWKW  ("or"|"and"|"is"|"not"|"print"|"for"|"in"|"if"|"try"|"except"|"yield"|"raise"|"break"|"continue"|"pass"|"if"|"return"|"while"|"elif"|"else"|"finally")
Packit 1c1d7e
QUOTES            ("\""[^"]*"\"")
Packit 1c1d7e
SINGLEQUOTES      ("'"[^']*"'")
Packit 1c1d7e
Packit 1c1d7e
LONGINTEGER       {INTEGER}("l"|"L")
Packit 1c1d7e
INTEGER           ({DECIMALINTEGER}|{OCTINTEGER}|{HEXINTEGER})
Packit 1c1d7e
DECIMALINTEGER    ({NONZERODIGIT}{DIGIT}*|"0")
Packit 1c1d7e
OCTINTEGER        "0"{OCTDIGIT}+
Packit 1c1d7e
HEXINTEGER        "0"("x"|"X"){HEXDIGIT}+  
Packit 1c1d7e
NONZERODIGIT      [1-9]  
Packit 1c1d7e
OCTDIGIT          [0-7]  
Packit 1c1d7e
HEXDIGIT          ({DIGIT}|[a-f]|[A-F])
Packit 1c1d7e
FLOATNUMBER       ({POINTFLOAT}|{EXPONENTFLOAT})
Packit 1c1d7e
POINTFLOAT        ({INTPART}?{FRACTION}|{INTPART}".")  
Packit 1c1d7e
EXPONENTFLOAT     ({INTPART}|{POINTFLOAT}){EXPONENT}
Packit 1c1d7e
INTPART             {DIGIT}+  
Packit 1c1d7e
FRACTION             "."{DIGIT}+  
Packit 1c1d7e
EXPONENT             ("e"|"E")("+"|"-")?{DIGIT}+
Packit 1c1d7e
IMAGNUMBER ({FLOATNUMBER}|{INTPART})("j"|"J")
Packit 1c1d7e
ATOM              ({IDENTIFIER}|{LITERAL}|{ENCLOSURE})
Packit 1c1d7e
ENCLOSURE             ({PARENTH_FORM}|{LIST_DISPLAY}|{DICT_DISPLAY}|{STRING_CONVERSION})
Packit 1c1d7e
LITERAL             ({STRINGLITERAL}|{INTEGER}|{LONGINTEGER}|{FLOATNUMBER}|{IMAGNUMBER})
Packit 1c1d7e
PARENTH_FORM       "("{EXPRESSION_LIST}?")"
Packit 1c1d7e
TEST             ({AND_TEST}("or"{AND_TEST})*|{LAMBDA_FORM})
Packit 1c1d7e
TESTLIST             {TEST}( ","{TEST})*","?
Packit 1c1d7e
LIST_DISPLAY        "["{LISTMAKER}?"]"  
Packit 1c1d7e
LISTMAKER             {EXPRESSION}({LIST_FOR}|(","{EXPRESSION})*","?)  
Packit 1c1d7e
LIST_ITER             ({LIST_FOR}|{LIST_IF})  
Packit 1c1d7e
LIST_FOR             "for"{EXPRESSION_LIST}"in"{TESTLIST}{LIST_ITER}?
Packit 1c1d7e
LIST_IF             "if"{TEST}{LIST_ITER}?
Packit 1c1d7e
DICT_DISPLAY             "\{"{KEY_DATUM_LIST}?"\}"
Packit 1c1d7e
KEY_DATUM_LIST       {KEY_DATUM}(","{KEY_DATUM})*","? 
Packit 1c1d7e
KEY_DATUM              {EXPRESSION}":"{EXPRESSION}
Packit 1c1d7e
STRING_CONVERSION        "`"{EXPRESSION_LIST}"`"
Packit 1c1d7e
PRIMARY             ({ATOM}|{ATTRIBUTEREF}|{SUBSCRIPTION}|{SLICING}|{CALL})
Packit 1c1d7e
ATTRIBUTEREF             {PRIMARY}"."{IDENTIFIER}
Packit 1c1d7e
SUBSCRIPTION             {PRIMARY}"["{EXPRESSION_LIST}"]"
Packit 1c1d7e
SLICING            ({SIMPLE_SLICING}|{EXTENDED_SLICING})
Packit 1c1d7e
SIMPLE_SLICING             {PRIMARY}"["{SHORT_SLICE}"]"  
Packit 1c1d7e
EXTENDED_SLICING           {PRIMARY}"["{SLICE_LIST}"]" 
Packit 1c1d7e
SLICE_LIST          {SLICE_ITEM}(","{SLICE_ITEM})*","?
Packit 1c1d7e
SLICE_ITEM           ({EXPRESSION}|{PROPER_SLICE}|{ELLIPSIS})
Packit 1c1d7e
PROPER_SLICE           ({SHORT_SLICE}|{LONG_SLICE})
Packit 1c1d7e
SHORT_SLICE              {LOWER_BOUND}?":"{UPPER_BOUND}?  
Packit 1c1d7e
LONG_SLICE             {SHORT_SLICE}":"{STRIDE}?
Packit 1c1d7e
LOWER_BOUND             {EXPRESSION}  
Packit 1c1d7e
UPPER_BOUND             {EXPRESSION}
Packit 1c1d7e
STRIDE             {EXPRESSION}
Packit 1c1d7e
ELLIPSIS             "..."
Packit 1c1d7e
CALL             {PRIMARY}"("({ARGUMENT_LIST}","?)?")"
Packit 1c1d7e
ARGUMENT_LIST       ({POSITIONAL_ARGUMENTS}(","{KEYWORD_ARGUMENTS})?(",""*"{EXPRESSION})?(",""**"{EXPRESSION})?|{KEYWORD_ARGUMENTS}(",""*"{EXPRESSION})?(",""**"{EXPRESSION})?|"*"{EXPRESSION}(",""**"{EXPRESSION})?|"**"{EXPRESSION})
Packit 1c1d7e
POSITIONAL_ARGUMENTS             {EXPRESSION}(","{EXPRESSION})*
Packit 1c1d7e
KEYWORD_ARGUMENTS              {KEYWORD_ITEM}(","{KEYWORD_ITEM})*
Packit 1c1d7e
KEYWORD_ITEM           {IDENTIFIER}"="{EXPRESSION}
Packit 1c1d7e
POWER             {PRIMARY}("**"{U_EXPR})?
Packit 1c1d7e
U_EXPR            ({POWER}|"-"{U_EXPR}|"+"{U_EXPR}|"\~"{U_EXPR})
Packit 1c1d7e
M_EXPR            ({U_EXPR}|{M_EXPR}"*"{U_EXPR}|{M_EXPR}"//"{U_EXPR}|{M_EXPR}"/"{U_EXPR}|{M_EXPR}"\%"{U_EXPR})
Packit 1c1d7e
A_EXPR         ({M_EXPR}|{A_EXPR}"+"{M_EXPR}|{A_EXPR}"-"{M_EXPR}
Packit 1c1d7e
SHIFT_EXPR            ({A_EXPR}|{SHIFT_EXPR}("<<"|">>"){A_EXPR})
Packit 1c1d7e
AND_EXPR            ({SHIFT_EXPR}|{AND_EXPR}"\;SPMamp;"{SHIFT_EXPR}
Packit 1c1d7e
XOR_EXPR            ({AND_EXPR}|{XOR_EXPR}"\textasciicircum"{AND_EXPR})
Packit 1c1d7e
OR_EXPR            ({XOR_EXPR}|{OR_EXPR}"|"{ XOR_EXPR})
Packit 1c1d7e
Packit 1c1d7e
COMPARISON             {OR_EXPR}({COMP_OPERATOR}{OR_EXPR})*
Packit 1c1d7e
COMP_OPERATOR         ("<"|">"|"=="|">="|"<="|"<>"|"!="|"is""not"?|"not"?"in")
Packit 1c1d7e
EXPRESSION            ({OR_TEST}|{LAMBDA_FORM})
Packit 1c1d7e
OR_TEST             ({AND_TEST}|{OR_TEST}"or"{AND_TEST})
Packit 1c1d7e
AND_TEST          ({NOT_TEST}|{AND_TEST}"and"{NOT_TEST})
Packit 1c1d7e
NOT_TEST           ({COMPARISON}|"not"{NOT_TEST})
Packit 1c1d7e
LAMBDA_FORM       "lambda"{PARAMETER_LIST}?":"{EXPRESSION}
Packit 1c1d7e
EXPRESSION_LIST      {EXPRESSION}(","{EXPRESSION})*","?
Packit 1c1d7e
SIMPLE_STMT       ({EXPRESSION_STMT}|{ASSERT_STMT}|{ASSIGNMENT_STMT}|{AUGMENTED_ASSIGNMENT_STMT}|{PASS_STMT}|{DEL_STMT}|{PRINT_STMT}|{RETURN_STMT}|{YIELD_STMT}|{RAISE_STMT}|{BREAK_STMT}|{CONTINUE_STMT}|{IMPORT_STMT}|{GLOBAL_STMT}|{EXEC_STMT})
Packit 1c1d7e
EXPRESSION_STMT     {EXPRESSION_LIST}
Packit 1c1d7e
ASSERT_STMT             "assert"{EXPRESSION}(","{EXPRESSION})?
Packit 1c1d7e
ASSIGNMENT_STMT     ({TARGET_LIST}"=")+{EXPRESSION_LIST}
Packit 1c1d7e
TARGET_LIST             {TARGET}(","{TARGET})*","?
Packit 1c1d7e
TARGET           ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUTEREF}|{SUBSCRIPTION}|{SLICING})
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
%option noyywrap
Packit 1c1d7e
%option stack
Packit 1c1d7e
Packit 1c1d7e
%x Body
Packit 1c1d7e
Packit 1c1d7e
%x FunctionDec
Packit 1c1d7e
%x FunctionParams
Packit 1c1d7e
Packit 1c1d7e
%x ClassDec
Packit 1c1d7e
%x ClassInheritance
Packit 1c1d7e
Packit 1c1d7e
%x Suite
Packit 1c1d7e
%x SuiteCaptureIndent
Packit 1c1d7e
%x SuiteStart
Packit 1c1d7e
%x SuiteMaintain
Packit 1c1d7e
%x SuiteContinuing
Packit 1c1d7e
Packit 1c1d7e
%x LongString
Packit 1c1d7e
Packit 1c1d7e
%x SingleQuoteString
Packit 1c1d7e
%x DoubleQuoteString
Packit 1c1d7e
%x TripleString
Packit 1c1d7e
Packit 1c1d7e
%x DocBlock
Packit 1c1d7e
%%
Packit 1c1d7e
Packit 1c1d7e
<Body,Suite>{
Packit 1c1d7e
      "def"{BB}                     {
Packit 1c1d7e
				        startFontClass("keyword");
Packit 1c1d7e
					codify(yytext);
Packit 1c1d7e
					endFontClass();
Packit 1c1d7e
					BEGIN( FunctionDec );
Packit 1c1d7e
		                    }
Packit 1c1d7e
Packit 1c1d7e
      "class"{BB}                   {
Packit 1c1d7e
				        startFontClass("keyword");
Packit 1c1d7e
					codify(yytext);
Packit 1c1d7e
					endFontClass();
Packit 1c1d7e
					BEGIN( ClassDec );
Packit 1c1d7e
		                    }
Packit 1c1d7e
      "None"                        {
Packit 1c1d7e
				        startFontClass("keywordtype");
Packit 1c1d7e
					codify(yytext);
Packit 1c1d7e
					endFontClass();
Packit 1c1d7e
				    }
Packit 1c1d7e
      "self."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" {
Packit 1c1d7e
				        codify("self.");
Packit 1c1d7e
				        findMemberLink(*g_code,&yytext[5]);
Packit 1c1d7e
	                            }
Packit 1c1d7e
      "self."{IDENTIFIER}/"("       {
Packit 1c1d7e
				        codify("self.");
Packit 1c1d7e
				        findMemberLink(*g_code,&yytext[5]);
Packit 1c1d7e
	                            }
Packit 1c1d7e
      "self."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} {
Packit 1c1d7e
				        codify("self.");
Packit 1c1d7e
				        findMemberLink(*g_code,&yytext[5]);
Packit 1c1d7e
	                            }
Packit 1c1d7e
      "self."{IDENTIFIER}           {
Packit 1c1d7e
				        codify("self.");
Packit 1c1d7e
				        findMemberLink(*g_code,&yytext[5]);
Packit 1c1d7e
	                            }
Packit 1c1d7e
      "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" {
Packit 1c1d7e
				        codify("cls.");
Packit 1c1d7e
				        findMemberLink(*g_code,&yytext[4]);
Packit 1c1d7e
	                            }
Packit 1c1d7e
      "cls."{IDENTIFIER}/"("       {
Packit 1c1d7e
				        codify("cls.");
Packit 1c1d7e
				        findMemberLink(*g_code,&yytext[4]);
Packit 1c1d7e
	                            }
Packit 1c1d7e
      "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} {
Packit 1c1d7e
				        codify("cls.");
Packit 1c1d7e
				        findMemberLink(*g_code,&yytext[4]);
Packit 1c1d7e
	                            }
Packit 1c1d7e
      "cls."{IDENTIFIER}           {
Packit 1c1d7e
				        codify("cls.");
Packit 1c1d7e
				        findMemberLink(*g_code,&yytext[4]);
Packit 1c1d7e
	                            }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
<ClassDec>{IDENTIFIER}              {
Packit 1c1d7e
Packit 1c1d7e
					generateClassOrGlobalLink(*g_code,yytext);
Packit 1c1d7e
					// codify(yytext);
Packit 1c1d7e
					g_curClassName = yytext;
Packit 1c1d7e
					g_curClassBases.clear();
Packit 1c1d7e
					BEGIN( ClassInheritance );
Packit 1c1d7e
		                    }
Packit 1c1d7e
Packit 1c1d7e
<ClassInheritance>{
Packit 1c1d7e
   ({BB}|[(,)])                     {
Packit 1c1d7e
					codify(yytext);
Packit 1c1d7e
                                    }
Packit 1c1d7e
Packit 1c1d7e
   ({IDENTIFIER}".")*{IDENTIFIER}   {
Packit 1c1d7e
                                        // The parser
Packit 1c1d7e
					// is assuming
Packit 1c1d7e
					// that ALL identifiers
Packit 1c1d7e
					// in this state
Packit 1c1d7e
					// are base classes;
Packit 1c1d7e
					// it doesn't check to see
Packit 1c1d7e
					// that the first parenthesis
Packit 1c1d7e
					// has been seen.
Packit 1c1d7e
Packit 1c1d7e
					// This is bad - it should
Packit 1c1d7e
					// probably be more strict
Packit 1c1d7e
					// about what to accept.
Packit 1c1d7e
Packit 1c1d7e
                                        g_curClassBases.inSort(yytext);
Packit 1c1d7e
					generateClassOrGlobalLink(*g_code,yytext);
Packit 1c1d7e
					// codify(yytext);
Packit 1c1d7e
                                    }
Packit 1c1d7e
Packit 1c1d7e
    ":"                             {
Packit 1c1d7e
				      codify(yytext);
Packit 1c1d7e
Packit 1c1d7e
				      // Assume this will
Packit 1c1d7e
				      // be a one-line suite;
Packit 1c1d7e
				      // found counter-example
Packit 1c1d7e
				      // in SuiteStart.
Packit 1c1d7e
Packit 1c1d7e
                                      // Push a class scope
Packit 1c1d7e
Packit 1c1d7e
                                      ClassDef *classDefToAdd = new ClassDef("",1,1,g_curClassName,ClassDef::Class,0,0,FALSE);
Packit 1c1d7e
                                      g_codeClassSDict.append(g_curClassName,classDefToAdd);
Packit 1c1d7e
                                      char *s=g_curClassBases.first();
Packit 1c1d7e
                                      while (s) 
Packit 1c1d7e
				      {
Packit 1c1d7e
                                        ClassDef *baseDefToAdd;
Packit 1c1d7e
                                        baseDefToAdd=g_codeClassSDict[s];
Packit 1c1d7e
Packit 1c1d7e
					// Try to find class in global
Packit 1c1d7e
					// scope
Packit 1c1d7e
					if (baseDefToAdd==0) 
Packit 1c1d7e
					{
Packit 1c1d7e
					  baseDefToAdd=getResolvedClass(g_currentDefinition,g_sourceFileDef,s);
Packit 1c1d7e
					}
Packit 1c1d7e
Packit 1c1d7e
					if (baseDefToAdd && baseDefToAdd!=classDefToAdd) 
Packit 1c1d7e
					{
Packit 1c1d7e
				          classDefToAdd->insertBaseClass(baseDefToAdd,s,Public,Normal);
Packit 1c1d7e
					}
Packit 1c1d7e
Packit 1c1d7e
                                        s=g_curClassBases.next();
Packit 1c1d7e
			              }
Packit 1c1d7e
Packit 1c1d7e
				      // Reset class-parsing variables.
Packit 1c1d7e
				      g_curClassName.resize(0);
Packit 1c1d7e
				      g_curClassBases.clear();
Packit 1c1d7e
				      
Packit 1c1d7e
				      g_noSuiteFound = TRUE;
Packit 1c1d7e
				      BEGIN( SuiteStart );
Packit 1c1d7e
                                    }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
<FunctionDec>{
Packit 1c1d7e
    {IDENTIFIER}                    {
Packit 1c1d7e
                                        generateFunctionLink(*g_code,yytext);
Packit 1c1d7e
                                    }
Packit 1c1d7e
Packit 1c1d7e
    {B}"("                          {
Packit 1c1d7e
				        codify(yytext);
Packit 1c1d7e
					BEGIN( FunctionParams );
Packit 1c1d7e
		                    }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
<FunctionParams>{
Packit 1c1d7e
    ({BB}|",")                      {
Packit 1c1d7e
                                         // Parses delimiters
Packit 1c1d7e
				         codify(yytext);
Packit 1c1d7e
                                    }
Packit 1c1d7e
Packit 1c1d7e
    ({IDENTIFIER}|{PARAMNONEMPTY}+) {
Packit 1c1d7e
				         codify(yytext);
Packit 1c1d7e
                                    }
Packit 1c1d7e
Packit 1c1d7e
    ")"                             {
Packit 1c1d7e
                                         codify(yytext);
Packit 1c1d7e
                                    }
Packit 1c1d7e
Packit 1c1d7e
    "\n"                            {
Packit 1c1d7e
				         codifyLines(yytext);
Packit 1c1d7e
                                    }
Packit 1c1d7e
Packit 1c1d7e
    ":"                             {
Packit 1c1d7e
				      codify(yytext);
Packit 1c1d7e
Packit 1c1d7e
				      // Assume this will
Packit 1c1d7e
				      // be a one-line suite;
Packit 1c1d7e
				      // found counter-example
Packit 1c1d7e
				      // in SuiteStart.
Packit 1c1d7e
				      g_noSuiteFound = TRUE;
Packit 1c1d7e
				      BEGIN( SuiteStart );
Packit 1c1d7e
                                    }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
<Body,Suite>{
Packit 1c1d7e
Packit 1c1d7e
    {KEYWORD}                  {
Packit 1c1d7e
                                 // Position-sensitive rules!
Packit 1c1d7e
                                 // Must come AFTER keyword-triggered rules
Packit 1c1d7e
                                 // Must come BEFORE identifier NONEMPTY-like rules
Packit 1c1d7e
                                 //   to syntax highlight.
Packit 1c1d7e
Packit 1c1d7e
  		                 startFontClass("keyword");
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
		                 endFontClass();
Packit 1c1d7e
                               }
Packit 1c1d7e
Packit 1c1d7e
    {FLOWKW}                   {
Packit 1c1d7e
  		                 startFontClass("keywordflow");
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
		                 endFontClass();
Packit 1c1d7e
                               }
Packit 1c1d7e
    ({IDENTIFIER}".")*{IDENTIFIER}/"("  {
Packit 1c1d7e
				 generateClassOrGlobalLink(*g_code,yytext);
Packit 1c1d7e
      			       }
Packit 1c1d7e
    ({IDENTIFIER}".")+{IDENTIFIER} {
Packit 1c1d7e
				 generateClassOrGlobalLink(*g_code,yytext,TRUE);
Packit 1c1d7e
			       }
Packit 1c1d7e
    {IDENTIFIER}               { codify(yytext); }
Packit 1c1d7e
		   	
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
<SuiteStart>{
Packit 1c1d7e
Packit 1c1d7e
    {BB}                               {
Packit 1c1d7e
                                         codify(yytext);
Packit 1c1d7e
                                       }
Packit 1c1d7e
    "pass"			       {
Packit 1c1d7e
                                          startFontClass("keyword");
Packit 1c1d7e
					  codifyLines(yytext);
Packit 1c1d7e
		                          endFontClass();
Packit 1c1d7e
					  BEGIN(Body);
Packit 1c1d7e
      				       }
Packit 1c1d7e
    {KEYWORD}                          {
Packit 1c1d7e
                                          startFontClass("keyword");
Packit 1c1d7e
					  codifyLines(yytext);
Packit 1c1d7e
		                          endFontClass();
Packit 1c1d7e
Packit 1c1d7e
					  // No indentation necessary
Packit 1c1d7e
					  g_noSuiteFound = FALSE;
Packit 1c1d7e
                                       }
Packit 1c1d7e
Packit 1c1d7e
    {FLOWKW}                           {
Packit 1c1d7e
                                          startFontClass("keywordflow");
Packit 1c1d7e
					  codifyLines(yytext);
Packit 1c1d7e
		                          endFontClass();
Packit 1c1d7e
Packit 1c1d7e
					  // No indentation necessary
Packit 1c1d7e
					  g_noSuiteFound = FALSE;
Packit 1c1d7e
                                       }
Packit 1c1d7e
    {IDENTIFIER}                       {
Packit 1c1d7e
                                         codify(yytext);
Packit 1c1d7e
				       } 
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
    {POUNDCOMMENT}                     {
Packit 1c1d7e
  				         if (YY_START==SingleQuoteString || 
Packit 1c1d7e
				             YY_START==DoubleQuoteString || 
Packit 1c1d7e
				             YY_START==TripleString
Packit 1c1d7e
				            )
Packit 1c1d7e
				         {
Packit 1c1d7e
				           REJECT;
Packit 1c1d7e
				         }
Packit 1c1d7e
                                         yy_push_state(YY_START);
Packit 1c1d7e
				         BEGIN(DocBlock);
Packit 1c1d7e
				         g_docBlock=yytext;
Packit 1c1d7e
                                       }
Packit 1c1d7e
Packit 1c1d7e
    {NEWLINE}                          {
Packit 1c1d7e
					  codifyLines(yytext);
Packit 1c1d7e
					  if ( g_noSuiteFound ) 
Packit 1c1d7e
					  {
Packit 1c1d7e
                                            // printf("New suite to capture! [%d]\n", g_yyLineNr);
Packit 1c1d7e
					    BEGIN ( SuiteCaptureIndent );
Packit 1c1d7e
					  }
Packit 1c1d7e
                                       }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
<SuiteCaptureIndent>{
Packit 1c1d7e
    "\n"|({BB}"\n")            {
Packit 1c1d7e
                                 // Blankline - ignore, keep looking for indentation.
Packit 1c1d7e
				 codifyLines(yytext);
Packit 1c1d7e
                               }
Packit 1c1d7e
Packit 1c1d7e
    {BB}                       {
Packit 1c1d7e
                                 // This state lasts momentarily,
Packit 1c1d7e
                                 // to check the indentation
Packit 1c1d7e
                                 // level that is about to be
Packit 1c1d7e
                                 // used.
Packit 1c1d7e
				 codifyLines(yytext);
Packit 1c1d7e
				 g_indents.push(yyleng);
Packit 1c1d7e
                                 // printf("Captured indent of %d [line %d]\n", yyleng, g_yyLineNr);
Packit 1c1d7e
				 BEGIN( Suite );
Packit 1c1d7e
                               }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
<SuiteMaintain>{
Packit 1c1d7e
Packit 1c1d7e
    {BB}/({NONEMPTY}|{EXPCHAR}) {
Packit 1c1d7e
                                 // This implements poor
Packit 1c1d7e
				 // indendation-tracking;
Packit 1c1d7e
                                 // should be improved.
Packit 1c1d7e
				 // (translate tabs to space, etc)
Packit 1c1d7e
  		                 codifyLines(yytext);
Packit 1c1d7e
                                 adjustScopesAndSuites((int)yyleng);
Packit 1c1d7e
                               }
Packit 1c1d7e
Packit 1c1d7e
    "\n"|({BB}"\n")            {
Packit 1c1d7e
                                 // If this ever succeeds,
Packit 1c1d7e
				 // it means that this is
Packit 1c1d7e
				 // a blank line, and
Packit 1c1d7e
				 // can be ignored.
Packit 1c1d7e
  		                 codifyLines(yytext);
Packit 1c1d7e
                               }
Packit 1c1d7e
Packit 1c1d7e
    ""/({NONEMPTY}|{EXPCHAR})  {
Packit 1c1d7e
                                 // Default rule; matches
Packit 1c1d7e
				 // the empty string, assuming
Packit 1c1d7e
				 // real text starts here.
Packit 1c1d7e
				 // Just go straight to Body.
Packit 1c1d7e
                                 adjustScopesAndSuites(0);
Packit 1c1d7e
                               }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
<Suite>{NEWLINE}               {
Packit 1c1d7e
                                 codifyLines(yytext);
Packit 1c1d7e
			         BEGIN( SuiteMaintain );
Packit 1c1d7e
		               }
Packit 1c1d7e
<Body>{IDENTIFIER}	       {
Packit 1c1d7e
  			         codify(yytext);
Packit 1c1d7e
                               }
Packit 1c1d7e
<Body>{NEWLINE}                {
Packit 1c1d7e
  		                 codifyLines(yytext);
Packit 1c1d7e
                               }
Packit 1c1d7e
Packit 1c1d7e
<SingleQuoteString>{ // Single quoted string like 'That\'s a """nice""" string!'
Packit 1c1d7e
    \\{B}\n                    { // line continuation
Packit 1c1d7e
  		                 codifyLines(yytext);
Packit 1c1d7e
                               }
Packit 1c1d7e
    \\.			       { // espaced char
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
                               }
Packit 1c1d7e
    {STRINGPREFIX}?{TRIDOUBLEQUOTE} { // tripple double quotes
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
      			       }
Packit 1c1d7e
    "'"			       { // end of the string
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
				 endFontClass();
Packit 1c1d7e
      		                 BEGIN(g_stringContext);
Packit 1c1d7e
                               }
Packit 1c1d7e
    [^"'\n\\]+	               { // normal chars
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
                               }
Packit 1c1d7e
    .			       { // normal char
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
                               }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
<DoubleQuoteString>{ // Double quoted string like "That's \"a '''nice'''\" string!"
Packit 1c1d7e
    \\{B}\n                    { // line continuation
Packit 1c1d7e
  		                 codifyLines(yytext);
Packit 1c1d7e
                               }
Packit 1c1d7e
    \\.			       { // espaced char
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
                               }
Packit 1c1d7e
    {STRINGPREFIX}?{TRISINGLEQUOTE} { // tripple single quotes
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
      			       }
Packit 1c1d7e
    "\""		       { // end of the string
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
				 endFontClass();
Packit 1c1d7e
      		                 BEGIN(g_stringContext);
Packit 1c1d7e
                               }
Packit 1c1d7e
    [^"'\n\\]+	               { // normal chars
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
                               }
Packit 1c1d7e
    .			       { // normal char
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
                               }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
<TripleString>{
Packit 1c1d7e
    {TRIDOUBLEQUOTE}   | 
Packit 1c1d7e
    {TRISINGLEQUOTE}   {
Packit 1c1d7e
  		          codify(yytext);
Packit 1c1d7e
			  if (g_doubleQuote==(yytext[0]=='"')) 
Packit 1c1d7e
			  {
Packit 1c1d7e
			    endFontClass();
Packit 1c1d7e
			    BEGIN(g_stringContext);
Packit 1c1d7e
			  }
Packit 1c1d7e
		       }
Packit 1c1d7e
    {LONGSTRINGBLOCK}  {
Packit 1c1d7e
			 codifyLines(yytext);
Packit 1c1d7e
		       }
Packit 1c1d7e
    \n		       {
Packit 1c1d7e
			 codifyLines(yytext);
Packit 1c1d7e
                       }
Packit 1c1d7e
    .		       {
Packit 1c1d7e
                         codify(yytext);
Packit 1c1d7e
                       }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
  /*
Packit 1c1d7e
<*>({NONEMPTY}|{EXPCHAR}|{BB})           { // This should go one character at a time.
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
				 // printf("[pycode] '%s' [ state %d ]  [line %d] no match\n",
Packit 1c1d7e
				 //       yytext, YY_START, g_yyLineNr);
Packit 1c1d7e
Packit 1c1d7e
				 //endFontClass();
Packit 1c1d7e
				 BEGIN(Body);					
Packit 1c1d7e
                               }
Packit 1c1d7e
   */
Packit 1c1d7e
Packit 1c1d7e
<*>{STRINGPREFIX}?{TRISINGLEQUOTE} |
Packit 1c1d7e
<*>{STRINGPREFIX}?{TRIDOUBLEQUOTE} {
Packit 1c1d7e
  				 startFontClass("stringliteral");
Packit 1c1d7e
				 g_stringContext=YY_START;
Packit 1c1d7e
				 g_doubleQuote=yytext[yyleng-1]=='"';
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
				 BEGIN(TripleString);
Packit 1c1d7e
                               }
Packit 1c1d7e
<*>{STRINGPREFIX}?"'"	       { // single quoted string
Packit 1c1d7e
  				 startFontClass("stringliteral");
Packit 1c1d7e
				 g_stringContext=YY_START;
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
				 BEGIN(SingleQuoteString);
Packit 1c1d7e
  			       }
Packit 1c1d7e
<*>{STRINGPREFIX}?"\""         { // double quoted string
Packit 1c1d7e
  				 startFontClass("stringliteral");
Packit 1c1d7e
				 g_stringContext=YY_START;
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
				 BEGIN(DoubleQuoteString);
Packit 1c1d7e
                               }
Packit 1c1d7e
<DocBlock>.*    	       { // contents of current comment line
Packit 1c1d7e
                                 g_docBlock+=yytext;
Packit 1c1d7e
  			       }
Packit 1c1d7e
<DocBlock>"\n"{B}("#")         { // comment block (next line is also comment line)
Packit 1c1d7e
				 g_docBlock+=yytext; 
Packit 1c1d7e
   			       }
Packit 1c1d7e
<DocBlock>{NEWLINE}            { // comment block ends at the end of this line
Packit 1c1d7e
                                 // remove special comment (default config)
Packit 1c1d7e
				 if (Config_getBool(STRIP_CODE_COMMENTS))
Packit 1c1d7e
				 {
Packit 1c1d7e
				    g_yyLineNr+=((QCString)g_docBlock).contains('\n');
Packit 1c1d7e
				    g_endComment=TRUE;
Packit 1c1d7e
				  }
Packit 1c1d7e
				  else // do not remove comment
Packit 1c1d7e
				  {
Packit 1c1d7e
				    startFontClass("comment");
Packit 1c1d7e
				    codifyLines(g_docBlock);
Packit 1c1d7e
				    endFontClass();
Packit 1c1d7e
				  }
Packit 1c1d7e
				  unput(*yytext);
Packit 1c1d7e
				  yy_pop_state();
Packit 1c1d7e
			       }
Packit 1c1d7e
<*>{POUNDCOMMENT}.*            {
Packit 1c1d7e
  				 if (YY_START==SingleQuoteString || 
Packit 1c1d7e
				     YY_START==DoubleQuoteString || 
Packit 1c1d7e
				     YY_START==TripleString
Packit 1c1d7e
				    )
Packit 1c1d7e
				 {
Packit 1c1d7e
				   REJECT;
Packit 1c1d7e
				 }
Packit 1c1d7e
                                 yy_push_state(YY_START);
Packit 1c1d7e
				 BEGIN(DocBlock);
Packit 1c1d7e
				 g_docBlock=yytext;
Packit 1c1d7e
                               }
Packit 1c1d7e
<*>"#".*                       { // normal comment
Packit 1c1d7e
  				 if (YY_START==SingleQuoteString || 
Packit 1c1d7e
				     YY_START==DoubleQuoteString || 
Packit 1c1d7e
				     YY_START==TripleString
Packit 1c1d7e
				    )
Packit 1c1d7e
				 {
Packit 1c1d7e
				   REJECT;
Packit 1c1d7e
				 }
Packit 1c1d7e
                                 startFontClass("comment");
Packit 1c1d7e
                                 codifyLines(yytext);
Packit 1c1d7e
                                 endFontClass();
Packit 1c1d7e
                               }
Packit 1c1d7e
<*>{NEWLINE}                   {
Packit 1c1d7e
				  if (g_endComment)
Packit 1c1d7e
				  {
Packit 1c1d7e
				    g_endComment=FALSE;
Packit 1c1d7e
				  }
Packit 1c1d7e
				  else
Packit 1c1d7e
				  {
Packit 1c1d7e
				    codifyLines(yytext);
Packit 1c1d7e
				  }
Packit 1c1d7e
				 //printf("[pycode] %d NEWLINE [line %d] no match\n",
Packit 1c1d7e
				 //       YY_START, g_yyLineNr);
Packit 1c1d7e
Packit 1c1d7e
				 //endFontClass();
Packit 1c1d7e
				 BEGIN(Body);
Packit 1c1d7e
                               }
Packit 1c1d7e
Packit 1c1d7e
<*>[ \t]+                      {
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
				 BEGIN(Body);					
Packit 1c1d7e
  			       }
Packit 1c1d7e
<*>.                           {
Packit 1c1d7e
  		                 codify(yytext);
Packit 1c1d7e
				 // printf("[pycode] '%s' [ state %d ]  [line %d] no match\n",
Packit 1c1d7e
				 //        yytext, YY_START, g_yyLineNr);
Packit 1c1d7e
Packit 1c1d7e
				 //endFontClass();
Packit 1c1d7e
				 BEGIN(Body);					
Packit 1c1d7e
                               }
Packit 1c1d7e
Packit 1c1d7e
<*><<EOF>>                     {
Packit 1c1d7e
                                 if (YY_START == DocBlock) {
Packit 1c1d7e
                                   if (!Config_getBool(STRIP_CODE_COMMENTS))
Packit 1c1d7e
                                   {
Packit 1c1d7e
                                     startFontClass("comment");
Packit 1c1d7e
                                     codifyLines(g_docBlock);
Packit 1c1d7e
                                     endFontClass();
Packit 1c1d7e
                                   }
Packit 1c1d7e
                                 }
Packit 1c1d7e
                                 yyterminate();
Packit 1c1d7e
                               }
Packit 1c1d7e
%%
Packit 1c1d7e
Packit 1c1d7e
/*@ ----------------------------------------------------------------------------
Packit 1c1d7e
 */
Packit 1c1d7e
Packit 1c1d7e
void resetPythonCodeParserState() 
Packit 1c1d7e
{
Packit 1c1d7e
  g_currentDefinition = 0;
Packit 1c1d7e
  g_currentMemberDef = 0;
Packit 1c1d7e
  g_doubleStringIsDoc = FALSE;
Packit 1c1d7e
  g_paramParens = 0;
Packit 1c1d7e
  g_indents.clear();
Packit 1c1d7e
  BEGIN( Body );
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Examines current stack of white-space indentations;
Packit 1c1d7e
  re-syncs the parser with the correct scope.
Packit 1c1d7e
*/
Packit 1c1d7e
static void adjustScopesAndSuites(unsigned indentLength) 
Packit 1c1d7e
{
Packit 1c1d7e
  // States to pop
Packit 1c1d7e
  if (!g_indents.isEmpty() && indentLength < g_indents.top()) 
Packit 1c1d7e
  {
Packit 1c1d7e
    while (!g_indents.isEmpty() && indentLength < g_indents.top()) 
Packit 1c1d7e
    {
Packit 1c1d7e
      // printf("Exited scope indent of [%d]\n", g_indents.top());
Packit 1c1d7e
      g_indents.pop(); // Pop the old suite's indentation
Packit 1c1d7e
Packit 1c1d7e
      g_currentMemberDef=0;
Packit 1c1d7e
      if (g_currentDefinition) 
Packit 1c1d7e
	g_currentDefinition=g_currentDefinition->getOuterScope();
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  // Are there any remaining indentation levels for suites?
Packit 1c1d7e
  if (!g_indents.isEmpty()) 
Packit 1c1d7e
  {
Packit 1c1d7e
    BEGIN( Suite );
Packit 1c1d7e
  }
Packit 1c1d7e
  else 
Packit 1c1d7e
  {
Packit 1c1d7e
    BEGIN( Body );
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void parsePythonCode(CodeOutputInterface &od,const char * /*className*/,
Packit 1c1d7e
                 const QCString &s,bool exBlock, const char *exName,
Packit 1c1d7e
                 FileDef *fd,int startLine,int endLine,bool inlineFragment,
Packit 1c1d7e
                 MemberDef *,bool,Definition *searchCtx,bool collectXRefs) 
Packit 1c1d7e
{
Packit 1c1d7e
Packit 1c1d7e
  //printf("***parseCode()\n");
Packit 1c1d7e
  
Packit 1c1d7e
  //--------------------------------------
Packit 1c1d7e
  if (s.isEmpty()) return;
Packit 1c1d7e
  printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL);
Packit 1c1d7e
  TooltipManager::instance()->clearTooltips();
Packit 1c1d7e
  g_code = &od;
Packit 1c1d7e
  g_inputString   = s;
Packit 1c1d7e
  g_inputPosition = 0;
Packit 1c1d7e
  g_currentFontClass = 0;
Packit 1c1d7e
  g_needsTermination = FALSE;
Packit 1c1d7e
  g_searchCtx=searchCtx;
Packit 1c1d7e
  g_collectXRefs=collectXRefs;
Packit 1c1d7e
  if (startLine!=-1)
Packit 1c1d7e
    g_yyLineNr    = startLine;
Packit 1c1d7e
  else
Packit 1c1d7e
    g_yyLineNr    = 1;
Packit 1c1d7e
  if (endLine!=-1)
Packit 1c1d7e
    g_inputLines  = endLine+1;
Packit 1c1d7e
  else
Packit 1c1d7e
    g_inputLines  = g_yyLineNr + countLines() - 1;
Packit 1c1d7e
  
Packit 1c1d7e
  
Packit 1c1d7e
  g_exampleBlock  = exBlock; 
Packit 1c1d7e
  g_exampleName   = exName;
Packit 1c1d7e
  g_sourceFileDef = fd;
Packit 1c1d7e
Packit 1c1d7e
  bool cleanupSourceDef = FALSE;
Packit 1c1d7e
  if (exBlock && fd==0)
Packit 1c1d7e
  {
Packit 1c1d7e
    // create a dummy filedef for the example
Packit 1c1d7e
    g_sourceFileDef = new FileDef("",(exName?exName:"generated"));
Packit 1c1d7e
    cleanupSourceDef = TRUE;
Packit 1c1d7e
  }
Packit 1c1d7e
  if (g_sourceFileDef) 
Packit 1c1d7e
  {
Packit 1c1d7e
    setCurrentDoc("l00001");
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  g_includeCodeFragment = inlineFragment;
Packit 1c1d7e
  // Starts line 1 on the output  
Packit 1c1d7e
  startCodeLine();
Packit 1c1d7e
Packit 1c1d7e
  pycodeYYrestart( pycodeYYin );
Packit 1c1d7e
Packit 1c1d7e
  pycodeYYlex();
Packit 1c1d7e
Packit 1c1d7e
  if (!g_indents.isEmpty()) 
Packit 1c1d7e
  {
Packit 1c1d7e
    // printf("Exited pysourceparser in inconsistent state!\n");
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  if (g_needsTermination)
Packit 1c1d7e
  {
Packit 1c1d7e
    endCodeLine();
Packit 1c1d7e
  }
Packit 1c1d7e
  if (fd)
Packit 1c1d7e
  {
Packit 1c1d7e
    TooltipManager::instance()->writeTooltips(*g_code);
Packit 1c1d7e
  }
Packit 1c1d7e
  if (cleanupSourceDef)
Packit 1c1d7e
  {
Packit 1c1d7e
    // delete the temporary file definition used for this example
Packit 1c1d7e
    delete g_sourceFileDef;
Packit 1c1d7e
    g_sourceFileDef=0;
Packit 1c1d7e
  }
Packit 1c1d7e
  printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL);
Packit 1c1d7e
  return;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
#if !defined(YY_FLEX_SUBMINOR_VERSION) 
Packit 1c1d7e
extern "C" { // some bogus code to keep the compiler happy
Packit 1c1d7e
  void pycodeYYdummy() { yy_flex_realloc(0,0); } 
Packit 1c1d7e
}
Packit 1c1d7e
#elif YY_FLEX_MAJOR_VERSION<=2 && YY_FLEX_MINOR_VERSION<=5 && YY_FLEX_SUBMINOR_VERSION<33
Packit 1c1d7e
#error "You seem to be using a version of flex newer than 2.5.4. These are currently incompatible with 2.5.4, and do NOT work with doxygen! Please use version 2.5.4 or expect things to be parsed wrongly! A bug report has been submitted (#732132)."
Packit 1c1d7e
#endif
Packit 1c1d7e