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