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