Doxygen
Loading...
Searching...
No Matches
pyscanner.l
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2021 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15/* This code is based on the work done by the MoxyPyDoxy team
16 * (Linda Leong, Mike Rivera, Kim Truong, and Gabriel Estrada)
17 * in Spring 2005 as part of CS 179E: Compiler Design Project
18 * at the University of California, Riverside; the course was
19 * taught by Peter H. Froehlich <phf@acm.org>.
20 */
21
22%option never-interactive
23%option prefix="pyscannerYY"
24%option reentrant
25%option extra-type="struct pyscannerYY_state *"
26%top{
27#include <stdint.h>
28// forward declare yyscan_t to improve type safety
29#define YY_TYPEDEF_YY_SCANNER_T
30struct yyguts_t;
31typedef yyguts_t *yyscan_t;
yyguts_t * yyscan_t
Definition code.l:24
32}
33
34%{
35
36// own header
37#include "pyscanner.h"
38
39// standard includes
40#include <algorithm>
41#include <memory>
42#include <string>
43#include <vector>
44
45// other includes
46#include "arguments.h"
47#include "commentscan.h"
48#include "config.h"
49#include "debug.h"
50#include "defargs.h"
51#include "entry.h"
52#include "fileinfo.h"
53#include "markdown.h"
54#include "message.h"
55#include "stringutil.h"
56#include "util.h"
57
58// Toggle for some debugging info
59//#define DBG_CTX(x) fprintf x
60#define DBG_CTX(x) do { } while(0)
61
62#define YY_NO_INPUT 1
63#define YY_NO_UNISTD_H 1
64
65#define unput_string(yytext,yyleng) do { for (int i=(int)yyleng-1;i>=0;i--) unput(yytext[i]); } while(0)
66
67/* ----------------------------------------------------------------- */
68
70{
73 const char * inputString = nullptr;
75 Protection protection = Protection::Public;
76 std::shared_ptr<Entry> current_root;
77 std::shared_ptr<Entry> current;
78 std::shared_ptr<Entry> previous;
79 std::shared_ptr<Entry> bodyEntry;
80 int yyLineNr = 1 ;
82 MethodTypes mtype = MethodTypes::Method;
83 bool isStatic = false;
84 Specifier virt = Specifier::Normal;
87 bool docBlockInBody = false;
88 bool docBlockJavaStyle = false;
89 bool docBrief = false;
90 bool docBlockSpecial = false;
91 bool doubleQuote = false;
92 bool specialBlock = false;
95 int indent = 0;
96 int curIndent = 0;
98 bool importTuple = false;
100 char atomStart = 0;
101 char atomEnd = 0;
102 int atomCount = 0;
103 int atomContext = 0;
107 int braceCount = 0;
108 bool lexInit = false;
110 bool startInit = false;
111 int searchCount = 0;
113 bool funcParamsEnd = false;
114 std::vector<DString> decorators;
118 bool checkDupEntry = false;
119 bool firstPass = true;
123};
124
125//-----------------------------------------------------------------------------
126[[maybe_unused]] static const char *stateToString(int state);
127
128static inline int computeIndent(const char *s);
129
130static void initParser(yyscan_t yyscanner);
131static void initEntry(yyscan_t yyscanner);
132static void newEntry(yyscan_t yyscanner);
133static void addEntry(yyscan_t yyscanner);
134static void docVariable(yyscan_t yyscanner,const char *s);
135static void newVariable(yyscan_t yyscanner);
136static void newTypeAlias(yyscan_t yyscanner);
137static void addVariable(yyscan_t yyscanner);
138static void newFunction(yyscan_t yyscanner);
139static DString findPackageScopeFromPath(yyscan_t yyscanner,const DString &path);
140static void addFrom(yyscan_t yyscanner,bool all);
141static void lineCount(yyscan_t yyscanner);
142static void incLineNr(yyscan_t yyscanner);
143static void startCommentBlock(yyscan_t yyscanner,bool brief);
144static void handleCommentBlock(yyscan_t yyscanner,const DString &doc,bool brief);
145static void endOfDef(yyscan_t yyscanner,int correction=0);
146static inline void addToString(yyscan_t yyscanner,const char *s);
147static void initTriDoubleQuoteBlock(yyscan_t yyscanner);
148static void initTriSingleQuoteBlock(yyscan_t yyscanner);
149static void initSpecialBlock(yyscan_t yyscanner);
150static void searchFoundDef(yyscan_t yyscanner);
151static void searchFoundClass(yyscan_t yyscanner);
152static void searchFoundTypeAlias(yyscan_t yyscanner);
153static DString findPackageScope(yyscan_t yyscanner,const DString &fileName);
154static void setProtection(yyscan_t yyscanner);
155static void handleParamComment(yyscan_t yyscanner,const DString &doc);
156
157static int yyread(yyscan_t yyscanner,char *buf,int max_size);
158
159//-----------------------------------------------------------------------------
160/* ----------------------------------------------------------------- */
161#undef YY_INPUT
162#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
163
164// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
165static inline const char *getLexerFILE() {return __FILE__;}
166#include "doxygen_lex.h"
167
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:84
Abstract interface for outline parsers.
Definition parserintf.h:41
Text streaming class that buffers data.
Definition textstream.h:36
Interface for the comment block scanner.
std::unordered_map< std::string, std::string > StringUnorderedMap
Definition containers.h:28
#define lineCount(s, len)
static void newEntry(yyscan_t yyscanner)
Definition pyscanner.l:1881
static void incLineNr(yyscan_t yyscanner)
Definition pyscanner.l:2095
static void docVariable(yyscan_t yyscanner, const char *s)
Definition pyscanner.l:1966
static void initSpecialBlock(yyscan_t yyscanner)
Definition pyscanner.l:2218
static void handleParamComment(yyscan_t yyscanner, const DString &doc)
Definition pyscanner.l:2275
static void initTriSingleQuoteBlock(yyscan_t yyscanner)
Definition pyscanner.l:2205
static int computeIndent(const char *s)
Definition pyscanner.l:2023
static void searchFoundTypeAlias(yyscan_t yyscanner)
Definition pyscanner.l:2262
static void addFrom(yyscan_t yyscanner, bool all)
Definition pyscanner.l:2072
static void setProtection(yyscan_t yyscanner)
Definition pyscanner.l:1950
static void initParser(yyscan_t yyscanner)
Definition pyscanner.l:1854
static void endOfDef(yyscan_t yyscanner, int correction=0)
Definition pyscanner.l:2173
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
Definition pyscanner.l:1844
static void searchFoundClass(yyscan_t yyscanner)
Definition pyscanner.l:2250
static const char * stateToString(int state)
static DString findPackageScope(yyscan_t yyscanner, const DString &fileName)
Definition pyscanner.l:2065
static void newVariable(yyscan_t yyscanner)
Definition pyscanner.l:1979
static void newTypeAlias(yyscan_t yyscanner)
Definition pyscanner.l:1990
static void initTriDoubleQuoteBlock(yyscan_t yyscanner)
Definition pyscanner.l:2192
static void searchFoundDef(yyscan_t yyscanner)
Definition pyscanner.l:2230
static void addEntry(yyscan_t yyscanner)
Definition pyscanner.l:1927
static const char * getLexerFILE()
Definition pyscanner.l:165
static void startCommentBlock(yyscan_t yyscanner, bool brief)
Definition pyscanner.l:2103
static void newFunction(yyscan_t yyscanner)
Definition pyscanner.l:2008
static DString findPackageScopeFromPath(yyscan_t yyscanner, const DString &path)
Definition pyscanner.l:2038
static void addVariable(yyscan_t yyscanner)
Definition pyscanner.l:1997
static void handleCommentBlock(yyscan_t yyscanner, const DString &doc, bool brief)
Definition pyscanner.l:2118
static void addToString(yyscan_t yyscanner, const char *s)
Definition pyscanner.l:2186
static void initEntry(yyscan_t yyscanner)
Definition pyscanner.l:1865
Some helper functions for std::string.
std::vector< DString > decorators
Definition pyscanner.l:114
std::shared_ptr< Entry > previous
Definition pyscanner.l:78
Specifier virt
Definition pyscanner.l:84
std::shared_ptr< Entry > current
Definition pyscanner.l:77
DString moduleScope
Definition pyscanner.l:104
StringUnorderedMap packageNameCache
Definition pyscanner.l:99
const char * inputString
Definition pyscanner.l:73
std::shared_ptr< Entry > bodyEntry
Definition pyscanner.l:79
TextStream * copyString
Definition pyscanner.l:94
TextStream defVal
Definition pyscanner.l:106
DString genericsValue
Definition pyscanner.l:122
TextStream decoratorCommentStr
Definition pyscanner.l:116
Protection protection
Definition pyscanner.l:75
std::shared_ptr< Entry > current_root
Definition pyscanner.l:76
DString packageName
Definition pyscanner.l:105
MethodTypes mtype
Definition pyscanner.l:82
bool packageCommentAllowed
Definition pyscanner.l:109
OutlineParserInterface * thisParser
Definition pyscanner.l:72
CommentScanner commentScanner
Definition pyscanner.l:71
MethodTypes
Definition types.h:119
Protection
Definition types.h:32
Specifier
Definition types.h:80
A bunch of utility functions.
168%}
169
170 /* start command character */
171
172CMD ("\\"|"@")
173BB [ \t]+
174B [ \t]*
175NEWLINE \n
176
177DIGIT [0-9]
178
179HEXNUMBER "0"[xX][0-9a-fA-F]+[lL]?
180OCTNUMBER "0"[0-7]+[lL]?
181NUMBER {DIGIT}+[lLjJ]?
182INTNUMBER {HEXNUMBER}|{OCTNUMBER}|{NUMBER}
183FLOATNUMBER {DIGIT}+"."{DIGIT}+([eE][+\-]?{DIGIT}+)?[jJ]?
184BOOL ("True"|"False")
185LETTER [A-Za-z\x80-\xFF]
186NONEMPTY [A-Za-z0-9_\x80-\xFF]
187EXPCHAR [#(){}\‍[\‍],:.%/\\=`*~|&<>!;+-]
188PARAMNONEMPTY [^ \t\n():]
189IDENTIFIER ({LETTER}|"_")({LETTER}|{DIGIT}|"_")*
190SCOPE {IDENTIFIER}("."{IDENTIFIER})*
191
192TRISINGLEQUOTE {STRINGPREFIX}?"'''"(!)?
193TRIDOUBLEQUOTE {STRINGPREFIX}?"\"\"\""(!)?
194ENDTRISINGLEQUOTE "'''"
195ENDTRIDOUBLEQUOTE "\"\"\""
196LONGSTRINGCHAR [^\\"']
197ESCAPESEQ ("\\")(.)
198LONGSTRINGITEM ({LONGSTRINGCHAR}|{ESCAPESEQ})
199SMALLQUOTE ("\"\""|"\""|"'"|"''")
200LONGSTRINGBLOCK ({LONGSTRINGITEM}|{SMALLQUOTE})
201
202STRINGPREFIX ("r"|"u"|"ur"|"R"|"U"|"UR"|"Ur"|"uR")
203POUNDCOMMENT "#"[^#\n][^\n]*
204SCRIPTCOMMENT "#!".*
205
206STARTDOCSYMS "##"
207
208LINENR {B}*[1-9][0-9]*
209FILEICHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+=&#@~]
210FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+=&#@~]
211FILECHARS {FILEICHAR}*{FILEECHAR}+
212HFILEMASK {FILEICHAR}*("."{FILEICHAR}+)+{FILECHARS}*
213VFILEMASK {FILECHARS}("."{FILECHARS})*
214FILEMASK {VFILEMASK}|{HFILEMASK}
215
216IDSYM [a-z_A-Z0-9]
217ID [a-z_A-Z%]+{IDSYM}*
218
219%option noyywrap
220
221 /* Main start state */
222
223%x Search
224%x SearchMemVars
225%x SearchSkipValue
226
227 /* Mid-comment states */
228
229 /* %x FuncDoubleComment */
230 /* %x ClassDoubleComment */
231%x TripleComment
232%x SpecialComment
233
234 /* Function states */
235
236%x FunctionDec
237%x FunctionParams
238%x FunctionBody
239%x FunctionAnnotation
240%x FunctionTypeAnnotation
241%x FunctionParamDefVal
242
243 /* Class states */
244
245%x ClassDec
246%x ClassInheritance
247%x ClassCaptureIndent
248%x ClassBody
249
250 /* Variable states */
251%x VariableDec
252%x VariableEnd
253%x VariableAtom
254
255 /* String states */
256
257%x SingleQuoteString
258%x DoubleQuoteString
259%x TripleString
260%x SingleQuoteStringIgnore
261%x DoubleQuoteStringIgnore
262
263 /* import */
264%x FromMod
265%x FromModItem
266%x Import
267
268 /* TypeHints */
269%x TypeHint
270
271 /* Decorator */
272%x Decorator
273
274 /* Generics */
275%x Generics
276%x TypeAlias
277%x TypeValue
278
280
281 /* ------------ Function recognition rules -------------- */
282
283<Search>{
284
285 ^{B}"def"{BB} { // start of a function/method definition with indent
286 DBG_CTX((stderr,"Found def at %d\n",yyextra->yyLineNr));
287 yyextra->indent=computeIndent(yytext);
288 searchFoundDef(yyscanner);
289 BEGIN( FunctionDec );
290 }
#define DBG_CTX(x)
Definition code.l:70
static int computeIndent(const char *s)
291 ^{B}"async"{BB}"def"{BB} { // start of an async function/method definition with indent
292 DBG_CTX((stderr,"Found async def at %d\n",yyextra->yyLineNr));
293 yyextra->indent=computeIndent(yytext);
294 searchFoundDef(yyscanner);
295 BEGIN( FunctionDec );
296 }
297 "def"{BB} { // start of a function/method definition
298 searchFoundDef(yyscanner);
299 BEGIN( FunctionDec );
300 }
301 "async"{BB}"def"{BB} { // start of a function/method definition
302 searchFoundDef(yyscanner);
303 BEGIN( FunctionDec );
304 }
305
306 ^{B}"class"{BB} { // start of a class definition with indent
307 DBG_CTX((stderr,"Found class at %d\n",yyextra->yyLineNr));
308 yyextra->indent=computeIndent(yytext);
309 searchFoundClass(yyscanner);
310 BEGIN( ClassDec ) ;
311 }
312 "class"{BB} { // start of a class definition
313 searchFoundClass(yyscanner);
314 BEGIN( ClassDec ) ;
315 }
316 ^{B}"type"{BB} {
317 yyextra->indent=computeIndent(yytext);
318 searchFoundTypeAlias(yyscanner);
319 BEGIN( TypeAlias );
320 }
321 "type"{BB} {
322 searchFoundTypeAlias(yyscanner);
323 BEGIN( TypeAlias );
324 }
325 ^{B}"from"{BB} |
326 "from"{BB} { // start of an from import
327 yyextra->packageCommentAllowed = false;
328 BEGIN( FromMod );
329 }
330
331 ^{B}"import"{BB} |
332 "import"{BB} { // start of an import statement
333 yyextra->packageCommentAllowed = false;
334 BEGIN( Import );
335 }
336 ^{B}{IDENTIFIER}/{B}"="{B}"property" { // property
337 yyextra->current->section = EntryType::makeVariable();
338 yyextra->current->mtype = MethodTypes::Property;
339 yyextra->current->name = DString(yytext).stripWhiteSpace();
340 yyextra->current->fileName = yyextra->fileName;
341 yyextra->current->startLine = yyextra->yyLineNr;
342 yyextra->current->bodyLine = yyextra->yyLineNr;
343 yyextra->packageCommentAllowed = false;
344 BEGIN(VariableDec);
345 }
DString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition dstring.h:337
346 ^{B}{IDENTIFIER}/{B}"="[^=] { // variable
347 if (yyextra->searchCount>0) REJECT;
348 yyextra->indent=computeIndent(yytext);
349 yyextra->current->section = EntryType::makeVariable();
350 yyextra->current->name = DString(yytext).stripWhiteSpace();
351 yyextra->current->fileName = yyextra->fileName;
352 yyextra->current->startLine = yyextra->yyLineNr;
353 yyextra->current->bodyLine = yyextra->yyLineNr;
354 yyextra->packageCommentAllowed = false;
355 BEGIN(VariableDec);
356 }
357 ^{B}{IDENTIFIER}/{B}":" { // variable
358 if (yyextra->searchCount>0) REJECT;
359 DString id = DString(yytext).stripWhiteSpace();
360 if (id =="try" || id == "else" || id == "except" || id == "finally") REJECT;
361 yyextra->indent=computeIndent(yytext);
362 yyextra->current->section = EntryType::makeVariable();
363 yyextra->current->name = id;
364 yyextra->current->fileName = yyextra->fileName;
365 yyextra->current->startLine = yyextra->yyLineNr;
366 yyextra->current->bodyLine = yyextra->yyLineNr;
367 yyextra->packageCommentAllowed = false;
368 BEGIN(VariableDec);
369 }
370 {B}{IDENTIFIER}/({B},{B}{IDENTIFIER})*{B}")"*{B}"="[^=] { // list of variables, we cannot place the default value
371 // so we will skip it later on in a general rule
372 // Also note ")" this is to catch also (a,b). the "("
373 // is caught in the rule: [(], the ")" will be handled in [)]
374 if (yyextra->searchCount>1) REJECT;
375 yyextra->indent=computeIndent(yytext);
376 yyextra->current->section = EntryType::makeVariable();
377 yyextra->current->name = DString(yytext).stripWhiteSpace();
378 yyextra->current->fileName = yyextra->fileName;
379 yyextra->current->startLine = yyextra->yyLineNr;
380 yyextra->current->bodyLine = yyextra->yyLineNr;
381 yyextra->packageCommentAllowed = false;
382 addVariable(yyscanner);
383 }
384 "'" { // start of a single quoted string
385 yyextra->stringContext=YY_START;
386 yyextra->copyString=nullptr;
387 yyextra->packageCommentAllowed = false;
388 BEGIN( SingleQuoteString );
389 }
390 "\"" { // start of a double quoted string
391 yyextra->stringContext=YY_START;
392 yyextra->copyString=nullptr;
393 yyextra->packageCommentAllowed = false;
394 BEGIN( DoubleQuoteString );
395 }
396 "@staticmethod" {
397 yyextra->isStatic=true;
398 }
399 "@"{SCOPE}"(" { // decorator
400 lineCount(yyscanner);
401 yyextra->decoratorRound = 1;
402 yyextra->copyString=nullptr;
403 BEGIN( Decorator );
404 }
405 "@"{SCOPE} { // decorator
406 lineCount(yyscanner);
407 }
408 {SCRIPTCOMMENT} { // Unix type script comment
409 if (yyextra->yyLineNr != 1) REJECT;
410 }
411 {POUNDCOMMENT} { // normal comment
412 // issue 9672
413 //yyextra->packageCommentAllowed = false;
414 }
415 {IDENTIFIER} { // some other identifier
416 yyextra->packageCommentAllowed = false;
417 }
418 ^{BB} {
419 yyextra->curIndent=computeIndent(yytext);
420 }
421
422 {NEWLINE}+ { // new line
423 lineCount(yyscanner);
424 }
425
426 {TRIDOUBLEQUOTE} { // start of a comment block
427 initTriDoubleQuoteBlock(yyscanner);
428 BEGIN(TripleComment);
429 }
430
431 {TRISINGLEQUOTE} { // start of a comment block
432 initTriSingleQuoteBlock(yyscanner);
433 BEGIN(TripleComment);
434 }
435
436 {B}{STARTDOCSYMS}/[^#] { // start of a special comment
437 yyextra->curIndent=computeIndent(yytext);
438 yyextra->packageCommentAllowed = false;
439 initSpecialBlock(yyscanner);
440 BEGIN(SpecialComment);
441 }
442 [(] { // we have to do something with (
443 yyextra->searchCount++;
444 }
445 [)] { // we have to do something with )
446 if (yyextra->searchCount>0)
447 {
448 yyextra->searchCount--;
449 }
450 }
451 "=" {
452 yyextra->current->doc.clear();
453 yyextra->current->brief.clear();
454 }
455 {IDENTIFIER} {
456 }
457 [^\n] { // any other character...
458 // This is the major default
459 // that should catch everything
460 // else in Body.
461 }
462}
463
464<FromMod>{
465 "." { // python3 style imports
466 }
467 {IDENTIFIER}({B}"."{B}{IDENTIFIER})* { // from package import
468 yyextra->packageName=yytext;
469 }
470 "import"{B} {
471 BEGIN(FromModItem);
472 }
473 \n {
474 incLineNr(yyscanner);
475 BEGIN(Search);
476 }
477 {B} {
478 }
479 . {
480 unput(*yytext);
481 BEGIN(Search);
482 }
483}
484
485<FromModItem>{
486 "*" { // import all
487 addFrom(yyscanner,true);
488 BEGIN(Search);
489 }
490 {IDENTIFIER}/{B}","{B} {
491 addFrom(yyscanner,false);
492 }
493 {IDENTIFIER}/{B}")" {
494 addFrom(yyscanner,false);
495 }
496 {IDENTIFIER} {
497 addFrom(yyscanner,false);
498 if (!yyextra->importTuple)
499 {
500 BEGIN(Search);
501 }
502 }
503 \n {
504 incLineNr(yyscanner);
505 if (!yyextra->importTuple)
506 {
507 BEGIN(Search);
508 }
509 }
510 {B} {
511 }
512 "(" {
513 yyextra->importTuple=true;
514 }
515 ")" {
516 yyextra->importTuple=false;
517 BEGIN(Search);
518 }
519 "," {
520 }
521 "\\"{B}\n { // line continuation
522 incLineNr(yyscanner);
523 }
524 . {
525 unput(*yytext);
526 BEGIN(Search);
527 }
528}
529
530<Import>{
531 {IDENTIFIER}({B}"."{B}{IDENTIFIER})* {
532 yyextra->current->name=removeRedundantWhiteSpace(substitute(yytext,".","::"));
533 yyextra->current->fileName = yyextra->fileName;
534 //printf("Adding using declaration: found:%s:%d name=%s\n",qPrint(yyextra->fileName),yyextra->yyLineNr,qPrint(yyextra->current->name));
535 yyextra->current->section=EntryType::makeUsingDecl();
536 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
537 initEntry(yyscanner);
538 BEGIN(Search);
539 }
DString substitute(const DString &s, const DString &src, const DString &dst)
substitute all occurrences of src in s by dst
Definition dstring.cpp:485
static void initEntry(yyscan_t yyscanner)
DString removeRedundantWhiteSpace(const DString &s)
Definition util.cpp:426
540 \n {
541 incLineNr(yyscanner);
542 BEGIN(Search);
543 }
544 {B} {
545 }
546 . {
547 unput(*yytext);
548 BEGIN(Search);
549 }
550}
551
552<SearchMemVars>{
553 ("cls"|"self")"."{IDENTIFIER}/{B}[,)] {
554 const char *s = strchr(yytext,'.'); s++;
555 DBG_CTX((stderr,"Found instance method variable %s in %s at %d\n",s,qPrint(yyextra->current_root->name.data(),yyextra->yyLineNr)));
556 docVariable(yyscanner,s);
557 addEntry(yyscanner);
558 }
const char * qPrint(const char *s)
Definition dstring.h:783
559 ("cls"|"self")"."{IDENTIFIER}/{B}"=" {
560 const char *s = strchr(yytext,'.'); s++;
561 DBG_CTX((stderr,"Found instance method variable %s in %s at %d\n",s,qPrint(yyextra->current_root->name.data(),yyextra->yyLineNr)));
562 docVariable(yyscanner,s);
563 BEGIN( SearchSkipValue );
564 }
565 ("cls"|"self")"."{IDENTIFIER}/{B}":" { // type hint
566 const char *s = strchr(yytext,'.'); s++;
567 DBG_CTX((stderr,"Found instance method variable %s in %s at %d\n",s,qPrint(yyextra->current_root->name.data(),yyextra->yyLineNr)));
568 docVariable(yyscanner,s);
569 BEGIN(TypeHint);
570 }
571 {TRIDOUBLEQUOTE} { // start of a comment block
572 initTriDoubleQuoteBlock(yyscanner);
573 BEGIN(TripleComment);
574 }
575
576 {TRISINGLEQUOTE} { // start of a comment block
577 initTriSingleQuoteBlock(yyscanner);
578 BEGIN(TripleComment);
579 }
580
581 {STARTDOCSYMS}/[^#] { // start of a special comment
582 initSpecialBlock(yyscanner);
583 BEGIN(SpecialComment);
584 }
585 {POUNDCOMMENT} { // #
586 }
587 "'" { // start of a single quoted string
588 yyextra->stringContext=YY_START;
589 yyextra->copyString=nullptr;
590 BEGIN( SingleQuoteString );
591 }
592 "\"" { // start of a double quoted string
593 yyextra->stringContext=YY_START;
594 yyextra->copyString=nullptr;
595 BEGIN( DoubleQuoteString );
596 }
597 \n { incLineNr(yyscanner); }
598 "=" {
599 yyextra->current->doc.clear();
600 yyextra->current->brief.clear();
601 unput(*yytext);
602 BEGIN( SearchSkipValue );
603 }
604 {IDENTIFIER} // identifiers
605 [^'"\.#a-z_A-Z=\n]+ // other uninteresting stuff
606 . // anything else
607}
608
609<TypeHint>{
610 ":" { // skip over start of type hint
611 yyextra->braceCount=0;
612 }
613 "("|"["|"{" {
614 yyextra->current->type+=*yytext;
615 yyextra->braceCount++;
616 }
617 ")"|"]"|"}" {
618 yyextra->current->type+=*yytext;
619 yyextra->braceCount--;
620 }
621 "'" { // start of a single quoted string
622 yyextra->stringContext=YY_START;
623 yyextra->copyString=nullptr;
624 BEGIN( SingleQuoteString );
625 }
626 "\"" { // start of a double quoted string
627 yyextra->stringContext=YY_START;
628 yyextra->copyString=nullptr;
629 BEGIN( DoubleQuoteString );
630 }
631 "=" {
632 if (yyextra->braceCount==0)
633 { // end of the type hint
634 yyextra->current->type = yyextra->current->type.stripWhiteSpace();
635 unput(*yytext);
636 BEGIN(SearchSkipValue);
637 }
638 else
639 {
640 yyextra->current->type+=*yytext;
641 }
642 }
643 \n { // end of the type hint
644 yyextra->current->type = yyextra->current->type.stripWhiteSpace();
645 incLineNr(yyscanner);
646 newEntry(yyscanner);
647 BEGIN(SearchMemVars);
648 }
649 "\\\n" {
650 yyextra->current->type+=' ';
651 incLineNr(yyscanner);
652 }
653 . {
654 yyextra->current->type+=*yytext;
655 }
656}
657
658<SearchSkipValue,VariableDec,TypeValue>{
659 "=" { // the assignment operator
660 //printf("====== VariableDec at line %d\n",yyextra->yyLineNr);
661 yyextra->startInit = true;
662 if (YY_START!=TypeValue)
663 {
664 yyextra->current->initializer.str(yytext);
665 yyextra->current->initializer << " ";
666 }
667 }
668 {B} { // spaces
669 yyextra->current->initializer << yytext;
670 }
671
672 {INTNUMBER} { // integer value
673 if (yyextra->current->type.empty()) yyextra->current->type = "int";
674 yyextra->current->initializer << yytext;
675 }
676 {FLOATNUMBER} { // floating point value
677 if (yyextra->current->type.empty()) yyextra->current->type = "float";
678 yyextra->current->initializer << yytext;
679 }
680 {BOOL} { // boolean value
681 if (yyextra->current->type.empty()) yyextra->current->type = "bool";
682 yyextra->current->initializer << yytext;
683 }
684 {STRINGPREFIX}?"'" { // string
685 if (yyextra->current->type.empty()) yyextra->current->type = "str";
686 yyextra->current->initializer << yytext;
687 yyextra->copyString=&yyextra->current->initializer;
688 yyextra->stringContext=YY_START;
689 BEGIN( SingleQuoteString );
690 }
691 {STRINGPREFIX}?"\"" { // string
692 if (yyextra->current->type.empty()) yyextra->current->type = "str";
693 yyextra->current->initializer << yytext;
694 yyextra->copyString=&yyextra->current->initializer;
695 yyextra->stringContext=YY_START;
696 BEGIN( DoubleQuoteString );
697 }
698 {TRIDOUBLEQUOTE} { // start of a comment block
699 if (yyextra->current->type.empty()) yyextra->current->type = "str";
700 yyextra->current->initializer << yytext;
701 yyextra->doubleQuote=true;
702 yyextra->copyString=&yyextra->current->initializer;
703 yyextra->stringContext=YY_START;
704 BEGIN(TripleString);
705 }
706
707 {TRISINGLEQUOTE} { // start of a comment block
708 if (yyextra->current->type.empty()) yyextra->current->type = "str";
709 yyextra->current->initializer << yytext;
710 yyextra->doubleQuote=false;
711 yyextra->copyString=&yyextra->current->initializer;
712 yyextra->stringContext=YY_START;
713 BEGIN(TripleString);
714 }
715 "(" { // tuple, only when direct after =
716 if (yyextra->current->mtype!=MethodTypes::Property && yyextra->startInit)
717 {
718 yyextra->current->type = "tuple";
719 }
720 yyextra->current->initializer << *yytext;
721 yyextra->atomStart='(';
722 yyextra->atomEnd=')';
723 yyextra->atomCount=1;
724 yyextra->atomContext=YY_START;
725 BEGIN( VariableAtom );
726 }
727 "[" { // list
728 if (yyextra->startInit) yyextra->current->type = "list";
729 yyextra->current->initializer << *yytext;
730 yyextra->atomStart='[';
731 yyextra->atomEnd=']';
732 yyextra->atomCount=1;
733 yyextra->atomContext=YY_START;
734 BEGIN( VariableAtom );
735 }
736 "{" { // dictionary
737 if (yyextra->startInit) yyextra->current->type = "dict";
738 yyextra->current->initializer << *yytext;
739 yyextra->atomStart='{';
740 yyextra->atomEnd='}';
741 yyextra->atomCount=1;
742 yyextra->atomContext=YY_START;
743 BEGIN( VariableAtom );
744 }
745 "\\\n" {
746 yyextra->current->initializer << yytext;
747 incLineNr(yyscanner);
748 }
749 {IDENTIFIER} {
750 // do something based on the type of the IDENTIFIER
751 if (yyextra->current->type.empty())
752 {
753 for (const auto &child : yyextra->current_root->children())
754 {
755 if (child->name == yytext)
756 {
757 yyextra->current->type = child->type;
758 break;
759 }
760 }
761 }
762 yyextra->startInit = false;
763 yyextra->current->initializer << yytext;
764 }
765 . {
766 yyextra->startInit = false;
767 yyextra->current->initializer << *yytext;
768 }
769}
770<SearchSkipValue>{
771 {STARTDOCSYMS}/[^#] { // start of a special comment
772 initSpecialBlock(yyscanner);
773 BEGIN(SpecialComment);
774 }
775 {POUNDCOMMENT} { // #
776 }
777 \n { incLineNr(yyscanner);
778 newEntry(yyscanner);
779 BEGIN(SearchMemVars);
780 }
781 <<EOF>> { incLineNr(yyscanner);
782 newEntry(yyscanner);
783 BEGIN(SearchMemVars);
784 }
785}
786
787<FunctionBody>{
788 \n{B}/{IDENTIFIER}[^{LETTER}{DIGIT}_] {
789 DBG_CTX((stderr,"indent %d<=%d\n",computeIndent(&yytext[1]),yyextra->indent));
790 if (computeIndent(&yytext[1])<=yyextra->indent)
791 {
792 unput_string(yytext,yyleng);
793 endOfDef(yyscanner);
794 //YY_CURRENT_BUFFER->yy_at_bol=true;
795 BEGIN(Search);
796 }
797 else
798 {
799 incLineNr(yyscanner);
800 yyextra->current->program << yytext;
801 }
802 }
#define unput_string(yytext, yyleng)
803 \n{B}/"##" {
804 if (computeIndent(&yytext[1])<=yyextra->indent)
805 {
806 unput_string(yytext,yyleng);
807 endOfDef(yyscanner);
808 //YY_CURRENT_BUFFER->yy_at_bol=true;
809 BEGIN(Search);
810 }
811 else
812 {
813 incLineNr(yyscanner);
814 yyextra->current->program << yytext;
815 }
816 }
817 <<EOF>> {
818 endOfDef(yyscanner);
819 yyterminate();
820 }
#define yyterminate()
821 ^{BB}/\n { // skip empty line
822 yyextra->current->program << yytext;
823 }
824 ^{BB} { // something at indent >0
825 yyextra->curIndent = computeIndent(yytext);
826 if (yyextra->curIndent<=yyextra->indent)
827 // jumped out of the function
828 {
829 endOfDef(yyscanner,1);
830 BEGIN(Search);
831 }
832 else
833 {
834 yyextra->current->program << yytext;
835 }
836 }
837 "'" { // start of a single quoted string
838 yyextra->current->program << yytext;
839 yyextra->stringContext=YY_START;
840 yyextra->specialBlock = false;
841 yyextra->copyString=&yyextra->current->program;
842 BEGIN( SingleQuoteString );
843 }
844 "\"" { // start of a double quoted string
845 yyextra->current->program << yytext;
846 yyextra->stringContext=YY_START;
847 yyextra->specialBlock = false;
848 yyextra->copyString=&yyextra->current->program;
849 BEGIN( DoubleQuoteString );
850 }
851 [^ \t\n#'".]+ { // non-special stuff
852 yyextra->current->program << yytext;
853 yyextra->specialBlock = false;
854 }
855 ^{POUNDCOMMENT} { // normal comment
856 yyextra->current->program << yytext;
857 }
858 "#".* { // comment half way
859 yyextra->current->program << yytext;
860 }
861 {NEWLINE} {
862 incLineNr(yyscanner);
863 yyextra->current->program << yytext;
864 }
865 . { // any character
866 yyextra->current->program << *yytext;
867 yyextra->specialBlock = false;
868 }
869
870 {TRIDOUBLEQUOTE} { // start of a comment block
871 yyextra->current->program << yytext;
872 initTriDoubleQuoteBlock(yyscanner);
873 BEGIN(TripleComment);
874 }
875
876 {TRISINGLEQUOTE} { // start of a comment block
877 yyextra->current->program << yytext;
878 initTriSingleQuoteBlock(yyscanner);
879 BEGIN(TripleComment);
880 }
881
882}
883
884<FunctionDec>{
885 {IDENTIFIER} {
886 //found function name
887 yyextra->current->name = yytext;
888 yyextra->current->name = yyextra->current->name.stripWhiteSpace();
889 newFunction(yyscanner);
890 }
891 {B}":"{B} { // function without arguments
892 yyextra->specialBlock = true; // expecting a docstring
893 yyextra->bodyEntry = yyextra->current;
894 yyextra->current->bodyLine = yyextra->yyLineNr;
895 BEGIN(FunctionBody);
896 }
897 "[" { // python 3.12+ style generics
898 yyextra->genericsContext = YY_START;
899 yyextra->bracketDepth = 1;
900 yyextra->genericsValue = "[";
901 BEGIN(Generics);
902 }
903 "->" {
904 yyextra->defVal.str(std::string());
905 yyextra->braceCount = 0;
906 BEGIN(FunctionTypeAnnotation);
907 }
908 {B}"(" {
909 yyextra->funcParamsEnd = false;
910 yyextra->current->bodyLine = yyextra->yyLineNr;
911 BEGIN(FunctionParams);
912 }
913 ")" { // end of parameter list
914 if (yyextra->current->argList.empty())
915 {
916 yyextra->current->argList.setNoParameters(true);
917 }
918 yyextra->current->args = argListToString(yyextra->current->argList);
919 yyextra->funcParamsEnd = true;
920 }
DString argListToString(const ArgumentList &al, bool useCanonicalType, bool showDefVals)
Definition util.cpp:859
921}
922
923<Generics>{
924 {IDENTIFIER} {
925 yyextra->genericsValue+=yytext;
926 }
927 "[" {
928 yyextra->genericsValue+=yytext;
929 yyextra->bracketDepth++;
930 }
931 "]" {
932 yyextra->genericsValue+=yytext;
933 yyextra->bracketDepth--;
934 if (yyextra->bracketDepth==0)
935 {
936 BEGIN(yyextra->genericsContext);
937 }
938 }
939 . {
940 yyextra->genericsValue+=yytext;
941 }
942}
943
944<FunctionParams>{
945 {BB} {
946 }
947
948 "," {
949 if (!yyextra->argType.empty())
950 {
951 Argument a;
952 a.name = "";
953 a.type = yyextra->argType;
954 yyextra->current->argList.push_back(a);
955 yyextra->argType = "";
956 }
957 }
This class contains the information about the argument of a function or template.
Definition arguments.h:27
DString name
Definition arguments.h:45
DString type
Definition arguments.h:43
void push_back(char c)
Definition dstring.h:202
958
959 [\*]+ {
960 yyextra->argType = yytext;
961 }
962 {IDENTIFIER} { // Name of parameter
963 lineCount(yyscanner);
964 Argument a;
965 a.name = DString(yytext).stripWhiteSpace();
966 a.type = yyextra->argType;
967 yyextra->current->argList.push_back(a);
968 yyextra->argType = "";
969 }
970 "=" { // default value
971 // TODO: this rule is too simple, need to be able to
972 // match things like =")" as well!
973 yyextra->defVal.str(std::string());
974 yyextra->braceCount = 0;
975 BEGIN(FunctionParamDefVal);
976 }
977 ")" {
978 if (!yyextra->argType.empty())
979 {
980 Argument a;
981 a.name = "";
982 a.type = yyextra->argType;
983 yyextra->current->argList.push_back(a);
984 yyextra->argType = "";
985 }
986 unput(*yytext);
987 BEGIN(FunctionDec);
988 }
989 ":"{B} {
990 yyextra->defVal.str(std::string());
991 yyextra->braceCount = 0;
992 BEGIN(FunctionAnnotation);
993 }
994 {STARTDOCSYMS}"<"/.* { // start of a special comment
995 handleParamComment(yyscanner,yytext);
996 BEGIN(SpecialComment);
997 }
998 {POUNDCOMMENT} { // a comment
999 }
1000 {PARAMNONEMPTY} { // Default rule inside arguments.
1001 }
1002
1003}
1004
1005<FunctionTypeAnnotation>{
1006 "{" |
1007 "[" |
1008 "(" {
1009 ++yyextra->braceCount;
1010 yyextra->defVal << *yytext;
1011 }
1012 "}" |
1013 "]" |
1014 ")" {
1015 --yyextra->braceCount;
1016 yyextra->defVal << *yytext;
1017 }
1018 ":" {
1019 if (yyextra->braceCount == 0)
1020 {
1021 yyextra->current->type = yyextra->defVal.str();
1022 unput(*yytext);
1023 BEGIN(FunctionDec);
1024 }
1025 else
1026 yyextra->defVal << *yytext;
1027 }
1028 "'" {
1029 yyextra->defVal << *yytext;
1030 yyextra->copyString=&yyextra->defVal;
1031 yyextra->stringContext=FunctionTypeAnnotation;
1032 BEGIN(SingleQuoteString);
1033 }
1034 "\"" {
1035 yyextra->defVal << *yytext;
1036 yyextra->copyString=&yyextra->defVal;
1037 yyextra->stringContext=FunctionTypeAnnotation;
1038 BEGIN(DoubleQuoteString);
1039 }
1040 \n {
1041 yyextra->defVal << *yytext;
1042 incLineNr(yyscanner);
1043 }
1044 . {
1045 yyextra->defVal << *yytext;
1046 }
1047}
1048
1049<FunctionAnnotation>{
1050 "{" |
1051 "[" |
1052 "(" {
1053 ++yyextra->braceCount;
1054 yyextra->defVal << *yytext;
1055 }
1056 "}" |
1057 "]" {
1058 --yyextra->braceCount;
1059 yyextra->defVal << *yytext;
1060 }
1061 ")" |
1062 "=" |
1063 "," {
1064 if (yyextra->braceCount == 0)
1065 {
1066 if (!yyextra->current->argList.empty())
1067 yyextra->current->argList.back().type += yyextra->defVal.str();
1068 if (*yytext != ',')
1069 unput(*yytext);
1070 BEGIN(FunctionParams);
1071 }
1072 else
1073 {
1074 if (*yytext == ')')
1075 --yyextra->braceCount;
1076 yyextra->defVal << *yytext;
1077 }
1078 }
1079 "'" {
1080 yyextra->defVal << *yytext;
1081 yyextra->copyString=&yyextra->defVal;
1082 yyextra->stringContext=FunctionAnnotation;
1083 BEGIN(SingleQuoteString);
1084 }
1085 "\"" {
1086 yyextra->defVal << *yytext;
1087 yyextra->copyString=&yyextra->defVal;
1088 yyextra->stringContext=FunctionAnnotation;
1089 BEGIN(DoubleQuoteString);
1090 }
1091 \n {
1092 yyextra->defVal << *yytext;
1093 incLineNr(yyscanner);
1094 }
1095 {STARTDOCSYMS}"<"/.* { // start of a special comment
1096 handleParamComment(yyscanner,yytext);
1097 BEGIN(SpecialComment);
1098 }
1099 {POUNDCOMMENT} { // a comment
1100 }
1101 . {
1102 yyextra->defVal << *yytext;
1103 }
1104}
1105
1106<FunctionParamDefVal>{
1107 "{" |
1108 "[" |
1109 "(" { // internal opening brace, assumption is that we have correct code so braces do match
1110 ++yyextra->braceCount;
1111 yyextra->defVal << *yytext;
1112 }
1113 "}" |
1114 "]" {
1115 --yyextra->braceCount;
1116 yyextra->defVal << *yytext;
1117 }
1118 ")" |
1119 "," {
1120 if (yyextra->braceCount == 0)
1121 {
1122 if (!yyextra->current->argList.empty())
1123 yyextra->current->argList.back().defval=DString(yyextra->defVal.str()).stripWhiteSpace();
1124 if (*yytext == ')')
1125 unput(*yytext);
1126 BEGIN(FunctionParams);
1127 }
1128 else
1129 {
1130 if (*yytext == ')')
1131 --yyextra->braceCount;
1132 yyextra->defVal << *yytext;
1133 }
1134 }
1135
1136 "'" {
1137 yyextra->defVal << *yytext;
1138 yyextra->copyString=&yyextra->defVal;
1139 yyextra->stringContext=FunctionParamDefVal;
1140 BEGIN( SingleQuoteString );
1141 }
1142 "\"" {
1143 yyextra->defVal << *yytext;
1144 yyextra->copyString=&yyextra->defVal;
1145 yyextra->stringContext=FunctionParamDefVal;
1146 BEGIN( DoubleQuoteString );
1147 }
1148 {STARTDOCSYMS}"<"/.* { // start of a special comment
1149 handleParamComment(yyscanner,yytext);
1150 BEGIN(SpecialComment);
1151 }
1152 {POUNDCOMMENT} { // a comment
1153 }
1154 \n {
1155 yyextra->defVal << *yytext;
1156 incLineNr(yyscanner);
1157 }
1158 . {
1159 yyextra->defVal << *yytext;
1160 }
1161}
1162
1163
1164<ClassBody>{
1165 \n/{IDENTIFIER}{BB} { // new def at indent 0
1166 if (computeIndent(&yytext[1])<=yyextra->indent)
1167 {
1168 int i;
1169 for (i=(int)yyleng-1;i>=0;i--)
1170 {
1171 unput(yytext[i]);
1172 }
1173 endOfDef(yyscanner);
1174 //YY_CURRENT_BUFFER->yy_at_bol=true;
1175 BEGIN(Search);
1176 }
1177 else
1178 {
1179 incLineNr(yyscanner);
1180 yyextra->current->program << yytext;
1181 }
1182 }
1183 \n/"##"[^#] { // start of a special comment at indent 0
1184 if (computeIndent(&yytext[1])<=yyextra->indent)
1185 {
1186 int i;
1187 for (i=(int)yyleng-1;i>=0;i--)
1188 {
1189 unput(yytext[i]);
1190 }
1191 endOfDef(yyscanner);
1192 //YY_CURRENT_BUFFER->yy_at_bol=true;
1193 BEGIN(Search);
1194 }
1195 else
1196 {
1197 incLineNr(yyscanner);
1198 yyextra->current->program << yytext;
1199 }
1200 }
1201 ^{BB}/\n { // skip empty line
1202 yyextra->current->program << yytext;
1203 }
1204 <<EOF>> {
1205 endOfDef(yyscanner);
1206 yyterminate();
1207 }
1208 ^{BB} { // something at indent >0
1209 yyextra->curIndent=computeIndent(yytext);
1210 DBG_CTX((stderr,"yyextra->curIndent=%d yyextra->indent=%d\n",yyextra->curIndent,yyextra->indent));
1211 if (yyextra->curIndent<=yyextra->indent)
1212 // jumped out of the class/method
1213 {
1214 endOfDef(yyscanner,1);
1215 yyextra->indent=yyextra->curIndent;
1216 // make sure the next rule matches ^...
1217 //YY_CURRENT_BUFFER->yy_at_bol=true;
1218 //yyextra->hideClassDocs = false;
1219 BEGIN(Search);
1220 }
1221 else
1222 {
1223 yyextra->current->program << yytext;
1224 }
1225 }
1226 "'" { // start of a single quoted string
1227 yyextra->current->program << *yytext;
1228 yyextra->stringContext=YY_START;
1229 yyextra->specialBlock = false;
1230 yyextra->copyString=&yyextra->current->program;
1231 BEGIN( SingleQuoteString );
1232 }
1233 "\"" { // start of a double quoted string
1234 yyextra->current->program << *yytext;
1235 yyextra->stringContext=YY_START;
1236 yyextra->specialBlock = false;
1237 yyextra->copyString=&yyextra->current->program;
1238 BEGIN( DoubleQuoteString );
1239 }
1240 [^ \t\n#'"]+ { // non-special stuff
1241 yyextra->current->program << yytext;
1242 yyextra->specialBlock = false;
1243 //yyextra->hideClassDocs = false;
1244 }
1245 {NEWLINE} {
1246 yyextra->current->program << *yytext;
1247 incLineNr(yyscanner);
1248 }
1249 {POUNDCOMMENT} { // normal comment
1250 yyextra->current->program << yytext;
1251 }
1252 . { // any character
1253 yyextra->specialBlock = false;
1254 yyextra->current->program << *yytext;
1255 }
1256 {TRIDOUBLEQUOTE} { // start of a comment block
1257 //if (!yyextra->hideClassDocs)
1258 yyextra->current->program << yytext;
1259 initTriDoubleQuoteBlock(yyscanner);
1260 BEGIN(TripleComment);
1261 }
1262
1263 {TRISINGLEQUOTE} { // start of a comment block
1264 //if (!yyextra->hideClassDocs)
1265 yyextra->current->program << yytext;
1266 initTriSingleQuoteBlock(yyscanner);
1267 BEGIN(TripleComment);
1268 }
1269}
1270
1271<TypeAlias>{
1272 {IDENTIFIER} {
1273 yyextra->current->name = yytext;
1274 }
1275 "[" {
1276 yyextra->bracketDepth=1;
1277 yyextra->genericsContext = YY_START;
1278 yyextra->genericsValue = "[";
1279 BEGIN(Generics);
1280 }
1281 "=" {
1282 yyextra->current->args = yyextra->genericsValue;
1283 BEGIN(TypeValue);
1284 }
1285}
1286<TypeValue>{
1287 \n {
1288 incLineNr(yyscanner);
1289 if (!stripWhiteSpace(yyextra->current->initializer.str()).empty())
1290 {
1291 newTypeAlias(yyscanner);
1292 }
1293 BEGIN(Search);
1294 }
std::string_view stripWhiteSpace(std::string_view s)
Given a string view s, returns a new, narrower view on that string, skipping over any leading or trai...
Definition stringutil.h:75
1295 . {
1296 unput(*yytext);
1297 newTypeAlias(yyscanner);
1298 BEGIN(Search);
1299 }
1300 <<EOF>> { yyterminate();
1301 }
1302}
1303
1304<ClassDec>{IDENTIFIER} {
1305 if (yyextra->current->type.empty())
1306 {
1307 yyextra->current->type = "class";
1308 }
1309
1310 yyextra->current->section = EntryType::makeClass();
1311 yyextra->current->name = yytext;
1312 // we need to set the protectiion based on the "local" class name
1313 setProtection(yyscanner);
1314
1315 // prepend scope in case of nested classes
1316 if (yyextra->current_root->section.isScope())
1317 {
1318 //printf("*** Prepending scope %s to class %s\n",qPrint(yyextra->current_root->name),qPrint(yyextra->current->name));
1319 yyextra->current->name.prepend(yyextra->current_root->name+"::");
1320 }
1321
1322 yyextra->current->name = yyextra->current->name.stripWhiteSpace();
1323 yyextra->current->fileName = yyextra->fileName;
1324 yyextra->docBlockContext = YY_START;
1325 yyextra->docBlockInBody = false;
1326 yyextra->docBlockJavaStyle = false;
1327 yyextra->docBlock.clear();
1328 yyextra->bracketDepth = 0;
1329
1330 BEGIN(ClassInheritance);
1331 }
1332
1333<ClassInheritance>{
1334 ({BB}|[\‍(,\‍)]) { // syntactic sugar for the list
1335 }
1336 "[" {
1337 yyextra->bracketDepth=1;
1338 yyextra->genericsContext = YY_START;
1339 yyextra->genericsValue = "[";
1340 BEGIN(Generics);
1341 }
1342 ":" { // begin of the class definition
1343 yyextra->specialBlock = true; // expecting a docstring
1344 yyextra->current->bodyLine = yyextra->yyLineNr;
1345 yyextra->current->program.str(std::string());
1346 BEGIN(ClassCaptureIndent);
1347 }
1348
1349 {SCOPE} {
1350 yyextra->current->extends.emplace_back(
1351 substitute(yytext,".","::"),Protection::Public,Specifier::Normal
1352 );
1353 }
1354 "'" { // start of a single quoted string
1355 yyextra->stringContext=YY_START;
1356 BEGIN( SingleQuoteStringIgnore );
1357 }
1358 "\"" { // start of a double quoted string
1359 yyextra->stringContext=YY_START;
1360 BEGIN( DoubleQuoteStringIgnore );
1361 }
1362}
1363
1364<SingleQuoteStringIgnore>{
1365 "'" { // end of a single quoted string
1366 BEGIN(yyextra->stringContext);
1367 }
1368 . { }
1369}
1370<DoubleQuoteStringIgnore>{
1371 "\"" { // end of a double quoted string
1372 BEGIN(yyextra->stringContext);
1373 }
1374 . { }
1375}
1376
1377<ClassCaptureIndent>{
1378 "\n"|({BB}"\n") {
1379 // Blankline - ignore, keep looking for indentation.
1380 lineCount(yyscanner);
1381 yyextra->current->program << yytext;
1382 }
1383
1384 {TRIDOUBLEQUOTE} { // start of a comment block
1385 initTriDoubleQuoteBlock(yyscanner);
1386 yyextra->current->program << yytext;
1387 BEGIN(TripleComment);
1388 }
1389 {TRISINGLEQUOTE} { // start of a comment block
1390 initTriSingleQuoteBlock(yyscanner);
1391 yyextra->current->program << yytext;
1392 BEGIN(TripleComment);
1393 }
1394 {STARTDOCSYMS}[#]* { // start of a special comment
1395 initSpecialBlock(yyscanner);
1396 BEGIN(SpecialComment);
1397 }
1398 {POUNDCOMMENT} { // ignore comment with just one #
1399 }
1400 ^{BB} {
1401 yyextra->current->program << yytext;
1402 //yyextra->current->startLine = yyextra->yyLineNr;
1403 yyextra->curIndent=computeIndent(yytext);
1404 yyextra->bodyEntry = yyextra->current;
1405 DBG_CTX((stderr,"setting indent %d\n",yyextra->curIndent));
1406 //printf("yyextra->current->program=[%s]\n",qPrint(yyextra->current->program));
1407 //yyextra->hideClassDocs = true;
1408 BEGIN(ClassBody);
1409 }
1410
1411 ""/({NONEMPTY}|{EXPCHAR}) {
1412 // Just pushback an empty class, and
1413 // resume parsing the body.
1414 newEntry(yyscanner);
1415 yyextra->current->program << yytext;
1416
1417 // printf("Failed to find indent - skipping!");
1418 BEGIN( Search );
1419 }
1420}
1421
1422
1423<VariableDec>{
1424 ":"{B}{IDENTIFIER} { //typing
1425 yyextra->startInit = false;
1426 yyextra->current->type = substitute(yytext,":","");
1427 }
1428 {STARTDOCSYMS}"<"/.* { // start of a special comment
1429 yyextra->curIndent=computeIndent(yytext);
1430 yyextra->packageCommentAllowed = false;
1431 initSpecialBlock(yyscanner);
1432 yyextra->docBlockContext = VariableEnd;
1433 BEGIN(SpecialComment);
1434 }
1435 "#".* { // comment
1436 BEGIN( VariableEnd );
1437 }
1438 \n {
1439 unput('\n');
1440 BEGIN( VariableEnd );
1441 }
1442}
1443
1444<VariableAtom>{
1445 [\‍(\‍[\{] {
1446 yyextra->current->initializer << *yytext;
1447 if (yyextra->atomStart==*yytext)
1448 {
1449 yyextra->atomCount++;
1450 }
1451 }
1452 [\‍)\‍]\}] {
1453 yyextra->current->initializer << *yytext;
1454 if (yyextra->atomEnd==*yytext)
1455 {
1456 yyextra->atomCount--;
1457 }
1458 if (yyextra->atomCount==0)
1459 {
1460 yyextra->startInit = false;
1461 BEGIN(yyextra->atomContext);
1462 }
1463 }
1464 {TRIDOUBLEQUOTE} { // start of a comment block
1465 yyextra->specialBlock = false;
1466 yyextra->current->program << yytext;
1467 initTriDoubleQuoteBlock(yyscanner);
1468 BEGIN(TripleComment);
1469 }
1470
1471 {TRISINGLEQUOTE} { // start of a comment block
1472 yyextra->specialBlock = false;
1473 yyextra->current->program << yytext;
1474 initTriSingleQuoteBlock(yyscanner);
1475 BEGIN(TripleComment);
1476 }
1477 "'" {
1478 yyextra->stringContext=YY_START;
1479 yyextra->current->initializer << "'";
1480 yyextra->copyString=&yyextra->current->initializer;
1481 BEGIN( SingleQuoteString );
1482 }
1483 "\"" {
1484 yyextra->stringContext=YY_START;
1485 yyextra->current->initializer << "\"";
1486 yyextra->copyString=&yyextra->current->initializer;
1487 BEGIN( DoubleQuoteString );
1488 }
1489 {IDENTIFIER} {
1490 yyextra->current->initializer << yytext;
1491 }
1492 {POUNDCOMMENT} { // normal comment
1493 yyextra->current->initializer << yytext;
1494 }
1495 . {
1496 yyextra->current->initializer << *yytext;
1497 }
1498 \n {
1499 yyextra->current->initializer << *yytext;
1500 incLineNr(yyscanner);
1501 }
1502
1503}
1504
1505<VariableEnd>{
1506 \n {
1507 incLineNr(yyscanner);
1508 if (!stripWhiteSpace(yyextra->current->initializer.str()).empty())
1509 {
1510 newVariable(yyscanner);
1511 }
1512 BEGIN(Search);
1513 }
1514 . {
1515 unput(*yytext);
1516 newVariable(yyscanner);
1517 BEGIN(Search);
1518 }
1519 <<EOF>> { yyterminate();
1520 }
1521}
1522
1523<TripleComment>{
1524 {ENDTRIDOUBLEQUOTE} |
1525 {ENDTRISINGLEQUOTE} {
1526 // printf("Expected module block %d special=%d\n",yyextra->expectModuleDocs,yyextra->specialBlock);
1527 if (yyextra->doubleQuote==(yytext[0]=='"'))
1528 {
1529 if (yyextra->specialBlock) // expecting a docstring
1530 {
1531 DString actualDoc=yyextra->docBlock;
1532 if (!yyextra->docBlockSpecial) // legacy unformatted docstring
1533 {
1534 if (!actualDoc.empty())
1535 {
1536 stripIndentationVerbatim(actualDoc,yyextra->commentIndent);
1537 actualDoc.prepend("@iverbatim\n");
1538 actualDoc.append("@endiverbatim ");
1539 }
1540 }
1541 //printf("-------> yyextra->current=%p yyextra->bodyEntry=%p\n",yyextra->current,yyextra->bodyEntry);
1542 handleCommentBlock(yyscanner, actualDoc, false);
1543 }
1544 else if (yyextra->packageCommentAllowed) // expecting module docs
1545 {
1546 DString actualDoc=yyextra->docBlock;
1547 if (!yyextra->docBlockSpecial) // legacy unformatted docstring
1548 {
1549 if (!actualDoc.empty())
1550 {
1551 stripIndentationVerbatim(actualDoc,yyextra->commentIndent);
1552 actualDoc.prepend("@iverbatim\n");
1553 actualDoc.append("@endiverbatim ");
1554 }
1555 }
1556 if (yyextra->moduleScope.startsWith("__") && yyextra->moduleScope.endsWith("__"))
1557 {
1558 actualDoc.prepend("\\namespace \\"+yyextra->moduleScope+" ");
1559 }
1560 else
1561 {
1562 actualDoc.prepend("\\namespace "+yyextra->moduleScope+" ");
1563 }
1564 handleCommentBlock(yyscanner, actualDoc, false);
1565 }
1566 if ((yyextra->docBlockContext==ClassBody /*&& !yyextra->hideClassDocs*/) ||
1567 yyextra->docBlockContext==FunctionBody)
1568 {
1569 yyextra->current->program << yyextra->docBlock;
1570 yyextra->current->program << yytext;
1571 }
1572 //if (yyextra->hideClassDocs)
1573 //{
1574 // yyextra->current->startLine = yyextra->yyLineNr;
1575 //}
1576 //yyextra->hideClassDocs=false;
1577 BEGIN(yyextra->docBlockContext);
1578 }
1579 else
1580 {
1581 yyextra->docBlock += yytext;
1582 }
1583 yyextra->packageCommentAllowed = false;
1584 }
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
DString & append(char c)
Definition dstring.h:489
DString & prepend(const char *s)
Definition dstring.h:515
static void handleCommentBlock(yyscan_t yyscanner, const DString &doc, bool brief)
void stripIndentationVerbatim(DString &doc, size_t indentationLevel, bool skipFirstLine)
Definition util.cpp:4772
1585
1586
1587 ^{BB} { // leading whitespace, compensate for """! / '''!
1588 if (yyextra->firstPass && yyextra->docBlockSpecial && yyleng >= yyextra->curIndent)
1589 yyextra->docBlock += yytext + yyextra->curIndent;
1590 else
1591 yyextra->docBlock += yytext;
1592 }
1593 [^"'\n \t\\@]+ {
1594 yyextra->docBlock += yytext;
1595 }
1596 \n {
1597 incLineNr(yyscanner);
1598 yyextra->docBlock += yytext;
1599 }
1600 {CMD}"ifile"{B}+"\""[^\n\"]+"\"" {
1601 yyextra->fileName = &yytext[6];
1602 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1603 yyextra->fileName = yyextra->fileName.mid(1,yyextra->fileName.length()-2);
1604 yyextra->docBlock+=yytext;
1605 }
1606 {CMD}"ifile"{B}+{FILEMASK} {
1607 yyextra->fileName = &yytext[6];
1608 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1609 yyextra->docBlock+=yytext;
1610 }
1611 {CMD}"iline"{LINENR}/[\n\.] |
1612 {CMD}"iline"{LINENR}{B} {
1613 bool ok = false;
1614 int nr = DString(&yytext[6]).toInt(&ok);
1615 if (!ok)
1616 {
1617 warn(yyextra->fileName,yyextra->yyLineNr,"Invalid line number '{}' for iline command",yytext);
1618 }
1619 else
1620 {
1621 yyextra->yyLineNr = nr;
1622 }
1623 yyextra->docBlock+=yytext;
1624 }
int toInt(bool *ok=nullptr, int base=10) const
Definition dstring.cpp:191
#define warn(file, line, fmt,...)
Definition message.h:97
1625 ({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command
1626 yyextra->docBlock+=yytext;
1627 }
1628 \\. { // escaped char TO be extended
1629 yyextra->docBlock += yytext;
1630 }
1631 . {
1632 yyextra->docBlock += yytext;
1633 }
1634}
1635
1636<SpecialComment>{
1637 ^{B}"#"("#")* { // skip leading hashes
1638 }
1639 \n/{B}"#" { // continuation of the comment on the next line
1640 yyextra->docBlock+='\n';
1641 yyextra->docBrief = false;
1642 incLineNr(yyscanner);
1643 }
1644 {CMD}"ifile"{B}+"\""[^\n\"]+"\"" {
1645 yyextra->fileName = &yytext[6];
1646 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1647 yyextra->fileName = yyextra->fileName.mid(1,yyextra->fileName.length()-2);
1648 yyextra->docBlock+=yytext;
1649 }
1650 {CMD}"ifile"{B}+{FILEMASK} {
1651 yyextra->fileName = &yytext[6];
1652 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1653 yyextra->docBlock+=yytext;
1654 }
1655 {CMD}"iline"{LINENR}/[\n\.] |
1656 {CMD}"iline"{LINENR}{B} {
1657 bool ok = false;
1658 int nr = DString(&yytext[6]).toInt(&ok);
1659 if (!ok)
1660 {
1661 warn(yyextra->fileName,yyextra->yyLineNr,"Invalid line number '{}' for iline command",yytext);
1662 }
1663 else
1664 {
1665 yyextra->yyLineNr = nr;
1666 }
1667 yyextra->docBlock+=yytext;
1668 }
1669 ({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command
1670 yyextra->docBlock+=yytext;
1671 }
1672 "\\ilinebr "{B}* {
1673 DString indent;
1674 int extraSpaces = std::max(0,static_cast<int>(yyleng-9-yyextra->curIndent-2));
1675 indent.fill(' ',extraSpaces);
1676 //printf("extraSpaces=%d\n",extraSpaces);
1677 yyextra->docBlock += "\\ilinebr ";
1678 yyextra->docBlock += indent;
1679 }
DString fill(char c, size_t len)
Fills a string with a predefined character.
Definition dstring.h:278
1680 [^#\\@\n]+ { // any other stuff
1681 yyextra->docBlock+=yytext;
1682 }
1683 \n { // new line that ends the comment
1684 handleCommentBlock(yyscanner, yyextra->docBlock, yyextra->docBrief);
1685 if (yyextra->docBlockContext == VariableEnd)
1686 {
1687 unput(*yytext);
1688 }
1689 else
1690 {
1691 incLineNr(yyscanner);
1692 }
1693 BEGIN(yyextra->docBlockContext);
1694 }
1695 . { // anything we missed
1696 yyextra->docBlock+=*yytext;
1697 }
1698}
1699
1700<SingleQuoteString>{
1701 \\{B}\n { // line continuation
1702 addToString(yyscanner,yytext);
1703 incLineNr(yyscanner);
1704 }
1705 \\. { // escaped char
1706 addToString(yyscanner,yytext);
1707 }
1708 "\"\"\"" { // triple double quotes
1709 addToString(yyscanner,yytext);
1710 }
1711 "'" { // end of the string
1712 addToString(yyscanner,yytext);
1713 BEGIN(yyextra->stringContext);
1714 }
1715 [^"'\n\\‍]+ { // normal chars
1716 addToString(yyscanner,yytext);
1717 }
1718 . { // normal char
1719 addToString(yyscanner,yytext);
1720 }
1721}
1722
1723<DoubleQuoteString>{
1724 \\{B}\n { // line continuation
1725 addToString(yyscanner,yytext);
1726 incLineNr(yyscanner);
1727 }
1728 \\. { // escaped char
1729 addToString(yyscanner,yytext);
1730 }
1731 "'''" { // triple single quotes
1732 addToString(yyscanner,yytext);
1733 }
1734 "\"" { // end of the string
1735 addToString(yyscanner,yytext);
1736 BEGIN(yyextra->stringContext);
1737 }
1738 [^"'\n\\‍]+ { // normal chars
1739 addToString(yyscanner,yytext);
1740 }
1741 . { // normal char
1742 addToString(yyscanner,yytext);
1743 }
1744}
1745
1746<TripleString>{
1747 {ENDTRIDOUBLEQUOTE} |
1748 {ENDTRISINGLEQUOTE} {
1749 *yyextra->copyString << yytext;
1750 if (yyextra->doubleQuote==(yytext[0]=='"'))
1751 {
1752 BEGIN(yyextra->stringContext);
1753 }
1754 }
1755
1756
1757 ({LONGSTRINGBLOCK}) {
1758 lineCount(yyscanner);
1759 *yyextra->copyString << yytext;
1760 }
1761 \n {
1762 incLineNr(yyscanner);
1763 *yyextra->copyString << yytext;
1764 }
1765 . {
1766 *yyextra->copyString << *yytext;
1767 }
1768}
1769
1770<Decorator>{
1771 {TRIDOUBLEQUOTE} { // start of a comment block
1772 yyextra->doubleQuote=true;
1773 yyextra->decoratorCommentStr.str(std::string());
1774 yyextra->copyString=&yyextra->decoratorCommentStr;
1775 yyextra->stringContext=YY_START;
1776 BEGIN(TripleString);
1777 }
1778
1779 {TRISINGLEQUOTE} { // start of a comment block
1780 yyextra->doubleQuote=false;
1781 yyextra->decoratorCommentStr.str(std::string());
1782 yyextra->copyString=&yyextra->decoratorCommentStr;
1783 yyextra->stringContext=YY_START;
1784 BEGIN(TripleString);
1785 }
1786 "'" {
1787 yyextra->stringContext=YY_START;
1788 yyextra->decoratorCommentStr.str(std::string());
1789 yyextra->copyString=&yyextra->decoratorCommentStr;
1790 BEGIN( SingleQuoteString );
1791 }
1792 "\"" {
1793 yyextra->stringContext=YY_START;
1794 yyextra->decoratorCommentStr.str(std::string());
1795 yyextra->copyString=&yyextra->decoratorCommentStr;
1796 BEGIN( DoubleQuoteString );
1797 }
1798 "(" {
1799 yyextra->decoratorRound++;
1800 }
1801 ")" {
1802 yyextra->decoratorRound--;
1803 if (!yyextra->decoratorRound) BEGIN( Search );
1804 }
1805 \n {
1806 incLineNr(yyscanner);
1807 }
1808 . { }
1809}
1810
1811 /* ------------ End rules -------------- */
1812
1813 /*
1814<*>({NONEMPTY}|{EXPCHAR}|{BB}) { // This should go one character at a time.
1815 // printf("[pyscanner] '%s' [ state %d ] [line %d] no match\n",
1816 // yytext, YY_START, yyextra->yyLineNr);
1817
1818 }
1819 */
1820
1821<*>{NEWLINE} {
1822 //printf("[pyscanner] %d NEWLINE [line %d] no match\n",
1823 // YY_START, yyextra->yyLineNr);
1824
1825 lineCount(yyscanner);
1826 }
1827
1828<*>"'" {
1829 //fprintf(stderr,"Quote: %d\n",YY_START);
1830 }
1831
1832<*>. {
1833 //printf("[pyscanner] '%s' [ state %d ] [line %d] no match\n",
1834 // yytext, YY_START, yyextra->yyLineNr);
1835
1836 }
1837
1838
1839%%
1840
1841//----------------------------------------------------------------------------
1842
1843
1844static int yyread(yyscan_t yyscanner,char *buf,int max_size)
1845{
1846 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1847 int c=0;
1848 const char *p = yyextra->inputString + yyextra->inputPosition;
1849 while ( c < max_size && *p ) { *buf++ = *p++; c++; }
1850 yyextra->inputPosition+=c;
1851 return c;
1852}
1853
1854static void initParser(yyscan_t yyscanner)
1855{
1856 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1857 yyextra->protection = Protection::Public;
1858 yyextra->mtype = MethodTypes::Method;
1859 yyextra->isStatic = false;
1860 yyextra->virt = Specifier::Normal;
1861 yyextra->previous = 0;
1862 yyextra->packageCommentAllowed = true;
1863}
1864
1865static void initEntry(yyscan_t yyscanner)
1866{
1867 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1868 //yyextra->current->python = true;
1869 yyextra->current->protection = yyextra->protection ;
1870 yyextra->current->mtype = yyextra->mtype;
1871 yyextra->current->virt = yyextra->virt;
1872 yyextra->current->isStatic = yyextra->isStatic;
1873 yyextra->current->lang = SrcLangExt::Python;
1874 yyextra->current->type.clear();
1875 yyextra->current->name.clear();
1876 yyextra->current->initializer.clear();
1877 yyextra->commentScanner.initGroupInfo(yyextra->current.get());
1878 yyextra->isStatic = false;
1879}
1880
1881static void newEntry(yyscan_t yyscanner)
1882{
1883 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1884 if (yyextra->current->name.empty())
1885 {
1886 initEntry(yyscanner);
1887 return;
1888 }
1889 bool found = false;
1890 if (yyextra->checkDupEntry)
1891 {
1892 for (auto &v : yyextra->current_root->children())
1893 {
1894 //printf("candidate %s<->%s section=%s!\n",qPrint(v->name),qPrint(yyextra->current->name), qPrint(v->section.to_string()));
1895 if (v->name==yyextra->current->name && v->section==yyextra->current->section) // name is already added, don't add it again
1896 {
1897 if (v->doc.empty() && !yyextra->current->doc.empty())
1898 {
1899 v->doc = yyextra->current->doc;
1900 v->docLine = yyextra->current->docLine;
1901 v->docFile = yyextra->current->docFile;
1902 }
1903 if (v->brief.empty() && !yyextra->current->brief.empty())
1904 {
1905 v->brief = yyextra->current->brief;
1906 v->briefLine = yyextra->current->briefLine;
1907 v->briefFile = yyextra->current->briefFile;
1908 }
1909 if (v->type.empty() && !yyextra->current->type.empty())
1910 {
1911 //printf("copying type '%s' from '%s' to '%s'\n",qPrint(yyextra->current->type),qPrint(yyextra->current->name),qPrint(v->name));
1912 v->type = yyextra->current->type;
1913 }
1914 found=true;
1915 break;
1916 }
1917 }
1918 }
1919 if (!found)
1920 {
1921 yyextra->previous = yyextra->current;
1922 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
1923 }
1924 initEntry(yyscanner);
1925}
1926
1927static void addEntry(yyscan_t yyscanner)
1928{
1929 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1930
1931 auto doc = yyextra->current->doc;
1932 auto docLine = yyextra->current->docLine;
1933 auto docFile = yyextra->current->docFile;
1934 auto brief = yyextra->current->brief;
1935 auto briefLine = yyextra->current->briefLine;
1936 auto briefFile = yyextra->current->briefFile;
1937
1938 yyextra->previous = yyextra->current;
1939 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
1940 initEntry(yyscanner);
1941
1942 yyextra->current->doc = doc;
1943 yyextra->current->docLine = docLine;
1944 yyextra->current->docFile = docFile;
1945 yyextra->current->brief = brief;
1946 yyextra->current->briefLine = briefLine;
1947 yyextra->current->briefFile = briefFile;
1948}
1949
1950static void setProtection(yyscan_t yyscanner)
1951{
1952 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1953 if (!yyextra->current->name.empty() && yyextra->current->name.at(0)=='_')
1954 {
1955 if (yyextra->current->name.at(1)=='_') // mark as private
1956 {
1957 yyextra->current->protection=Protection::Private;
1958 }
1959 else // mark as protected
1960 {
1961 yyextra->current->protection=Protection::Protected;
1962 }
1963 }
1964}
1965
1966static void docVariable(yyscan_t yyscanner,const char *name)
1967{
1968 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1969 yyextra->current->name = name;
1970 yyextra->current->section=EntryType::makeVariable();
1971 yyextra->current->fileName = yyextra->fileName;
1972 yyextra->current->startLine = yyextra->yyLineNr;
1973 yyextra->current->bodyLine = yyextra->yyLineNr;
1974 yyextra->current->type.clear();
1975 setProtection(yyscanner);
1976 yyextra->checkDupEntry = true;
1977}
1978
1979static void newVariable(yyscan_t yyscanner)
1980{
1981 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1982 setProtection(yyscanner);
1983 if (yyextra->current_root->section.isCompound()) // mark as class variable
1984 {
1985 yyextra->current->isStatic = true;
1986 }
1987 newEntry(yyscanner);
1988}
1989
1990static void newTypeAlias(yyscan_t yyscanner)
1991{
1992 //struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1993 //printf("*** newTypeAlias %s\n",qPrint(yyextra->current->name));
1994 newEntry(yyscanner);
1995}
1996
1997static void addVariable(yyscan_t yyscanner)
1998{
1999 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2000 setProtection(yyscanner);
2001 if (yyextra->current_root->section.isCompound()) // mark as class variable
2002 {
2003 yyextra->current->isStatic = true;
2004 }
2005 addEntry(yyscanner);
2006}
2007
2008static void newFunction(yyscan_t yyscanner)
2009{
2010 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2011 if (yyextra->current->name.startsWith("__") && yyextra->current->name.endsWith("__"))
2012 {
2013 // special method name, see
2014 // http://docs.python.org/ref/specialnames.html
2015 yyextra->current->protection=Protection::Public;
2016 }
2017 else
2018 {
2019 setProtection(yyscanner);
2020 }
2021}
2022
2023static inline int computeIndent(const char *s)
2024{
2025 int col=0;
2026 int tabSize=Config_getInt(TAB_SIZE);
2027 const char *p=s;
2028 char c;
2029 while ((c=*p++))
2030 {
2031 if (c==' ') col++;
2032 else if (c=='\t') col+=tabSize-(col%tabSize);
2033 else break;
2034 }
2035 return col;
2036}
2037
2039{
2040 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2041 auto it = yyextra->packageNameCache.find(path.str());
2042 if (it!=yyextra->packageNameCache.end())
2043 {
2044 return it->second;
2045 }
2046 FileInfo pf(path.str()+"/__init__.py"); // found package initialization file
2047 if (pf.exists())
2048 {
2049 size_t i=path.rfind('/');
2050 if (i!=DString::npos)
2051 {
2052 DString scope = findPackageScopeFromPath(yyscanner,path.left(i));
2053 if (!scope.empty())
2054 {
2055 scope+="::";
2056 }
2057 scope+=path.mid(i+1);
2058 yyextra->packageNameCache.emplace(path.str(),scope.str());
2059 return scope;
2060 }
2061 }
2062 return "";
2063}
2064
2065static DString findPackageScope(yyscan_t yyscanner,const DString &fileName)
2066{
2067 if (fileName.empty()) return fileName;
2068 FileInfo fi(fileName.str());
2069 return findPackageScopeFromPath(yyscanner,fi.dirPath(true));
2070}
2071
2072static void addFrom(yyscan_t yyscanner,bool all)
2073{
2074 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2075 DString item=all ? yyextra->packageName : yyextra->packageName+"."+yytext;
2076 yyextra->current->name=removeRedundantWhiteSpace(substitute(item,".","::"));
2077 yyextra->current->fileName = yyextra->fileName;
2078 //printf("Adding using declaration: found:%s:%d name=%s\n",qPrint(yyextra->fileName),yyextra->yyLineNr,qPrint(yyextra->current->name));
2079 yyextra->current->section=all ? EntryType::makeUsingDir() : EntryType::makeUsingDecl();
2080 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
2081 initEntry(yyscanner);
2082}
2083//-----------------------------------------------------------------------------
2084
2085static void lineCount(yyscan_t yyscanner)
2086{
2087 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2088 DBG_CTX((stderr,"yyextra->yyLineNr=%d\n",yyextra->yyLineNr));
2089 for (const char *p = yytext; *p; ++p)
2090 {
2091 yyextra->yyLineNr += (*p == '\n') ;
2092 }
2093}
2094
2095static void incLineNr(yyscan_t yyscanner)
2096{
2097 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2098 DBG_CTX((stderr,"yyextra->yyLineNr=%d\n",yyextra->yyLineNr));
2099 yyextra->yyLineNr++;
2100}
2101
2102//-----------------------------------------------------------------
2103static void startCommentBlock(yyscan_t yyscanner,bool brief)
2104{
2105 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2106 if (brief)
2107 {
2108 yyextra->current->briefFile = yyextra->fileName;
2109 yyextra->current->briefLine = yyextra->yyLineNr;
2110 }
2111 else
2112 {
2113 yyextra->current->docFile = yyextra->fileName;
2114 yyextra->current->docLine = yyextra->yyLineNr;
2115 }
2116}
2117
2118static void handleCommentBlock(yyscan_t yyscanner,const DString &doc,bool brief)
2119{
2120 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2121 //printf("handleCommentBlock(doc=[%s] brief=%d yyextra->docBlockInBody=%d yyextra->docBlockJavaStyle=%d\n",
2122 // qPrint(doc),brief,yyextra->docBlockInBody,yyextra->docBlockJavaStyle);
2123
2124 // TODO: Fix me
2125 yyextra->docBlockInBody=false;
2126
2127 if (!yyextra->current->doc.empty())
2128 {
2129 yyextra->current->doc=yyextra->current->doc.stripWhiteSpace()+"\n\n";
2130 }
2131 if (yyextra->docBlockInBody && yyextra->previous && !yyextra->previous->doc.empty())
2132 {
2133 yyextra->previous->doc=yyextra->previous->doc.stripWhiteSpace()+"\n\n";
2134 }
2135
2136 int position = 0;
2137 bool needsEntry = false;
2138 int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine;
2139 Markdown markdown(yyextra->fileName,lineNr);
2140 GuardedSectionStack guards;
2141 DString strippedDoc = stripIndentation(doc,true);
2142 //printf("stippedDoc=[%s]\n",qPrint(strippedDoc));
2143 DString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(strippedDoc,lineNr) : strippedDoc;
2144 while (yyextra->commentScanner.parseCommentBlock(
2145 yyextra->thisParser,
2146 (yyextra->docBlockInBody && yyextra->previous) ? yyextra->previous.get() : yyextra->current.get(),
2147 processedDoc, // text
2148 yyextra->fileName, // file
2149 lineNr,
2150 yyextra->docBlockInBody ? false : brief,
2151 yyextra->docBlockJavaStyle, // javadoc style // or false,
2152 yyextra->docBlockInBody,
2153 yyextra->protection,
2154 position,
2155 needsEntry,
2156 Config_getBool(MARKDOWN_SUPPORT),
2157 &guards
2158 )
2159 ) // need to start a new entry
2160 {
2161 if (needsEntry)
2162 {
2163 newEntry(yyscanner);
2164 }
2165 }
2166 if (needsEntry)
2167 {
2168 newEntry(yyscanner);
2169 }
2170
2171}
2172
2173static void endOfDef(yyscan_t yyscanner,int correction)
2174{
2175 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2176 //printf("endOfDef at=%d\n",yyextra->yyLineNr);
2177 if (yyextra->bodyEntry)
2178 {
2179 yyextra->bodyEntry->endBodyLine = yyextra->yyLineNr-correction;
2180 yyextra->bodyEntry = 0;
2181 }
2182 newEntry(yyscanner);
2183 //yyextra->insideConstructor = false;
2184}
2185
2186static inline void addToString(yyscan_t yyscanner,const char *s)
2187{
2188 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2189 if (yyextra->copyString) (*yyextra->copyString) << s;
2190}
2191
2192static void initTriDoubleQuoteBlock(yyscan_t yyscanner)
2193{
2194 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2195 yyextra->docBlockContext = YY_START;
2196 yyextra->docBlockInBody = false;
2197 yyextra->docBlockJavaStyle = true;
2198 yyextra->docBlockSpecial = yytext[strlen(yytext) - 1]=='!' || !Config_getBool(PYTHON_DOCSTRING);
2199 yyextra->docBlock.clear();
2200 yyextra->commentIndent = yyextra->curIndent;
2201 yyextra->doubleQuote = true;
2202 startCommentBlock(yyscanner,false);
2203}
2204
2205static void initTriSingleQuoteBlock(yyscan_t yyscanner)
2206{
2207 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2208 yyextra->docBlockContext = YY_START;
2209 yyextra->docBlockInBody = false;
2210 yyextra->docBlockJavaStyle = true;
2211 yyextra->docBlockSpecial = yytext[strlen(yytext) - 1]=='!' || !Config_getBool(PYTHON_DOCSTRING);
2212 yyextra->docBlock.clear();
2213 yyextra->commentIndent = yyextra->curIndent;
2214 yyextra->doubleQuote = false;
2215 startCommentBlock(yyscanner,false);
2216}
2217
2218static void initSpecialBlock(yyscan_t yyscanner)
2219{
2220 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2221 yyextra->docBlockContext = YY_START;
2222 yyextra->docBlockInBody = false;
2223 yyextra->docBlockJavaStyle = true;
2224 yyextra->docBrief = true;
2225 yyextra->docBlock.clear();
2226 yyextra->commentIndent = yyextra->curIndent;
2227 startCommentBlock(yyscanner,false);
2228}
2229
2230static void searchFoundDef(yyscan_t yyscanner)
2231{
2232 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2233 yyextra->current->fileName = yyextra->fileName;
2234 yyextra->current->startLine = yyextra->yyLineNr;
2235 yyextra->current->bodyLine = yyextra->yyLineNr;
2236 yyextra->current->section = EntryType::makeFunction();
2237 yyextra->current->lang = SrcLangExt::Python;
2238 yyextra->current->virt = Specifier::Normal;
2239 yyextra->current->isStatic = yyextra->isStatic;
2240 yyextra->current->mtype = yyextra->mtype = MethodTypes::Method;
2241 yyextra->current->type.clear();
2242 yyextra->current->name.clear();
2243 yyextra->current->args.clear();
2244 yyextra->current->argList.clear();
2245 yyextra->packageCommentAllowed = false;
2246 yyextra->isStatic=false;
2247 //printf("searchFoundDef at=%d\n",yyextra->yyLineNr);
2248}
2249
2250static void searchFoundClass(yyscan_t yyscanner)
2251{
2252 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2253 yyextra->current->section = EntryType::makeClass();
2254 yyextra->current->argList.clear();
2255 yyextra->current->type += "class" ;
2256 yyextra->current->fileName = yyextra->fileName;
2257 yyextra->current->startLine = yyextra->yyLineNr;
2258 yyextra->current->bodyLine = yyextra->yyLineNr;
2259 yyextra->packageCommentAllowed = false;
2260}
2261
2262static void searchFoundTypeAlias(yyscan_t yyscanner)
2263{
2264 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2265 yyextra->current->section = EntryType::makeVariable();
2266 yyextra->current->argList.clear();
2267 yyextra->current->type = "typedef " ;
2268 yyextra->current->spec.setAlias(true);
2269 yyextra->current->fileName = yyextra->fileName;
2270 yyextra->current->startLine = yyextra->yyLineNr;
2271 yyextra->current->bodyLine = yyextra->yyLineNr;
2272 yyextra->packageCommentAllowed = false;
2273}
2274
2275static void handleParamComment(yyscan_t yyscanner,const DString &doc)
2276{
2277 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2278 yyextra->curIndent=computeIndent(yytext);
2279 initSpecialBlock(yyscanner);
2280 if (!yyextra->current->argList.empty())
2281 {
2282 yyextra->docBlock += "@param ";
2283 yyextra->docBlock += yyextra->current->argList.back().name;
2284 yyextra->docBlock += " ";
2285 }
2286 yyextra->docBlockContext = YY_START;
2287}
2288
2289//----------------------------------------------------------------------------
2290
2291static void parseCompounds(yyscan_t yyscanner,std::shared_ptr<Entry> rt)
2292{
2293 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2294 //printf("parseCompounds(%s)\n",qPrint(rt->name));
2295 for (size_t i=0; i<rt->children().size(); ++i)
2296 {
2297 std::shared_ptr<Entry> ce = rt->children()[i];
2298 if (!ce->program.empty())
2299 {
2300 //fprintf(stderr,"parseCompounds: -- %s (line %d) ---------\n%s\n---------------\n",
2301 // qPrint(ce->name), ce->bodyLine, qPrint(ce->program));
2302 // init scanner state
2303 yyextra->programStr = ce->program.str();
2304 yyextra->inputString = yyextra->programStr.data();
2305 yyextra->inputPosition = 0;
2306 yyextra->firstPass = false;
2307 pyscannerYYrestart( nullptr, yyscanner );
2308 if (ce->section.isCompound())
2309 {
2310 yyextra->specialBlock = false;
2311 yyextra->current_root = ce;
2312 BEGIN( Search );
2313 }
2314 else if (ce->parent())
2315 {
2316 yyextra->current_root = rt;
2317 //printf("Searching for member variables in %s parent=%s\n",
2318 // qPrint(ce->name),qPrint(ce->parent->name));
2319 BEGIN( SearchMemVars );
2320 }
2321 yyextra->fileName = ce->fileName;
2322 yyextra->yyLineNr = ce->bodyLine ;
2323 yyextra->current = std::make_shared<Entry>();
2324 initEntry(yyscanner);
2325
2326 yyextra->checkDupEntry = false;
2327
2328 DString name = ce->name;
2329 yyextra->commentScanner.enterCompound(yyextra->fileName,yyextra->yyLineNr,name);
2330
2331 pyscannerYYlex(yyscanner) ;
2332 yyextra->lexInit=true;
2333
2334 yyextra->programStr.clear();
2335 ce->program.str(std::string());
2336
2337 yyextra->commentScanner.leaveCompound(yyextra->fileName,yyextra->yyLineNr,name);
2338
2339 }
2340 parseCompounds(yyscanner,ce);
2341 }
2342}
2343
2344//----------------------------------------------------------------------------
2345
2346
2347static void parseMain(yyscan_t yyscanner, const DString &fileName,const char *fileBuf,const std::shared_ptr<Entry> &rt)
2348{
2349 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2350 initParser(yyscanner);
2351
2352 if (fileBuf==nullptr || fileBuf[0]=='\0') return;
2353
2354 yyextra->inputString = fileBuf;
2355 yyextra->inputPosition = 0;
2356
2357 yyextra->protection = Protection::Public;
2358 yyextra->mtype = MethodTypes::Method;
2359 yyextra->isStatic = false;
2360 yyextra->virt = Specifier::Normal;
2361 yyextra->current_root = rt;
2362 yyextra->specialBlock = false;
2363
2364 yyextra->yyLineNr = 1 ;
2365 yyextra->fileName = fileName;
2366 yyextra->checkDupEntry = false;
2367 yyextra->firstPass = true;
2368 //setContext();
2369 msg("Parsing file {}...\n",yyextra->fileName);
2370
2371 FileInfo fi(fileName.str());
2372 yyextra->moduleScope = findPackageScope(yyscanner,fileName);
2373 DString baseName=fi.baseName();
2374 if (baseName!="__init__") // package initializer file is not a package itself
2375 {
2376 if (!yyextra->moduleScope.empty())
2377 {
2378 yyextra->moduleScope+="::";
2379 }
2380 yyextra->moduleScope+=baseName;
2381 }
2382
2383 // add namespaces for each scope
2384 DString scope = yyextra->moduleScope;
2385 size_t startPos = 0;
2386 size_t pos = 0;
2387 do
2388 {
2389 pos = scope.find("::",startPos);
2390 if (pos==DString::npos)
2391 {
2392 startPos = pos = scope.length();
2393 }
2394 else
2395 {
2396 startPos = pos+2;
2397 }
2398 yyextra->current = std::make_shared<Entry>();
2399 initEntry(yyscanner);
2400 yyextra->current->name = scope.left(pos);
2401 yyextra->current->section = EntryType::makeNamespace();
2402 yyextra->current->type = "namespace";
2403 yyextra->current->fileName = yyextra->fileName;
2404 yyextra->current->startLine = yyextra->yyLineNr;
2405 yyextra->current->bodyLine = yyextra->yyLineNr;
2406 yyextra->current_root = yyextra->current;
2407 rt->moveToSubEntryAndRefresh(yyextra->current);
2408 } while (pos<scope.length());
2409
2410 initParser(yyscanner);
2411
2412 yyextra->commentScanner.enterFile(yyextra->fileName,yyextra->yyLineNr);
2413
2414 yyextra->current->reset();
2415 initEntry(yyscanner);
2416 pyscannerYYrestart(nullptr,yyscanner);
2417 BEGIN( Search );
2418 pyscannerYYlex(yyscanner);
2419 yyextra->lexInit=true;
2420
2421 yyextra->commentScanner.leaveFile(yyextra->fileName,yyextra->yyLineNr);
2422
2423 yyextra->programStr.clear();
2424 yyextra->current_root->program.str(std::string());
2425
2426 parseCompounds(yyscanner, yyextra->current_root);
2427}
2428
2429//----------------------------------------------------------------------------
2430
2431static void parsePrototype(yyscan_t yyscanner,const DString &text)
2432{
2433 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2434 //printf("**** parsePrototype(%s) begin\n",qPrint(text));
2435 if (text.empty())
2436 {
2437 warn(yyextra->fileName,yyextra->yyLineNr,"Empty prototype found!");
2438 return;
2439 }
2440
2441 yyextra->specialBlock = false;
2442 yyextra->packageCommentAllowed = false;
2443
2444 // save scanner state
2445 YY_BUFFER_STATE orgState = YY_CURRENT_BUFFER;
2446 yy_switch_to_buffer(yy_create_buffer(nullptr, YY_BUF_SIZE, yyscanner), yyscanner);
2447 const char *orgInputString = yyextra->inputString;
2448 int orgInputPosition = yyextra->inputPosition;
2449
2450 // set new string
2451 yyextra->inputString = text.data();
2452 yyextra->inputPosition = 0;
2453 pyscannerYYrestart( nullptr, yyscanner );
2454
2455 BEGIN( FunctionDec );
2456
2457 pyscannerYYlex(yyscanner);
2458 yyextra->lexInit=true;
2459
2460 yyextra->current->name = yyextra->current->name.stripWhiteSpace();
2461 if (yyextra->current->section.isMemberDoc() && yyextra->current->args.empty())
2462 {
2463 yyextra->current->section = EntryType::makeVariableDoc();
2464 }
2465
2466 // restore original scanner state
2467
2468 yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner);
2469 yy_switch_to_buffer(orgState, yyscanner);
2470
2471 yyextra->inputString = orgInputString;
2472 yyextra->inputPosition = orgInputPosition;
2473
2474 //printf("**** parsePrototype end\n");
2475}
2476
2477//----------------------------------------------------------------------------
2478
2484
2486{
2487 pyscannerYYlex_init_extra(&p->state,&p->yyscanner);
2488#ifdef FLEX_DEBUG
2489 pyscannerYYset_debug(Debug::isFlagSet(Debug::Lex_pyscanner)?1:0,p->yyscanner);
2490#endif
2491}
2492
2494{
2495 pyscannerYYlex_destroy(p->yyscanner);
2496}
2497
2498
2500 const char *fileBuf,
2501 const std::shared_ptr<Entry> &root,
2502 ClangTUParser * /*clangParser*/)
2503{
2504 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
2505 yyextra->thisParser = this;
2506 DebugLex debugLex(Debug::Lex_pyscanner, __FILE__, qPrint(fileName));
2507 ::parseMain(p->yyscanner, fileName,fileBuf,root);
2508
2509 // May print the AST for debugging purposes
2510 // printAST(global_root);
2511}
2512
2514{
2515 return false;
2516}
2517
2519{
2520 ::parsePrototype(p->yyscanner,text);
2521}
2522
2523//----------------------------------------------------------------------------
2524
2525#include "pyscanner.l.h"
Clang parser object for a single translation unit, which consists of a source file and the directly o...
Definition clangparser.h:25
size_t rfind(char c, size_t pos=npos) const
Definition dstring.h:244
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:318
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:178
size_t find(char c, size_t pos=0) const
Definition dstring.h:239
DString left(size_t len) const
Definition dstring.h:306
const std::string & str() const
Definition dstring.h:645
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:157
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:151
@ Lex_pyscanner
Definition debug.h:68
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:132
Minimal replacement for QFileInfo.
Definition fileinfo.h:26
bool exists() const
Definition fileinfo.cpp:34
std::string dirPath(bool absPath=true) const
Definition fileinfo.cpp:141
std::string baseName() const
Definition fileinfo.cpp:127
Helper class to process markdown formatted text.
Definition markdown.h:33
DString process(const DString &input, int &startNewlines, bool fromParseInput=false)
void parseInput(const DString &fileName, const char *fileBuf, const std::shared_ptr< Entry > &root, ClangTUParser *clangParser) override
Parses a single input file with the goal to build an Entry tree.
Definition pyscanner.l:2499
std::unique_ptr< Private > p
Definition pyscanner.h:46
~PythonOutlineParser() override
Definition pyscanner.l:2493
void parsePrototype(const DString &text) override
Callback function called by the comment block scanner.
Definition pyscanner.l:2518
bool needsPreprocessing(const DString &extension) const override
Returns true if the language identified by extension needs the C preprocessor to be run before feed t...
Definition pyscanner.l:2513
#define YY_BUF_SIZE
Definition commentcnv.l:19
std::stack< GuardedSection > GuardedSectionStack
Definition commentscan.h:48
#define Config_getInt(name)
Definition config.h:34
#define Config_getBool(name)
Definition config.h:33
static void startCommentBlock(yyscan_t yyscanner, bool)
#define msg(fmt,...)
Definition message.h:94
Definition dstring.h:913
static void parseMain(yyscan_t yyscanner, const DString &fileName, const char *fileBuf, const std::shared_ptr< Entry > &rt)
Definition pyscanner.l:2347
static void parsePrototype(yyscan_t yyscanner, const DString &text)
Definition pyscanner.l:2431
static void parseCompounds(yyscan_t yyscanner, std::shared_ptr< Entry > rt)
Definition pyscanner.l:2291
pyscannerYY_state state
Definition pyscanner.l:2482
DString stripIndentation(const DString &s, bool skipFirstLine)
Definition util.cpp:4683
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
Definition xml.l:230