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