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