summaryrefslogtreecommitdiffstats
path: root/src/pycode.l
diff options
context:
space:
mode:
Diffstat (limited to 'src/pycode.l')
-rw-r--r--src/pycode.l2402
1 files changed, 1188 insertions, 1214 deletions
diff --git a/src/pycode.l b/src/pycode.l
index f7e255f..65788cc 100644
--- a/src/pycode.l
+++ b/src/pycode.l
@@ -1,12 +1,10 @@
/******************************************************************************
*
- *
- *
- * Copyright (C) 1997-2015 by Dimitri van Heesch.
+ * Copyright (C) 1997-2020 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
+ * 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.
*
@@ -23,15 +21,24 @@
%option never-interactive
%option prefix="pycodeYY"
+%option reentrant
+%option extra-type="struct pycodeYY_state *"
+%option noyy_top_state
+%top{
+#include <stdint.h>
+}
%{
+#include <vector>
+#include <unordered_map>
+#include <string>
+#include <stack>
+
#include <stdio.h>
-#include <qvaluestack.h>
#include "pycode.h"
#include "message.h"
-
#include "scanner.h"
#include "entry.h"
#include "doxygen.h"
@@ -45,6 +52,8 @@
#include "filedef.h"
#include "namespacedef.h"
#include "tooltip.h"
+#include "scopedtypevariant.h"
+#include "symbolresolver.h"
// Toggle for some debugging info
//#define DBG_CTX(x) fprintf x
@@ -53,276 +62,913 @@
#define YY_NO_INPUT 1
#define YY_NO_UNISTD_H 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 const Definition *g_searchCtx;
-static bool g_collectXRefs;
-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_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 QCString g_docBlock; //!< contents of all lines of a documentation block
-static bool g_endComment;
-
-static void endFontClass();
-static void adjustScopesAndSuites(unsigned indentLength);
-static const char *stateToString(int state);
+#define USE_STATE2STRING 0
-/*! 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
+struct pycodeYY_state
{
- public:
- static const ClassDef *dummyContext;
- class Scope : public SDict<ClassDef>
- {
- public:
- Scope() : SDict<ClassDef>(17) {}
- };
-
- PyVariableContext()
- {
- m_scopes.setAutoDelete(TRUE);
- }
+ std::unordered_map< std::string, ScopedTypeVariant > codeClassMap;
+ QCString curClassName;
+ QStrList curClassBases;
+
+ CodeOutputInterface * code = 0;
+ const char * inputString = 0; //!< the code fragment as text
+ yy_size_t inputPosition = 0; //!< read offset during parsing
+ const char * currentFontClass = 0;
+ bool needsTermination = FALSE;
+ const Definition *searchCtx = 0;
+ bool collectXRefs = FALSE;
+ int inputLines = 0; //!< number of line in the code fragment
+ int yyLineNr = 0; //!< current line number
+ FileDef * sourceFileDef = 0;
+ const Definition * currentDefinition = 0;
+ const MemberDef * currentMemberDef = 0;
+ bool includeCodeFragment = FALSE;
+ QCString realScope;
+ int bodyCurlyCount = 0;
+ bool searchingForBody = FALSE;
+ QCString classScope;
+ int paramParens = 0;
+
+ bool exampleBlock = FALSE;
+ QCString exampleName;
+
+ QCString type;
+ QCString name;
+
+ bool doubleStringIsDoc = FALSE;
+ bool doubleQuote = FALSE;
+ bool noSuiteFound = FALSE;
+ int stringContext = 0;
+
+ std::stack<yy_size_t> indents; //!< Tracks indentation levels for scoping in python
+
+ QCString docBlock; //!< contents of all lines of a documentation block
+ bool endComment = FALSE;
+ VariableContext theVarContext;
+ CallContext theCallContext;
+ SymbolResolver symbolResolver;
+};
- virtual ~PyVariableContext()
- {
- }
-
- void pushScope()
- {
- m_scopes.append(new Scope);
- }
- void popScope()
- {
- if (m_scopes.count()>0)
- {
- m_scopes.remove(m_scopes.count()-1);
- }
- }
+#if USE_STATE2STRING
+static const char *stateToString(int state);
+#endif
+
+static void startCodeLine(yyscan_t yyscanner);
+static int countLines(yyscan_t yyscanner);
+static void setCurrentDoc(yyscan_t yyscanner, const QCString &anchor);
+static void addToSearchIndex(yyscan_t yyscanner, const char *text);
+static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definition *d);
+static void codify(yyscan_t yyscanner,const char* text);
+static void endCodeLine(yyscan_t yyscanner);
+static void nextCodeLine(yyscan_t yyscanner);
+static void writeMultiLineCodeLink(yyscan_t yyscanner, CodeOutputInterface &ol, const Definition *d, const char *text);
+static void startFontClass(yyscan_t yyscanner,const char *s);
+static void endFontClass(yyscan_t yyscanner);
+static void codifyLines(yyscan_t yyscanner,const char *text);
+static bool getLinkInScope(yyscan_t yyscanner, const QCString &c, const QCString &m,
+ const char *memberText, CodeOutputInterface &ol, const char *text);
+static bool getLink(yyscan_t yyscanner, const char *className, const char *memberName,
+ CodeOutputInterface &ol, const char *text=0);
+static void generateClassOrGlobalLink(yyscan_t yyscanner, CodeOutputInterface &ol,
+ const char *clName, bool typeOnly=FALSE);
+static void generateFunctionLink(yyscan_t yyscanner, CodeOutputInterface &ol,
+ const char *funcName);
+static bool findMemberLink(yyscan_t yyscanner, CodeOutputInterface &ol,
+ Definition *sym, const char *symName);
+static void findMemberLink(yyscan_t yyscanner, CodeOutputInterface &ol,
+ const char *symName);
+static void adjustScopesAndSuites(yyscan_t yyscanner,unsigned indentLength);
+static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
+
+#if 0 // TODO: call me to store local variables and get better syntax highlighting, see code.l
+static void addVariable(yyscan_t yyscanner, QCString type, QCString name);
+#endif
+
+//-------------------------------------------------------------------
+
+static std::mutex g_searchIndexMutex;
+static std::mutex g_docCrossReferenceMutex;
+static std::mutex g_countFlowKeywordsMutex;
+
+//-------------------------------------------------------------------
- void clear()
- {
- m_scopes.clear();
- m_globalScope.clear();
- }
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
- 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)
+BB [ \t]+
+B [ \t]*
+NEWLINE \n
+
+DIGIT [0-9]
+LETTER [A-Za-z\x80-\xFF]
+NONEMPTY [A-Za-z0-9_\x80-\xFF]
+EXPCHAR [#(){}\[\],:.%/\\=`*~|&<>!;+-]
+NONEMPTYEXP [^ \t\n:]
+PARAMNONEMPTY [^ \t\n():]
+IDENTIFIER ({LETTER}|"_")({LETTER}|{DIGIT}|"_")*
+SCOPE {IDENTIFIER}("."{IDENTIFIER})*
+CALLANY "("[^)]*")"
+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"|"with"|"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 stack
+
+%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
+
+%x DocBlock
+%%
+
+<Body,Suite>{
+ "def"{BB} {
+ startFontClass(yyscanner,"keyword");
+ codify(yyscanner,yytext);
+ endFontClass(yyscanner);
+ BEGIN( FunctionDec );
+ }
+
+ "class"{BB} {
+ startFontClass(yyscanner,"keyword");
+ codify(yyscanner,yytext);
+ endFontClass(yyscanner);
+ BEGIN( ClassDec );
+ }
+ "None" {
+ startFontClass(yyscanner,"keywordtype");
+ codify(yyscanner,yytext);
+ endFontClass(yyscanner);
+ }
+ "self."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" {
+ codify(yyscanner,"self.");
+ findMemberLink(yyscanner,*yyextra->code,&yytext[5]);
+ }
+ "self."{IDENTIFIER}/"(" {
+ codify(yyscanner,"self.");
+ findMemberLink(yyscanner,*yyextra->code,&yytext[5]);
+ }
+ "self."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} {
+ codify(yyscanner,"self.");
+ findMemberLink(yyscanner,*yyextra->code,&yytext[5]);
+ }
+ "self."{IDENTIFIER} {
+ codify(yyscanner,"self.");
+ findMemberLink(yyscanner,*yyextra->code,&yytext[5]);
+ }
+ "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" {
+ codify(yyscanner,"cls.");
+ findMemberLink(yyscanner,*yyextra->code,&yytext[4]);
+ }
+ "cls."{IDENTIFIER}/"(" {
+ codify(yyscanner,"cls.");
+ findMemberLink(yyscanner,*yyextra->code,&yytext[4]);
+ }
+ "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} {
+ codify(yyscanner,"cls.");
+ findMemberLink(yyscanner,*yyextra->code,&yytext[4]);
+ }
+ "cls."{IDENTIFIER} {
+ codify(yyscanner,"cls.");
+ findMemberLink(yyscanner,*yyextra->code,&yytext[4]);
+ }
+ "@"{SCOPE}{CALLANY}? { // decorator
+ startFontClass(yyscanner,"preprocessor");
+ codify(yyscanner,yytext);
+ endFontClass(yyscanner);
+ }
+}
+
+<ClassDec>{IDENTIFIER} {
+ generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
+ // codify(yyscanner,yytext);
+ yyextra->curClassName = yytext;
+ yyextra->curClassBases.clear();
+ BEGIN( ClassInheritance );
+ }
+
+<ClassInheritance>{
+ ({BB}|[(,)]) {
+ codify(yyscanner,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.
+
+ yyextra->curClassBases.inSort(yytext);
+ generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
+ // codify(yyscanner,yytext);
+ }
+
+ ":" {
+ codify(yyscanner,yytext);
+
+ // Assume this will
+ // be a one-line suite;
+ // found counter-example
+ // in SuiteStart.
+
+ // Push a class scope
+
+ std::unique_ptr<ClassDef> classDefToAdd { createClassDef("<code>",1,1,yyextra->curClassName,ClassDef::Class,0,0,FALSE) };
+ ScopedTypeVariant var(yyextra->curClassName);
+ char *s=yyextra->curClassBases.first();
+ while (s)
+ {
+ const ClassDef *baseDefToAdd = 0;
+ // find class in the local scope
+ auto it = yyextra->codeClassMap.find(s);
+ if (it != yyextra->codeClassMap.end())
+ {
+ baseDefToAdd = toClassDef(it->second.globalDef());
+ }
+ // Try to find class in global scope
+ if (baseDefToAdd==0)
+ {
+ baseDefToAdd=yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,s);
+ }
+
+ if (baseDefToAdd && baseDefToAdd->name()!=yyextra->curClassName)
+ {
+ var.localDef()->insertBaseClass(baseDefToAdd->name());
+ }
+
+ s=yyextra->curClassBases.next();
+ }
+ yyextra->codeClassMap.emplace(std::make_pair(yyextra->curClassName.str(),std::move(var)));
+
+ // Reset class-parsing variables.
+ yyextra->curClassName.resize(0);
+ yyextra->curClassBases.clear();
+
+ yyextra->noSuiteFound = TRUE;
+ BEGIN( SuiteStart );
+ }
+}
+
+
+<FunctionDec>{
+ {IDENTIFIER} {
+ generateFunctionLink(yyscanner,*yyextra->code,yytext);
+ }
+
+ {B}"(" {
+ codify(yyscanner,yytext);
+ BEGIN( FunctionParams );
+ }
+}
+
+<FunctionParams>{
+ ({BB}|",") {
+ // Parses delimiters
+ codify(yyscanner,yytext);
+ }
+
+ ({IDENTIFIER}|{PARAMNONEMPTY}+) {
+ codify(yyscanner,yytext);
+ }
+
+ ")" {
+ codify(yyscanner,yytext);
+ }
+
+ "\n" {
+ codifyLines(yyscanner,yytext);
+ }
+
+ ":" {
+ codify(yyscanner,yytext);
+
+ // Assume this will
+ // be a one-line suite;
+ // found counter-example
+ // in SuiteStart.
+ yyextra->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(yyscanner,"keyword");
+ codify(yyscanner,yytext);
+ endFontClass(yyscanner);
+ }
+
+ {FLOWKW} {
+ if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction())
+ {
+ std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex);
+ MemberDefMutable *mdm = toMemberDefMutable(yyextra->currentMemberDef);
+ if (mdm)
+ {
+ mdm->incrementFlowKeyWordCount();
+ }
+ }
+ startFontClass(yyscanner,"keywordflow");
+ codify(yyscanner,yytext);
+ endFontClass(yyscanner);
+ }
+ ({IDENTIFIER}".")*{IDENTIFIER}/"(" {
+ generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
+ }
+ ({IDENTIFIER}".")+{IDENTIFIER} {
+ generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,TRUE);
+ }
+ {IDENTIFIER} { codify(yyscanner,yytext); }
+
+}
+
+
+
+<SuiteStart>{
+
+ {BB} {
+ codify(yyscanner,yytext);
+ }
+ "pass" {
+ startFontClass(yyscanner,"keyword");
+ codifyLines(yyscanner,yytext);
+ endFontClass(yyscanner);
+ BEGIN(Body);
+ }
+ {KEYWORD} {
+ startFontClass(yyscanner,"keyword");
+ codifyLines(yyscanner,yytext);
+ endFontClass(yyscanner);
+
+ // No indentation necessary
+ yyextra->noSuiteFound = FALSE;
+ }
+
+ {FLOWKW} {
+ if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction())
+ {
+ std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex);
+ MemberDefMutable *mdm = toMemberDefMutable(yyextra->currentMemberDef);
+ if (mdm)
+ {
+ mdm->incrementFlowKeyWordCount();
+ }
+ }
+ startFontClass(yyscanner,"keywordflow");
+ codifyLines(yyscanner,yytext);
+ endFontClass(yyscanner);
+
+ // No indentation necessary
+ yyextra->noSuiteFound = FALSE;
+ }
+ {IDENTIFIER} {
+ codify(yyscanner,yytext);
+ }
+
+
+ {POUNDCOMMENT} {
+ if (YY_START==SingleQuoteString ||
+ YY_START==DoubleQuoteString ||
+ YY_START==TripleString
+ )
+ {
+ REJECT;
+ }
+ yy_push_state(YY_START,yyscanner);
+ BEGIN(DocBlock);
+ yyextra->docBlock=yytext;
+ }
+
+ {NEWLINE} {
+ codifyLines(yyscanner,yytext);
+ if ( yyextra->noSuiteFound )
+ {
+ // printf("New suite to capture! [%d]\n", yyextra->yyLineNr);
+ BEGIN ( SuiteCaptureIndent );
+ }
+ }
+}
+
+<SuiteCaptureIndent>{
+ "\n"|({BB}"\n") {
+ // Blankline - ignore, keep looking for indentation.
+ codifyLines(yyscanner,yytext);
+ }
+
+ {BB} {
+ // This state lasts momentarily,
+ // to check the indentation
+ // level that is about to be
+ // used.
+ codifyLines(yyscanner,yytext);
+ yyextra->indents.push(yyleng);
+ // printf("Captured indent of %d [line %d]\n", yyleng, yyextra->yyLineNr);
+ BEGIN( Suite );
+ }
+}
+
+<SuiteMaintain>{
+
+ {BB}/({NONEMPTY}|{EXPCHAR}) {
+ // This implements poor
+ // indentation-tracking;
+ // should be improved.
+ // (translate tabs to space, etc)
+ codifyLines(yyscanner,yytext);
+ adjustScopesAndSuites(yyscanner,static_cast<int>(yyleng));
+ }
+
+ "\n"|({BB}"\n") {
+ // If this ever succeeds,
+ // it means that this is
+ // a blank line, and
+ // can be ignored.
+ codifyLines(yyscanner,yytext);
+ }
+
+ ""/({NONEMPTY}|{EXPCHAR}) {
+ // Default rule; matches
+ // the empty string, assuming
+ // real text starts here.
+ // Just go straight to Body.
+ adjustScopesAndSuites(yyscanner,0);
+ }
+}
+
+
+<Suite>{NEWLINE} {
+ codifyLines(yyscanner,yytext);
+ BEGIN( SuiteMaintain );
+ }
+<Body>{IDENTIFIER} {
+ codify(yyscanner,yytext);
+ }
+<Body>{NEWLINE} {
+ codifyLines(yyscanner,yytext);
+ }
+
+<SingleQuoteString>{ // Single quoted string like 'That\'s a """nice""" string!'
+ \\{B}\n { // line continuation
+ codifyLines(yyscanner,yytext);
+ }
+ \\. { // escaped char
+ codify(yyscanner,yytext);
+ }
+ {STRINGPREFIX}?{TRIDOUBLEQUOTE} { // triple double quotes
+ codify(yyscanner,yytext);
+ }
+ "'" { // end of the string
+ codify(yyscanner,yytext);
+ endFontClass(yyscanner);
+ BEGIN(yyextra->stringContext);
+ }
+ [^"'\n\\]+ { // normal chars
+ codify(yyscanner,yytext);
+ }
+ . { // normal char
+ codify(yyscanner,yytext);
+ }
+}
+
+<DoubleQuoteString>{ // Double quoted string like "That's \"a '''nice'''\" string!"
+ \\{B}\n { // line continuation
+ codifyLines(yyscanner,yytext);
+ }
+ \\. { // escaped char
+ codify(yyscanner,yytext);
+ }
+ {STRINGPREFIX}?{TRISINGLEQUOTE} { // triple single quotes
+ codify(yyscanner,yytext);
+ }
+ "\"" { // end of the string
+ codify(yyscanner,yytext);
+ endFontClass(yyscanner);
+ BEGIN(yyextra->stringContext);
+ }
+ [^"'\n\\]+ { // normal chars
+ codify(yyscanner,yytext);
+ }
+ . { // normal char
+ codify(yyscanner,yytext);
+ }
+}
+
+<TripleString>{
+ {TRIDOUBLEQUOTE} |
+ {TRISINGLEQUOTE} {
+ codify(yyscanner,yytext);
+ if (yyextra->doubleQuote==(yytext[0]=='"'))
+ {
+ endFontClass(yyscanner);
+ BEGIN(yyextra->stringContext);
+ }
+ }
+ {LONGSTRINGBLOCK} {
+ codifyLines(yyscanner,yytext);
+ }
+ \n {
+ codifyLines(yyscanner,yytext);
+ }
+ . {
+ codify(yyscanner,yytext);
+ }
+}
+
+
+<*>{STRINGPREFIX}?{TRISINGLEQUOTE} {
+ if (YY_START==SingleQuoteString) REJECT;
+ startFontClass(yyscanner,"stringliteral");
+ yyextra->stringContext=YY_START;
+ yyextra->doubleQuote=yytext[yyleng-1]=='"';
+ codify(yyscanner,yytext);
+ BEGIN(TripleString);
+ }
+<*>{STRINGPREFIX}?{TRIDOUBLEQUOTE} {
+ if (YY_START==DoubleQuoteString) REJECT;
+ startFontClass(yyscanner,"stringliteral");
+ yyextra->stringContext=YY_START;
+ yyextra->doubleQuote=yytext[yyleng-1]=='"';
+ codify(yyscanner,yytext);
+ BEGIN(TripleString);
+ }
+<*>{STRINGPREFIX}?"'" { // single quoted string
+ if (YY_START==SingleQuoteString ||
+ YY_START==DoubleQuoteString ||
+ YY_START==TripleString)
+ {
+ REJECT;
+ }
+ startFontClass(yyscanner,"stringliteral");
+ yyextra->stringContext=YY_START;
+ codify(yyscanner,yytext);
+ BEGIN(SingleQuoteString);
+ }
+<*>{STRINGPREFIX}?"\"" { // double quoted string
+ if (YY_START==SingleQuoteString ||
+ YY_START==DoubleQuoteString ||
+ YY_START==TripleString)
+ {
+ REJECT;
+ }
+ startFontClass(yyscanner,"stringliteral");
+ yyextra->stringContext=YY_START;
+ codify(yyscanner,yytext);
+ BEGIN(DoubleQuoteString);
+ }
+<DocBlock>.* { // contents of current comment line
+ yyextra->docBlock+=yytext;
+ }
+<DocBlock>"\n"{B}("#") { // comment block (next line is also comment line)
+ yyextra->docBlock+=yytext;
+ }
+<DocBlock>{NEWLINE} { // comment block ends at the end of this line
+ // remove special comment (default config)
+ if (Config_getBool(STRIP_CODE_COMMENTS))
+ {
+ yyextra->yyLineNr+=((QCString)yyextra->docBlock).contains('\n');
+ yyextra->endComment=TRUE;
+ }
+ else // do not remove comment
+ {
+ startFontClass(yyscanner,"comment");
+ codifyLines(yyscanner,yyextra->docBlock);
+ endFontClass(yyscanner);
+ }
+ unput(*yytext);
+ yy_pop_state(yyscanner);
+ }
+<*>{POUNDCOMMENT}.* {
+ if (YY_START==SingleQuoteString ||
+ YY_START==DoubleQuoteString ||
+ YY_START==TripleString)
+ {
+ REJECT;
+ }
+ yy_push_state(YY_START,yyscanner);
+ BEGIN(DocBlock);
+ yyextra->docBlock=yytext;
+ }
+<*>"#".* { // normal comment
+ if (YY_START==SingleQuoteString ||
+ YY_START==DoubleQuoteString ||
+ YY_START==TripleString)
+ {
+ REJECT;
+ }
+ startFontClass(yyscanner,"comment");
+ codifyLines(yyscanner,yytext);
+ endFontClass(yyscanner);
+ }
+<*>{NEWLINE} {
+ if (yyextra->endComment)
+ {
+ yyextra->endComment=FALSE;
+ }
+ else
+ {
+ codifyLines(yyscanner,yytext);
+ }
+ //printf("[pycode] %d NEWLINE [line %d] no match\n",
+ // YY_START, yyextra->yyLineNr);
+
+ BEGIN(Body);
+ }
+
+<*>[ \t]+ {
+ codify(yyscanner,yytext);
+ BEGIN(Body);
+ }
+<*>. {
+ codify(yyscanner,yytext);
+ // printf("[pycode] '%s' [ state %d ] [line %d] no match\n",
+ // yytext, YY_START, yyextra->yyLineNr);
+
+ BEGIN(Body);
+ }
+
+<*><<EOF>> {
+ if (YY_START==DocBlock && !Config_getBool(STRIP_CODE_COMMENTS))
+ {
+ startFontClass(yyscanner,"comment");
+ codifyLines(yyscanner,yyextra->docBlock);
+ endFontClass(yyscanner);
+ }
+ yyterminate();
+ }
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+#if 0 // TODO: call me to store local variables and get better syntax highlighting, see code.l
+static void addVariable(yyscan_t yyscanner, QCString type, QCString name)
{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
//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();
- const 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
- )
+ auto it = yyextra->codeClassMap.find(ltype.str());
+ if (it!=yyextra->codeClassMap.end())
{
- scope->append(lname,varType); // add it to a list
+ yyextra->theVarContext.addVariable(lname,std::move(it->second));
}
- else
+ 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!
+ const ClassDef *varType = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,ltype); // look for global class definitions
+ if (varType)
{
- scope->append(lname,dummyContext);
+ yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varType));
+ }
+ else
+ {
+ if (!yyextra->theVarContext.atGlobalScope()) // for local variable add a dummy entry to avoid linking to a global that is shadowed.
+ {
+ yyextra->theVarContext.addVariable(lname.str(),ScopedTypeVariant());
+ }
}
}
}
+#endif
+
+//-------------------------------------------------------------------------------
-ClassDef *PyVariableContext::findVariable(const QCString &name)
+static yy_size_t yyread(yyscan_t yyscanner, char *buf,yy_size_t max_size)
{
- 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)
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ yy_size_t inputPosition = yyextra->inputPosition;
+ const char *s = yyextra->inputString + inputPosition;
+ yy_size_t c=0;
+ while( c < max_size && *s )
{
- result = scope->find(name);
- if (result)
- {
- return result;
- }
+ *buf++ = *s++;
+ c++;
}
- // nothing found -> also try the global scope
- result=m_globalScope.find(name);
- return result;
+ yyextra->inputPosition += c;
+ return c;
}
-static PyVariableContext g_theVarContext;
-const ClassDef *PyVariableContext::dummyContext = (ClassDef*)0x8;
+//-------------------------------------------------------------------------------
-class PyCallContext
+/*!
+ Examines current stack of white-space indentations;
+ re-syncs the parser with the correct scope.
+*/
+static void adjustScopesAndSuites(yyscan_t yyscanner,unsigned indentLength)
{
- public:
- struct Ctx
- {
- Ctx() : name(g_name), type(g_type), cd(0) {}
- QCString name;
- QCString type;
- const ClassDef *cd;
- };
-
- PyCallContext()
- {
- m_classList.append(new Ctx);
- m_classList.setAutoDelete(TRUE);
- }
-
- virtual ~PyCallContext() {}
-
- void setClass(const 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);
- }
-
- const ClassDef *getClass() const
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ // States to pop
+ if (!yyextra->indents.empty() && indentLength < yyextra->indents.top())
+ {
+ while (!yyextra->indents.empty() && indentLength < yyextra->indents.top())
{
- Ctx *ctx = m_classList.getLast();
+ // printf("Exited scope indent of [%d]\n", yyextra->indents.top());
+ yyextra->indents.pop(); // Pop the old suite's indentation
- if (ctx)
- return ctx->cd;
- else
- return 0;
+ yyextra->currentMemberDef=0;
+ if (yyextra->currentDefinition)
+ yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope();
}
+ }
- private:
- QList<Ctx> m_classList;
-};
-
-static PyCallContext g_theCallContext;
+ // Are there any remaining indentation levels for suites?
+ if (!yyextra->indents.empty())
+ {
+ BEGIN( Suite );
+ }
+ else
+ {
+ BEGIN( Body );
+ }
+}
+//-------------------------------------------------------------------------------
/*! counts the number of lines in the input */
-static int countLines()
+static int countLines(yyscan_t yyscanner)
{
- const char *p=g_inputString;
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ const char *p=yyextra->inputString;
char c;
int count=1;
- while ((c=*p))
- {
- p++ ;
- if (c=='\n') count++;
+ while ((c=*p))
+ {
+ p++;
+ if (c=='\n') count++;
}
- if (p>g_inputString && *(p-1)!='\n')
+ if (p>yyextra->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;
- }
+ count++;
+ yyextra->needsTermination=TRUE;
+ }
return count;
}
-static void setCurrentDoc(const QCString &anchor)
+//-------------------------------------------------------------------------------
+
+static void setCurrentDoc(yyscan_t yyscanner, const QCString &anchor)
{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
if (Doxygen::searchIndex)
{
- if (g_searchCtx)
+ std::lock_guard<std::mutex> lock(g_searchIndexMutex);
+ if (yyextra->searchCtx)
{
- Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE);
+ yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE);
}
else
{
- Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE);
+ yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,TRUE);
}
}
}
-static void addToSearchIndex(const char *text)
+//-------------------------------------------------------------------------------
+
+static void addToSearchIndex(yyscan_t yyscanner, const char *text)
{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
if (Doxygen::searchIndex)
{
- Doxygen::searchIndex->addWord(text,FALSE);
+ std::lock_guard<std::mutex> lock(g_searchIndexMutex);
+ yyextra->code->addWord(text,FALSE);
}
}
+//-------------------------------------------------------------------------------
-static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition)
+static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definition *d)
{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
int pos=0;
QCString type = s;
QCString className;
@@ -330,15 +976,14 @@ static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefin
while (extractClassNameFromType(type,pos,className,templSpec)!=-1)
{
QCString clName=className+templSpec;
-
const ClassDef *cd=0;
- if (!g_classScope.isEmpty())
+ if (!yyextra->classScope.isEmpty())
{
- cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName);
+ cd=yyextra->symbolResolver.resolveClass(d,yyextra->classScope+"::"+clName);
}
if (cd==0)
{
- cd=getResolvedClass(d,g_sourceFileDef,clName);
+ cd=yyextra->symbolResolver.resolveClass(d,clName);
}
if (cd)
{
@@ -349,104 +994,117 @@ static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefin
return 0;
}
+//-------------------------------------------------------------------------------
-
-/*! start a new line of code, inserting a line number if g_sourceFileDef
+/*! start a new line of code, inserting a line number if yyextra->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()
+static void startCodeLine(yyscan_t yyscanner)
{
- //if (g_currentFontClass) { g_code->endFontClass(); }
- if (g_sourceFileDef)
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ //if (yyextra->currentFontClass) { yyextra->code->endFontClass(yyscanner); }
+ if (yyextra->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())
+ //lineNumber.sprintf("%05d",yyextra->yyLineNr);
+ //lineAnchor.sprintf("l%05d",yyextra->yyLineNr);
+
+ const Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr);
+ //printf("startCodeLine %d d=%p\n",yyextra->yyLineNr,d);
+ //yyextra->code->startLineNumber();
+
+ if (!yyextra->includeCodeFragment && d && d->isLinkableInProject())
{
- g_currentDefinition = d;
- g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr);
- //g_insideBody = FALSE;
- g_endComment = 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;
+ yyextra->currentDefinition = d;
+ yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr);
+ //yyextra->insideBody = FALSE;
+ yyextra->endComment = FALSE;
+ yyextra->searchingForBody = TRUE;
+ yyextra->realScope = d->name().copy();
+ yyextra->classScope = d->name().copy();
+ //printf("Real scope: '%s'\n",yyextra->realScope.data());
+ yyextra->bodyCurlyCount = 0;
QCString lineAnchor;
- lineAnchor.sprintf("l%05d",g_yyLineNr);
- if (g_currentMemberDef)
+ lineAnchor.sprintf("l%05d",yyextra->yyLineNr);
+ if (yyextra->currentMemberDef)
{
- g_code->writeLineNumber(g_currentMemberDef->getReference(),
- g_currentMemberDef->getOutputFileBase(),
- g_currentMemberDef->anchor(),g_yyLineNr);
- setCurrentDoc(lineAnchor);
+ yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
+ yyextra->currentMemberDef->getOutputFileBase(),
+ yyextra->currentMemberDef->anchor(),yyextra->yyLineNr);
+ setCurrentDoc(yyscanner,lineAnchor);
}
else
{
- g_code->writeLineNumber(d->getReference(),
- d->getOutputFileBase(),
- 0,g_yyLineNr);
- setCurrentDoc(lineAnchor);
+ yyextra->code->writeLineNumber(d->getReference(),
+ d->getOutputFileBase(),
+ 0,yyextra->yyLineNr);
+ setCurrentDoc(yyscanner,lineAnchor);
}
}
else
{
- //g_code->codify(lineNumber);
- g_code->writeLineNumber(0,0,0,g_yyLineNr);
+ //yyextra->code->codify(lineNumber);
+ yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr);
}
- //g_code->endLineNumber();
+ //yyextra->code->endLineNumber();
}
- g_code->startCodeLine(g_sourceFileDef);
- if (g_currentFontClass)
+ yyextra->code->startCodeLine(yyextra->sourceFileDef);
+ if (yyextra->currentFontClass)
{
- g_code->startFontClass(g_currentFontClass);
+ yyextra->code->startFontClass(yyextra->currentFontClass);
}
}
-static void codify(const char* text)
-{
- g_code->codify(text);
+//-------------------------------------------------------------------------------
+
+static void codify(yyscan_t yyscanner,const char* text)
+{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ yyextra->code->codify(text);
}
-static void endCodeLine()
+//-------------------------------------------------------------------------------
+
+static void endCodeLine(yyscan_t yyscanner)
{
- endFontClass();
- g_code->endCodeLine();
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ endFontClass(yyscanner);
+ yyextra->code->endCodeLine();
}
-static void nextCodeLine()
+//-------------------------------------------------------------------------------
+
+static void nextCodeLine(yyscan_t yyscanner)
{
- const char *fc = g_currentFontClass;
- endCodeLine();
- if (g_yyLineNr<g_inputLines)
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ const char *fc = yyextra->currentFontClass;
+ endCodeLine(yyscanner);
+ if (yyextra->yyLineNr<yyextra->inputLines)
{
- g_currentFontClass = fc;
- startCodeLine();
+ yyextra->currentFontClass = fc;
+ startCodeLine(yyscanner);
}
}
+//-------------------------------------------------------------------------------
/*! 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
+ * 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,
+static void writeMultiLineCodeLink(yyscan_t yyscanner,
+ CodeOutputInterface &ol,
const Definition *d,
const char *text)
{
- static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS);
- TooltipManager::instance()->addTooltip(d);
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS);
+ TooltipManager::instance().addTooltip(ol,d);
QCString ref = d->getReference();
QCString file = d->getOutputFileBase();
QCString anchor = d->anchor();
- QCString tooltip;
+ QCString tooltip;
if (!sourceTooltips) // fall back to simple "title" tooltips
{
tooltip = d->briefDescriptionAsTooltip();
@@ -460,11 +1118,11 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol,
while ((c=*p++) && c!='\n') { }
if (c=='\n')
{
- g_yyLineNr++;
+ yyextra->yyLineNr++;
*(p-1)='\0';
//printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
ol.writeCodeLink(ref,file,anchor,sp,tooltip);
- nextCodeLine();
+ nextCodeLine(yyscanner);
}
else
{
@@ -475,141 +1133,150 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol,
}
}
-static void startFontClass(const char *s)
+//-------------------------------------------------------------------------------
+
+static void startFontClass(yyscan_t yyscanner,const char *s)
{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
// if font class is already set don't stop and start it.
// strcmp does not like null pointers as input.
- if (!g_currentFontClass || !s || strcmp(g_currentFontClass,s))
+ if (!yyextra->currentFontClass || !s || strcmp(yyextra->currentFontClass,s))
{
- endFontClass();
- g_code->startFontClass(s);
- g_currentFontClass=s;
+ endFontClass(yyscanner);
+ yyextra->code->startFontClass(s);
+ yyextra->currentFontClass=s;
}
}
-static void endFontClass()
+//-------------------------------------------------------------------------------
+
+static void endFontClass(yyscan_t yyscanner)
{
- if (g_currentFontClass)
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ if (yyextra->currentFontClass)
{
- g_code->endFontClass();
- g_currentFontClass=0;
+ yyextra->code->endFontClass();
+ yyextra->currentFontClass=0;
}
}
-static void codifyLines(char *text)
+//-------------------------------------------------------------------------------
+
+static void codifyLines(yyscan_t yyscanner,const char *text)
{
- //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text);
- char *p=text,*sp=p;
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ //printf("codifyLines(%d,\"%s\")\n",yyextra->yyLineNr,text);
+ const char *p=text,*sp=p;
char c;
bool done=FALSE;
- const char * tmp_currentFontClass = g_currentFontClass;
while (!done)
{
sp=p;
while ((c=*p++) && c!='\n') { }
if (c=='\n')
{
- g_yyLineNr++;
- *(p-1)='\0';
- g_code->codify(sp);
- endCodeLine();
- if (g_yyLineNr<g_inputLines)
- {
- startCodeLine();
- }
- if (tmp_currentFontClass)
- {
- startFontClass(tmp_currentFontClass);
- }
+ yyextra->yyLineNr++;
+ int l = (int)(p-sp-1);
+ char *tmp = (char*)malloc(l+1);
+ memcpy(tmp,sp,l);
+ tmp[l]='\0';
+ yyextra->code->codify(tmp);
+ free(tmp);
+ nextCodeLine(yyscanner);
}
else
{
- g_code->codify(sp);
+ yyextra->code->codify(sp);
done=TRUE;
}
}
}
-static void codifyLines(const QCString &str)
-{
- char *tmp= (char *)malloc(str.length()+1);
- qstrcpy(tmp, str);
- codifyLines(tmp);
- free(tmp);
-}
+//-------------------------------------------------------------------------------
-static bool getLinkInScope(const QCString &c, // scope
+static bool getLinkInScope(yyscan_t yyscanner,
+ const QCString &c, // scope
const QCString &m, // member
- const char *memberText, // exact text
- CodeOutputInterface &ol,
- const char *text
- )
+ const char *memberText, // exact text
+ CodeOutputInterface &ol,
+ const char *text
+ )
{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
const MemberDef *md = 0;
const ClassDef *cd = 0;
const FileDef *fd = 0;
const NamespaceDef *nd = 0;
const GroupDef *gd = 0;
//printf("Trying '%s'::'%s'\n",c.data(),m.data());
- if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef) &&
+ if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,yyextra->sourceFileDef) &&
md->isLinkable())
{
//Definition *d=0;
//if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd;
const Definition *d = md->getOuterScope()==Doxygen::globalScope ?
- md->getBodyDef() : md->getOuterScope();
+ 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);
+ yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope())));
+ //printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p\n",
+ // yyextra->currentDefinition,yyextra->currentMemberDef);
- if (g_currentDefinition && g_currentMemberDef &&
- md!=g_currentMemberDef && g_collectXRefs)
+ if (yyextra->currentDefinition && yyextra->currentMemberDef &&
+ md!=yyextra->currentMemberDef && yyextra->collectXRefs)
{
- addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md));
+ std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex);
+ addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(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, text ? text : memberText);
- addToSearchIndex(text ? text : memberText);
+
+ writeMultiLineCodeLink(yyscanner,ol,md, text ? text : memberText);
+ addToSearchIndex(yyscanner,text ? text : memberText);
return TRUE;
- }
+ }
}
return FALSE;
}
-static bool getLink(const char *className,
+//-------------------------------------------------------------------------------
+
+static bool getLink(yyscan_t yyscanner,
+ const char *className,
const char *memberName,
- CodeOutputInterface &ol,
- const char *text=0)
+ CodeOutputInterface &ol,
+ const char *text)
{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
QCString m=removeRedundantWhiteSpace(memberName);
QCString c=className;
- if (!getLinkInScope(c,m,memberName,ol,text))
+ if (!getLinkInScope(yyscanner,c,m,memberName,ol,text))
{
- if (!g_curClassName.isEmpty())
+ if (!yyextra->curClassName.isEmpty())
{
if (!c.isEmpty()) c.prepend("::");
- c.prepend(g_curClassName);
- return getLinkInScope(c,m,memberName,ol,text);
+ c.prepend(yyextra->curClassName);
+ return getLinkInScope(yyscanner,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)
+static void generateClassOrGlobalLink(yyscan_t yyscanner,
+ CodeOutputInterface &ol,
+ const char *clName,
+ bool typeOnly)
{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
QCString className=clName;
// Don't do anything for empty text
@@ -617,20 +1284,22 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
DBG_CTX((stderr,"generateClassOrGlobalLink(className=%s)\n",className.data()));
- const ClassDef *cd=0,*lcd=0; /** Class def that we may find */
- const MemberDef *md=0; /** Member def that we may find */
+ const ScopedTypeVariant *lcd = 0;
+ const ClassDef *cd=0; // Class def that we may find
+ const MemberDef *md=0; // Member def that we may find
//bool isLocal=FALSE;
- if ((lcd=g_theVarContext.findVariable(className))==0) // not a local variable
+ if ((lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable
{
- Definition *d = g_currentDefinition;
+ const Definition *d = yyextra->currentDefinition;
QCString scope = substitute(className,".","::");
- cd = getResolvedClass(d,g_sourceFileDef,substitute(className,".","::"),&md);
+ cd = yyextra->symbolResolver.resolveClass(d,substitute(className,".","::"));
+ md = yyextra->symbolResolver.getTypedef();
- DBG_CTX((stderr,"d=%s g_sourceFileDef=%s\n",
+ DBG_CTX((stderr,"d=%s yyextra->sourceFileDef=%s\n",
d?d->displayName().data():"<null>",
- g_currentDefinition?g_currentDefinition->displayName().data():"<null>"));
+ yyextra->currentDefinition?yyextra->currentDefinition->displayName().data():"<null>"));
DBG_CTX((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
@@ -638,21 +1307,21 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
const NamespaceDef *nd = getResolvedNamespace(scope);
if (nd)
{
- writeMultiLineCodeLink(ol,nd,clName);
- addToSearchIndex(className);
+ writeMultiLineCodeLink(yyscanner,ol,nd,clName);
+ addToSearchIndex(yyscanner,className);
return;
}
- else if (getLink(g_classScope,clName,ol,clName))
+ else if (getLink(yyscanner,yyextra->classScope,clName,ol,clName))
{
- return;
+ return;
}
}
}
else
{
- if (lcd!=PyVariableContext::dummyContext)
+ if (lcd->type()!=ScopedTypeVariant::Dummy)
{
- g_theCallContext.setClass(lcd);
+ yyextra->theCallContext.setScope(*lcd);
}
//isLocal=TRUE;
DBG_CTX((stderr,"is a local variable cd=%p!\n",cd));
@@ -660,17 +1329,18 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
if (cd && cd->isLinkable()) // is it a linkable class
{
- writeMultiLineCodeLink(ol,cd,clName);
- addToSearchIndex(className);
+ writeMultiLineCodeLink(yyscanner,ol,cd,clName);
+ addToSearchIndex(yyscanner,className);
if (md)
{
const Definition *d = md->getOuterScope()==Doxygen::globalScope ?
md->getBodyDef() : md->getOuterScope();
if (md->getGroupDef()) d = md->getGroupDef();
- if (d && d->isLinkable() && md->isLinkable() &&
- g_currentMemberDef && g_collectXRefs)
+ if (d && d->isLinkable() && md->isLinkable() &&
+ yyextra->currentMemberDef && yyextra->collectXRefs)
{
- addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md));
+ std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex);
+ addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md));
}
}
}
@@ -685,55 +1355,59 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
DBG_CTX((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,clName);
- addToSearchIndex(className);
- const Definition *d = md->getOuterScope()==Doxygen::globalScope ?
- md->getBodyDef() : md->getOuterScope();
- if (md->getGroupDef()) d = md->getGroupDef();
- if (d && d->isLinkable() && md->isLinkable() &&
- g_currentMemberDef && g_collectXRefs)
- {
- addDocCrossReference(g_currentMemberDef,md);
- }
- return;
- }
+ MemberDef *mmd = mcd->getMemberByName(locName);
+ if (mmd)
+ {
+ yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope())));
+ writeMultiLineCodeLink(yyscanner,ol,mmd,clName);
+ addToSearchIndex(yyscanner,className);
+ const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ?
+ mmd->getBodyDef() : mmd->getOuterScope();
+ if (mmd->getGroupDef()) d = mmd->getGroupDef();
+ if (d && d->isLinkable() && mmd->isLinkable() &&
+ yyextra->currentMemberDef && yyextra->collectXRefs)
+ {
+ std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex);
+ addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(mmd));
+ }
+ return;
+ }
}
else // check namespace as well
{
const NamespaceDef *mnd = getResolvedNamespace(scope);
if (mnd)
{
- MemberDef *md=mnd->getMemberByName(locName);
- if (md)
+ const MemberDef *mmd=mnd->getMemberByName(locName);
+ if (mmd)
{
- //printf("name=%s scope=%s\n",locName.data(),scope.data());
- g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
- writeMultiLineCodeLink(ol,md,clName);
- addToSearchIndex(className);
- const Definition *d = md->getOuterScope()==Doxygen::globalScope ?
- md->getBodyDef() : md->getOuterScope();
- if (md->getGroupDef()) d = md->getGroupDef();
- if (d && d->isLinkable() && md->isLinkable() &&
- g_currentMemberDef && g_collectXRefs)
- {
- addDocCrossReference(g_currentMemberDef,md);
- }
- return;
+ //printf("name=%s scope=%s\n",locName.data(),scope.data());
+ yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope())));
+ writeMultiLineCodeLink(yyscanner,ol,mmd,clName);
+ addToSearchIndex(yyscanner,className);
+ const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ?
+ mmd->getBodyDef() : mmd->getOuterScope();
+ if (mmd->getGroupDef()) d = mmd->getGroupDef();
+ if (d && d->isLinkable() && mmd->isLinkable() &&
+ yyextra->currentMemberDef && yyextra->collectXRefs)
+ {
+ std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex);
+ addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(mmd));
+ }
+ return;
}
}
}
}
-
+
// nothing found, just write out the word
- codifyLines(clName);
- addToSearchIndex(clName);
+ codifyLines(yyscanner,clName);
+ addToSearchIndex(yyscanner,clName);
}
}
+//-------------------------------------------------------------------------------
+
/*
As of June 1, this function seems to work
for file members, but scopes are not
@@ -741,11 +1415,12 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
so it doesn't work for classes yet.
*/
-static void generateFunctionLink(CodeOutputInterface &ol,char *funcName)
+static void generateFunctionLink(yyscan_t yyscanner,
+ CodeOutputInterface &ol,
+ const char *funcName)
{
- //CodeClassDef *ccd=0;
- ClassDef *ccd=0;
- QCString locScope=g_classScope.copy();
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ QCString locScope=yyextra->classScope;
QCString locFunc=removeRedundantWhiteSpace(funcName);
DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data()));
int i=locFunc.findRev("::");
@@ -755,916 +1430,215 @@ static void generateFunctionLink(CodeOutputInterface &ol,char *funcName)
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]))
+ if (!locScope.isEmpty())
{
- //printf("using classScope %s\n",g_classScope.data());
- if (ccd->baseClasses())
+ auto it = yyextra->codeClassMap.find(locScope.str());
+ if (it!=yyextra->codeClassMap.end())
{
- BaseClassListIterator bcli(*ccd->baseClasses());
- for ( ; bcli.current() ; ++bcli)
+ ScopedTypeVariant ccd = it->second;
+ //printf("using classScope %s\n",yyextra->classScope.data());
+ if (ccd.localDef() && !ccd.localDef()->baseClasses().empty())
{
- if (getLink(bcli.current()->classDef->name(),locFunc,ol,funcName))
- {
- return;
- }
+ for (const auto &bcName : ccd.localDef()->baseClasses())
+ {
+ if (getLink(yyscanner,bcName,locFunc,ol,funcName))
+ {
+ return;
+ }
+ }
}
}
}
- if (!getLink(locScope,locFunc,ol,funcName))
+ if (!getLink(yyscanner,locScope,locFunc,ol,funcName))
{
- generateClassOrGlobalLink(ol,funcName);
+ generateClassOrGlobalLink(yyscanner,ol,funcName);
}
return;
}
-static bool findMemberLink(CodeOutputInterface &ol,Definition *sym,const char *symName)
+//-------------------------------------------------------------------------------
+
+static bool findMemberLink(yyscan_t yyscanner,
+ CodeOutputInterface &ol,
+ Definition *sym,
+ const char *symName)
{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
//printf("sym %s outerScope=%s equal=%d\n",
// sym->name().data(),sym->getOuterScope()->name().data(),
- // sym->getOuterScope()==g_currentDefinition);
+ // sym->getOuterScope()==yyextra->currentDefinition);
if (sym->getOuterScope() &&
sym->getOuterScope()->definitionType()==Definition::TypeClass &&
- g_currentDefinition->definitionType()==Definition::TypeClass)
+ yyextra->currentDefinition->definitionType()==Definition::TypeClass)
{
- ClassDef *cd = dynamic_cast<ClassDef*>(sym->getOuterScope());
- ClassDef *thisCd = dynamic_cast<ClassDef *>(g_currentDefinition);
+ const ClassDef *cd = toClassDef(sym->getOuterScope());
+ const ClassDef *thisCd = toClassDef(yyextra->currentDefinition);
if (sym->definitionType()==Definition::TypeMember)
{
- if (g_currentMemberDef && g_collectXRefs)
+ if (yyextra->currentMemberDef && yyextra->collectXRefs)
{
- addDocCrossReference(g_currentMemberDef,dynamic_cast<MemberDef*>(sym));
+ std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex);
+ addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(toMemberDef(sym)));
}
}
DBG_CTX((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
+ // thisCd
if (cd==thisCd || (thisCd && thisCd->isBaseClass(cd,TRUE)))
{
- writeMultiLineCodeLink(ol,sym,symName);
+ writeMultiLineCodeLink(yyscanner,ol,sym,symName);
return TRUE;
}
}
return FALSE;
}
-static void findMemberLink(CodeOutputInterface &ol,char *symName)
+//-------------------------------------------------------------------------------
+
+static void findMemberLink(yyscan_t yyscanner,
+ CodeOutputInterface &ol,
+ const char *symName)
{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
//printf("Member reference: %s scope=%s member=%s\n",
// yytext,
- // g_currentDefinition?g_currentDefinition->name().data():"<none>",
- // g_currentMemberDef?g_currentMemberDef->name().data():"<none>"
+ // yyextra->currentDefinition?yyextra->currentDefinition->name().data():"<none>",
+ // yyextra->currentMemberDef?yyextra->currentMemberDef->name().data():"<none>"
// );
- if (g_currentDefinition)
+ if (yyextra->currentDefinition)
{
- DefinitionIntf *di = Doxygen::symbolMap->find(symName);
- if (di)
+ auto range = Doxygen::symbolMap.find(symName);
+ for (auto it = range.first; it!=range.second; ++it)
{
- 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;
- }
+ findMemberLink(yyscanner,ol,it->second,symName);
}
}
//printf("sym %s not found\n",&yytext[5]);
- codify(symName);
-}
-
-#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;
+ codify(yyscanner,symName);
}
-%}
-
-BB [ \t]+
-B [ \t]*
-NEWLINE \n
+//-------------------------------------------------------------------------------
-DIGIT [0-9]
-LETTER [A-Za-z\x80-\xFF]
-NONEMPTY [A-Za-z0-9_\x80-\xFF]
-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"|"with"|"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 stack
-
-%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
-
-%x DocBlock
-%%
-
-<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}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" {
- codify("self.");
- findMemberLink(*g_code,&yytext[5]);
- }
- "self."{IDENTIFIER}/"(" {
- codify("self.");
- findMemberLink(*g_code,&yytext[5]);
- }
- "self."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} {
- codify("self.");
- findMemberLink(*g_code,&yytext[5]);
- }
- "self."{IDENTIFIER} {
- codify("self.");
- findMemberLink(*g_code,&yytext[5]);
- }
- "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" {
- codify("cls.");
- findMemberLink(*g_code,&yytext[4]);
- }
- "cls."{IDENTIFIER}/"(" {
- codify("cls.");
- findMemberLink(*g_code,&yytext[4]);
- }
- "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} {
- codify("cls.");
- findMemberLink(*g_code,&yytext[4]);
- }
- "cls."{IDENTIFIER} {
- codify("cls.");
- findMemberLink(*g_code,&yytext[4]);
- }
-}
-
-<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 = createClassDef("<code>",1,1,g_curClassName,ClassDef::Class,0,0,FALSE);
- g_codeClassSDict.append(g_curClassName,classDefToAdd);
- char *s=g_curClassBases.first();
- while (s)
- {
- const ClassDef *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(const_cast<ClassDef*>(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);
- }
-
- "\n" {
- codifyLines(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} {
- if (g_currentMemberDef && g_currentMemberDef->isFunction())
- {
- g_currentMemberDef->incrementFlowKeyWordCount();
- }
- 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 necessary
- g_noSuiteFound = FALSE;
- }
-
- {FLOWKW} {
- if (g_currentMemberDef && g_currentMemberDef->isFunction())
- {
- g_currentMemberDef->incrementFlowKeyWordCount();
- }
- startFontClass("keywordflow");
- codifyLines(yytext);
- endFontClass();
-
- // No indentation necessary
- g_noSuiteFound = FALSE;
- }
- {IDENTIFIER} {
- codify(yytext);
- }
-
-
- {POUNDCOMMENT} {
- if (YY_START==SingleQuoteString ||
- YY_START==DoubleQuoteString ||
- YY_START==TripleString
- )
- {
- REJECT;
- }
- yy_push_state(YY_START);
- BEGIN(DocBlock);
- g_docBlock=yytext;
- }
-
- {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
- // indentation-tracking;
- // should be improved.
- // (translate tabs to space, etc)
- codifyLines(yytext);
- adjustScopesAndSuites((int)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);
- }
- \\. { // escaped char
- codify(yytext);
- }
- {STRINGPREFIX}?{TRIDOUBLEQUOTE} { // triple 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);
- }
- \\. { // escaped char
- codify(yytext);
- }
- {STRINGPREFIX}?{TRISINGLEQUOTE} { // triple single quotes
- codify(yytext);
- }
- "\"" { // end of the string
- codify(yytext);
- endFontClass();
- BEGIN(g_stringContext);
- }
- [^"'\n\\]+ { // normal chars
- codify(yytext);
- }
- . { // normal char
- codify(yytext);
- }
-}
+struct PythonCodeParser::Private
+{
+ yyscan_t yyscanner;
+ pycodeYY_state state;
+};
-<TripleString>{
- {TRIDOUBLEQUOTE} |
- {TRISINGLEQUOTE} {
- codify(yytext);
- if (g_doubleQuote==(yytext[0]=='"'))
- {
- endFontClass();
- BEGIN(g_stringContext);
- }
- }
- {LONGSTRINGBLOCK} {
- codifyLines(yytext);
- }
- \n {
- codifyLines(yytext);
- }
- . {
- codify(yytext);
- }
+PythonCodeParser::PythonCodeParser() : p(std::make_unique<Private>())
+{
+ pycodeYYlex_init_extra(&p->state,&p->yyscanner);
+#ifdef FLEX_DEBUG
+ pycodeYYset_debug(1,p->yyscanner);
+#endif
+ resetCodeParserState();
}
- /*
-<*>({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} {
- if (YY_START==SingleQuoteString) REJECT;
- startFontClass("stringliteral");
- g_stringContext=YY_START;
- g_doubleQuote=yytext[yyleng-1]=='"';
- codify(yytext);
- BEGIN(TripleString);
- }
-<*>{STRINGPREFIX}?{TRIDOUBLEQUOTE} {
- if (YY_START==DoubleQuoteString) REJECT;
- startFontClass("stringliteral");
- g_stringContext=YY_START;
- g_doubleQuote=yytext[yyleng-1]=='"';
- codify(yytext);
- BEGIN(TripleString);
- }
-<*>{STRINGPREFIX}?"'" { // single quoted string
- if (YY_START==SingleQuoteString ||
- YY_START==DoubleQuoteString ||
- YY_START==TripleString
- )
- {
- REJECT;
- }
- startFontClass("stringliteral");
- g_stringContext=YY_START;
- codify(yytext);
- BEGIN(SingleQuoteString);
- }
-<*>{STRINGPREFIX}?"\"" { // double quoted string
- if (YY_START==SingleQuoteString ||
- YY_START==DoubleQuoteString ||
- YY_START==TripleString
- )
- {
- REJECT;
- }
- startFontClass("stringliteral");
- g_stringContext=YY_START;
- codify(yytext);
- BEGIN(DoubleQuoteString);
- }
-<DocBlock>.* { // contents of current comment line
- g_docBlock+=yytext;
- }
-<DocBlock>"\n"{B}("#") { // comment block (next line is also comment line)
- g_docBlock+=yytext;
- }
-<DocBlock>{NEWLINE} { // comment block ends at the end of this line
- // remove special comment (default config)
- if (Config_getBool(STRIP_CODE_COMMENTS))
- {
- g_yyLineNr+=((QCString)g_docBlock).contains('\n');
- g_endComment=TRUE;
- }
- else // do not remove comment
- {
- startFontClass("comment");
- codifyLines(g_docBlock);
- endFontClass();
- }
- unput(*yytext);
- yy_pop_state();
- }
-<*>{POUNDCOMMENT}.* {
- if (YY_START==SingleQuoteString ||
- YY_START==DoubleQuoteString ||
- YY_START==TripleString
- )
- {
- REJECT;
- }
- yy_push_state(YY_START);
- BEGIN(DocBlock);
- g_docBlock=yytext;
- }
-<*>"#".* { // normal comment
- if (YY_START==SingleQuoteString ||
- YY_START==DoubleQuoteString ||
- YY_START==TripleString
- )
- {
- REJECT;
- }
- startFontClass("comment");
- codifyLines(yytext);
- endFontClass();
- }
-<*>{NEWLINE} {
- if (g_endComment)
- {
- g_endComment=FALSE;
- }
- else
- {
- 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);
- }
-
-<*><<EOF>> {
- if (YY_START == DocBlock) {
- if (!Config_getBool(STRIP_CODE_COMMENTS))
- {
- startFontClass("comment");
- codifyLines(g_docBlock);
- endFontClass();
- }
- }
- yyterminate();
- }
-%%
-
-/*@ ----------------------------------------------------------------------------
- */
-
-void resetPythonCodeParserState()
+PythonCodeParser::~PythonCodeParser()
{
- g_codeClassSDict.setAutoDelete(TRUE);
- g_codeClassSDict.clear();
- g_currentDefinition = 0;
- g_currentMemberDef = 0;
- g_doubleStringIsDoc = FALSE;
- g_paramParens = 0;
- g_indents.clear();
- BEGIN( Body );
+ pycodeYYlex_destroy(p->yyscanner);
}
-/*!
- Examines current stack of white-space indentations;
- re-syncs the parser with the correct scope.
-*/
-static void adjustScopesAndSuites(unsigned indentLength)
+void PythonCodeParser::resetCodeParserState()
{
- // 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 );
- }
+ struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
+ yyextra->codeClassMap.clear();
+ yyextra->currentDefinition = 0;
+ yyextra->currentMemberDef = 0;
+ yyextra->doubleStringIsDoc = FALSE;
+ yyextra->paramParens = 0;
+ while (!yyextra->indents.empty()) yyextra->indents.pop();
+ 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,
- const MemberDef *,bool,const Definition *searchCtx,bool collectXRefs)
+void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
+ const char *scopeName,
+ const QCString &input,
+ SrcLangExt /*lang*/,
+ bool isExampleBlock,
+ const char *exampleName,
+ FileDef *fileDef,
+ int startLine,
+ int endLine,
+ bool inlineFragment,
+ const MemberDef *memberDef,
+ bool showLineNumbers,
+ const Definition *searchCtx,
+ bool collectXRefs
+ )
{
+ yyscan_t yyscanner = p->yyscanner;
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
//printf("***parseCode()\n");
-
- //--------------------------------------
- if (s.isEmpty()) return;
- printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL);
- g_codeClassSDict.setAutoDelete(TRUE);
- g_code = &od;
- g_inputString = s;
- g_inputPosition = 0;
- g_currentFontClass = 0;
- g_needsTermination = FALSE;
- g_searchCtx=searchCtx;
- g_collectXRefs=collectXRefs;
+
+ if (input.isEmpty()) return;
+ printlex(yy_flex_debug, TRUE, __FILE__, fileDef ? fileDef->fileName().data(): NULL);
+ yyextra->code = &codeOutIntf;
+ yyextra->inputString = input;
+ yyextra->inputPosition = 0;
+ yyextra->currentFontClass = 0;
+ yyextra->needsTermination = FALSE;
+ yyextra->searchCtx=searchCtx;
+ yyextra->collectXRefs=collectXRefs;
if (startLine!=-1)
- g_yyLineNr = startLine;
+ yyextra->yyLineNr = startLine;
else
- g_yyLineNr = 1;
+ yyextra->yyLineNr = 1;
if (endLine!=-1)
- g_inputLines = endLine+1;
+ yyextra->inputLines = endLine+1;
else
- g_inputLines = g_yyLineNr + countLines() - 1;
-
-
- g_exampleBlock = exBlock;
- g_exampleName = exName;
- g_sourceFileDef = fd;
+ yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1;
+
+
+ yyextra->exampleBlock = isExampleBlock;
+ yyextra->exampleName = exampleName;
+ yyextra->sourceFileDef = fileDef;
+ yyextra->symbolResolver.setFileScope(fileDef);
bool cleanupSourceDef = FALSE;
- if (exBlock && fd==0)
+ if (yyextra->exampleBlock && fileDef==0)
{
// create a dummy filedef for the example
- g_sourceFileDef = createFileDef("",(exName?exName:"generated"));
+ yyextra->sourceFileDef = createFileDef("",(exampleName?exampleName:"generated"));
cleanupSourceDef = TRUE;
}
- if (g_sourceFileDef)
+ if (yyextra->sourceFileDef)
{
- setCurrentDoc("l00001");
+ setCurrentDoc(yyscanner,"l00001");
}
- g_includeCodeFragment = inlineFragment;
- // Starts line 1 on the output
- startCodeLine();
+ yyextra->includeCodeFragment = inlineFragment;
+ // Starts line 1 on the output
+ startCodeLine(yyscanner);
- pycodeYYrestart( pycodeYYin );
+ pycodeYYrestart(0,yyscanner);
- pycodeYYlex();
+ pycodeYYlex(yyscanner);
- if (!g_indents.isEmpty())
+ if (!yyextra->indents.empty())
{
// printf("Exited pysourceparser in inconsistent state!\n");
}
- if (g_needsTermination)
+ if (yyextra->needsTermination)
{
- endCodeLine();
+ endCodeLine(yyscanner);
}
if (cleanupSourceDef)
{
// delete the temporary file definition used for this example
- delete g_sourceFileDef;
- g_sourceFileDef=0;
+ delete yyextra->sourceFileDef;
+ yyextra->sourceFileDef=0;
}
- printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL);
- return;
+ // write the tooltips
+ TooltipManager::instance().writeTooltips(codeOutIntf);
+ printlex(yy_flex_debug, FALSE, __FILE__, fileDef ? fileDef->fileName().data(): NULL);
}
-//----------------------------------------------------------------------------
-
-void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
- const char *scopeName,
- const QCString &input,
- SrcLangExt /*lang*/,
- bool isExampleBlock,
- const char *exampleName,
- FileDef *fileDef,
- int startLine,
- int endLine,
- bool inlineFragment,
- const MemberDef *memberDef,
- bool showLineNumbers,
- const Definition *searchCtx,
- bool collectXRefs
- )
-{
- ::parsePythonCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName,
- fileDef,startLine,endLine,inlineFragment,memberDef,
- showLineNumbers,searchCtx,collectXRefs);
-}
-
-void PythonCodeParser::resetCodeParserState()
-{
- ::resetPythonCodeParserState();
-}
-
-
+#if USE_STATE2STRING
#include "pycode.l.h"
+#endif