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
125
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"
165
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:1770
static void incLineNr(yyscan_t yyscanner)
Definition pyscanner.l:1972
static void docVariable(yyscan_t yyscanner, const char *s)
Definition pyscanner.l:1850
static void initSpecialBlock(yyscan_t yyscanner)
Definition pyscanner.l:2102
static void initTriSingleQuoteBlock(yyscan_t yyscanner)
Definition pyscanner.l:2085
static int computeIndent(const char *s)
Definition pyscanner.l:1900
static void addFrom(yyscan_t yyscanner, bool all)
Definition pyscanner.l:1949
static void setProtection(yyscan_t yyscanner)
Definition pyscanner.l:1834
static void initParser(yyscan_t yyscanner)
Definition pyscanner.l:1744
static void endOfDef(yyscan_t yyscanner, int correction=0)
Definition pyscanner.l:2049
static QCString findPackageScope(yyscan_t yyscanner, const QCString &fileName)
Definition pyscanner.l:1942
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
Definition pyscanner.l:1734
static void searchFoundClass(yyscan_t yyscanner)
Definition pyscanner.l:2134
static const char * stateToString(int state)
static QCString findPackageScopeFromPath(yyscan_t yyscanner, const QCString &path)
Definition pyscanner.l:1915
static void newVariable(yyscan_t yyscanner)
Definition pyscanner.l:1863
static void initTriDoubleQuoteBlock(yyscan_t yyscanner)
Definition pyscanner.l:2068
static void handleCommentBlock(yyscan_t yyscanner, const QCString &doc, bool brief)
Definition pyscanner.l:1995
static void searchFoundDef(yyscan_t yyscanner)
Definition pyscanner.l:2114
static void addEntry(yyscan_t yyscanner)
Definition pyscanner.l:1811
static const char * getLexerFILE()
Definition pyscanner.l:163
static void startCommentBlock(yyscan_t yyscanner, bool brief)
Definition pyscanner.l:1980
static void newFunction(yyscan_t yyscanner)
Definition pyscanner.l:1885
static void addVariable(yyscan_t yyscanner)
Definition pyscanner.l:1874
static void addToString(yyscan_t yyscanner, const char *s)
Definition pyscanner.l:2062
static void initEntry(yyscan_t yyscanner)
Definition pyscanner.l:1755
#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
Kind of method.
Definition types.h:32
Protection
Protection level of members.
Definition types.h:26
@ Public
Definition types.h:26
Specifier
Virtualness of a member.
Definition types.h:29
@ Normal
Definition types.h:29
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
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
static int computeIndent(const char *s)
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:245
@ Property
Definition types.h:32
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 }
static void addVariable(yyscan_t yyscanner, QCString type, QCString name)
Definition code.l:2181
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 }
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:477
QCString removeRedundantWhiteSpace(const QCString &s)
Definition util.cpp:578
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:672
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 == QCString(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}
763
764<FunctionBody>{
765 \n{B}/{IDENTIFIER}[^{LETTER}{DIGIT}_] {
766 DBG_CTX((stderr,"indent %d<=%d\n",computeIndent(&yytext[1]),yyextra->indent));
767 if (computeIndent(&yytext[1])<=yyextra->indent)
768 {
769 unput_string(yytext,yyleng);
770 endOfDef(yyscanner);
771 //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
772 BEGIN(Search);
773 }
774 else
775 {
776 incLineNr(yyscanner);
777 yyextra->current->program << yytext;
778 }
779 }
#define unput_string(yytext, yyleng)
780 \n{B}/"##" {
781 if (computeIndent(&yytext[1])<=yyextra->indent)
782 {
783 unput_string(yytext,yyleng);
784 endOfDef(yyscanner);
785 //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
786 BEGIN(Search);
787 }
788 else
789 {
790 incLineNr(yyscanner);
791 yyextra->current->program << yytext;
792 }
793 }
794 <<EOF>> {
795 endOfDef(yyscanner);
796 yyterminate();
797 }
#define yyterminate()
798 ^{BB}/\n { // skip empty line
799 yyextra->current->program << yytext;
800 }
801 ^{BB} { // something at indent >0
802 yyextra->current->program << yytext;
803 yyextra->curIndent = computeIndent(yytext);
804 if (yyextra->curIndent<=yyextra->indent)
805 // jumped out of the function
806 {
807 endOfDef(yyscanner,1);
808 BEGIN(Search);
809 }
810 }
811 "'" { // start of a single quoted string
812 yyextra->current->program << yytext;
813 yyextra->stringContext=YY_START;
814 yyextra->specialBlock = FALSE;
815 yyextra->copyString=&yyextra->current->program;
816 BEGIN( SingleQuoteString );
817 }
818 "\"" { // start of a double quoted string
819 yyextra->current->program << yytext;
820 yyextra->stringContext=YY_START;
821 yyextra->specialBlock = FALSE;
822 yyextra->copyString=&yyextra->current->program;
823 BEGIN( DoubleQuoteString );
824 }
825 [^ \t\n#'".]+ { // non-special stuff
826 yyextra->current->program << yytext;
827 yyextra->specialBlock = FALSE;
828 }
829 ^{POUNDCOMMENT} { // normal comment
830 yyextra->current->program << yytext;
831 }
832 "#".* { // comment half way
833 yyextra->current->program << yytext;
834 }
835 {NEWLINE} {
836 incLineNr(yyscanner);
837 yyextra->current->program << yytext;
838 }
839 . { // any character
840 yyextra->current->program << *yytext;
841 yyextra->specialBlock = FALSE;
842 }
843
844 {TRIDOUBLEQUOTE} { // start of a comment block
845 yyextra->current->program << yytext;
846 initTriDoubleQuoteBlock(yyscanner);
847 BEGIN(TripleComment);
848 }
849
850 {TRISINGLEQUOTE} { // start of a comment block
851 yyextra->current->program << yytext;
852 initTriSingleQuoteBlock(yyscanner);
853 BEGIN(TripleComment);
854 }
855
856}
857
858<FunctionDec>{
859 {IDENTIFIER} {
860 //found function name
861 yyextra->current->name = yytext;
862 yyextra->current->name = yyextra->current->name.stripWhiteSpace();
863 newFunction(yyscanner);
864 }
865 {B}":"{B} { // function without arguments
866 yyextra->specialBlock = TRUE; // expecting a docstring
867 yyextra->bodyEntry = yyextra->current;
868 yyextra->current->bodyLine = yyextra->yyLineNr;
869 BEGIN(FunctionBody);
870 }
871
872 "->" {
873 yyextra->defVal.str(std::string());
874 yyextra->braceCount = 0;
875 BEGIN(FunctionTypeAnnotation);
876 }
877 {B}"(" {
878 yyextra->funcParamsEnd = FALSE;
879 yyextra->current->bodyLine = yyextra->yyLineNr;
880 BEGIN(FunctionParams);
881 }
882 ")" { // end of parameter list
883 if (yyextra->current->argList.empty())
884 {
885 yyextra->current->argList.setNoParameters(TRUE);
886 }
887 yyextra->current->args = argListToString(yyextra->current->argList);
888 yyextra->funcParamsEnd = TRUE;
889 }
QCString argListToString(const ArgumentList &al, bool useCanonicalType, bool showDefVals)
Definition util.cpp:1174
890}
891
892<FunctionParams>{
893 {BB} {
894 }
895
896 "," {
897 if (!yyextra->argType.isEmpty())
898 {
899 Argument a;
900 a.name = "";
901 a.type = yyextra->argType;
902 yyextra->current->argList.push_back(a);
903 yyextra->argType = "";
904 }
905 }
This class contains the information about the argument of a function or template.
Definition arguments.h:27
QCString type
Definition arguments.h:37
QCString name
Definition arguments.h:39
906
907 [\*]+ {
908 yyextra->argType = yytext;
909 }
910 {IDENTIFIER} { // Name of parameter
911 lineCount(yyscanner);
912 Argument a;
913 a.name = QCString(yytext).stripWhiteSpace();
914 a.type = yyextra->argType;
915 yyextra->current->argList.push_back(a);
916 yyextra->argType = "";
917 }
918 "=" { // default value
919 // TODO: this rule is too simple, need to be able to
920 // match things like =")" as well!
921 yyextra->defVal.str(std::string());
922 yyextra->braceCount = 0;
923 BEGIN(FunctionParamDefVal);
924 }
925 ")" {
926 if (!yyextra->argType.isEmpty())
927 {
928 Argument a;
929 a.name = "";
930 a.type = yyextra->argType;
931 yyextra->current->argList.push_back(a);
932 yyextra->argType = "";
933 }
934 unput(*yytext);
935 BEGIN(FunctionDec);
936 }
937 ":"{B} {
938 yyextra->defVal.str(std::string());
939 yyextra->braceCount = 0;
940 BEGIN(FunctionAnnotation);
941 }
942 {POUNDCOMMENT} { // a comment
943 }
944 {PARAMNONEMPTY} { // Default rule inside arguments.
945 }
946
947}
948
949<FunctionTypeAnnotation>{
950 "{" |
951 "[" |
952 "(" {
953 ++yyextra->braceCount;
954 yyextra->defVal << *yytext;
955 }
956 "}" |
957 "]" |
958 ")" {
959 --yyextra->braceCount;
960 yyextra->defVal << *yytext;
961 }
962 ":" {
963 if (yyextra->braceCount == 0)
964 {
965 yyextra->current->type = yyextra->defVal.str();
966 unput(*yytext);
967 BEGIN(FunctionDec);
968 }
969 else
970 yyextra->defVal << *yytext;
971 }
972 "'" {
973 yyextra->defVal << *yytext;
974 yyextra->copyString=&yyextra->defVal;
975 yyextra->stringContext=FunctionTypeAnnotation;
976 BEGIN(SingleQuoteString);
977 }
978 "\"" {
979 yyextra->defVal << *yytext;
980 yyextra->copyString=&yyextra->defVal;
981 yyextra->stringContext=FunctionTypeAnnotation;
982 BEGIN(DoubleQuoteString);
983 }
984 \n {
985 yyextra->defVal << *yytext;
986 incLineNr(yyscanner);
987 }
988 . {
989 yyextra->defVal << *yytext;
990 }
991}
992
993<FunctionAnnotation>{
994 "{" |
995 "[" |
996 "(" {
997 ++yyextra->braceCount;
998 yyextra->defVal << *yytext;
999 }
1000 "}" |
1001 "]" {
1002 --yyextra->braceCount;
1003 yyextra->defVal << *yytext;
1004 }
1005 ")" |
1006 "=" |
1007 "," {
1008 if (yyextra->braceCount == 0)
1009 {
1010 if (!yyextra->current->argList.empty())
1011 yyextra->current->argList.back().type += yyextra->defVal.str();
1012 if (*yytext != ',')
1013 unput(*yytext);
1014 BEGIN(FunctionParams);
1015 }
1016 else
1017 {
1018 if (*yytext == ')')
1019 --yyextra->braceCount;
1020 yyextra->defVal << *yytext;
1021 }
1022 }
1023 "'" {
1024 yyextra->defVal << *yytext;
1025 yyextra->copyString=&yyextra->defVal;
1026 yyextra->stringContext=FunctionAnnotation;
1027 BEGIN(SingleQuoteString);
1028 }
1029 "\"" {
1030 yyextra->defVal << *yytext;
1031 yyextra->copyString=&yyextra->defVal;
1032 yyextra->stringContext=FunctionAnnotation;
1033 BEGIN(DoubleQuoteString);
1034 }
1035 \n {
1036 yyextra->defVal << *yytext;
1037 incLineNr(yyscanner);
1038 }
1039 . {
1040 yyextra->defVal << *yytext;
1041 }
1042}
1043
1044<FunctionParamDefVal>{
1045 "{" |
1046 "[" |
1047 "(" { // internal opening brace, assumption is that we have correct code so braces do match
1048 ++yyextra->braceCount;
1049 yyextra->defVal << *yytext;
1050 }
1051 "}" |
1052 "]" {
1053 --yyextra->braceCount;
1054 yyextra->defVal << *yytext;
1055 }
1056 ")" |
1057 "," {
1058 if (yyextra->braceCount == 0)
1059 {
1060 if (!yyextra->current->argList.empty())
1061 yyextra->current->argList.back().defval=QCString(yyextra->defVal.str()).stripWhiteSpace();
1062 if (*yytext == ')')
1063 unput(*yytext);
1064 BEGIN(FunctionParams);
1065 }
1066 else
1067 {
1068 if (*yytext == ')')
1069 --yyextra->braceCount;
1070 yyextra->defVal << *yytext;
1071 }
1072 }
1073
1074 "'" {
1075 yyextra->defVal << *yytext;
1076 yyextra->copyString=&yyextra->defVal;
1077 yyextra->stringContext=FunctionParamDefVal;
1078 BEGIN( SingleQuoteString );
1079 }
1080 "\"" {
1081 yyextra->defVal << *yytext;
1082 yyextra->copyString=&yyextra->defVal;
1083 yyextra->stringContext=FunctionParamDefVal;
1084 BEGIN( DoubleQuoteString );
1085 }
1086 \n {
1087 yyextra->defVal << *yytext;
1088 incLineNr(yyscanner);
1089 }
1090 . {
1091 yyextra->defVal << *yytext;
1092 }
1093}
1094
1095
1096<ClassBody>{
1097 \n/{IDENTIFIER}{BB} { // new def at indent 0
1098 if (computeIndent(&yytext[1])<=yyextra->indent)
1099 {
1100 int i;
1101 for (i=(int)yyleng-1;i>=0;i--)
1102 {
1103 unput(yytext[i]);
1104 }
1105 endOfDef(yyscanner);
1106 //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
1107 BEGIN(Search);
1108 }
1109 else
1110 {
1111 incLineNr(yyscanner);
1112 yyextra->current->program << yytext;
1113 }
1114 }
1115 \n/"##"[^#] { // start of a special comment at indent 0
1116 if (computeIndent(&yytext[1])<=yyextra->indent)
1117 {
1118 int i;
1119 for (i=(int)yyleng-1;i>=0;i--)
1120 {
1121 unput(yytext[i]);
1122 }
1123 endOfDef(yyscanner);
1124 //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
1125 BEGIN(Search);
1126 }
1127 else
1128 {
1129 incLineNr(yyscanner);
1130 yyextra->current->program << yytext;
1131 }
1132 }
1133 ^{BB}/\n { // skip empty line
1134 yyextra->current->program << yytext;
1135 }
1136 <<EOF>> {
1137 endOfDef(yyscanner);
1138 yyterminate();
1139 }
1140 ^{BB} { // something at indent >0
1141 yyextra->curIndent=computeIndent(yytext);
1142 DBG_CTX((stderr,"yyextra->curIndent=%d yyextra->indent=%d\n",yyextra->curIndent,yyextra->indent));
1143 if (yyextra->curIndent<=yyextra->indent)
1144 // jumped out of the class/method
1145 {
1146 endOfDef(yyscanner,1);
1147 yyextra->indent=yyextra->curIndent;
1148 // make sure the next rule matches ^...
1149 //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
1150 //yyextra->hideClassDocs = FALSE;
1151 BEGIN(Search);
1152 }
1153 else
1154 {
1155 yyextra->current->program << yytext;
1156 }
1157 }
1158 "'" { // start of a single quoted string
1159 yyextra->current->program << *yytext;
1160 yyextra->stringContext=YY_START;
1161 yyextra->specialBlock = FALSE;
1162 yyextra->copyString=&yyextra->current->program;
1163 BEGIN( SingleQuoteString );
1164 }
1165 "\"" { // start of a double quoted string
1166 yyextra->current->program << *yytext;
1167 yyextra->stringContext=YY_START;
1168 yyextra->specialBlock = FALSE;
1169 yyextra->copyString=&yyextra->current->program;
1170 BEGIN( DoubleQuoteString );
1171 }
1172 [^ \t\n#'"]+ { // non-special stuff
1173 yyextra->current->program << yytext;
1174 yyextra->specialBlock = FALSE;
1175 //yyextra->hideClassDocs = FALSE;
1176 }
1177 {NEWLINE} {
1178 yyextra->current->program << *yytext;
1179 incLineNr(yyscanner);
1180 }
1181 {POUNDCOMMENT} { // normal comment
1182 yyextra->current->program << yytext;
1183 }
1184 . { // any character
1185 yyextra->specialBlock = FALSE;
1186 yyextra->current->program << *yytext;
1187 }
1188 {TRIDOUBLEQUOTE} { // start of a comment block
1189 //if (!yyextra->hideClassDocs)
1190 yyextra->current->program << yytext;
1191 initTriDoubleQuoteBlock(yyscanner);
1192 BEGIN(TripleComment);
1193 }
1194
1195 {TRISINGLEQUOTE} { // start of a comment block
1196 //if (!yyextra->hideClassDocs)
1197 yyextra->current->program << yytext;
1198 initTriSingleQuoteBlock(yyscanner);
1199 BEGIN(TripleComment);
1200 }
1201}
1202
1203<ClassDec>{IDENTIFIER} {
1204 if (yyextra->current->type.isEmpty())
1205 {
1206 yyextra->current->type = "class";
1207 }
1208
1209 yyextra->current->section = EntryType::makeClass();
1210 yyextra->current->name = yytext;
1211 // we need to set the protectiion based on the "local" class name
1212 setProtection(yyscanner);
1213
1214 // prepend scope in case of nested classes
1215 if (yyextra->current_root->section.isScope())
1216 {
1217 //printf("*** Prepending scope %s to class %s\n",qPrint(yyextra->current_root->name),qPrint(yyextra->current->name));
1218 yyextra->current->name.prepend(yyextra->current_root->name+"::");
1219 }
1220
1221 yyextra->current->name = yyextra->current->name.stripWhiteSpace();
1222 yyextra->current->fileName = yyextra->fileName;
1223 yyextra->docBlockContext = YY_START;
1224 yyextra->docBlockInBody = FALSE;
1225 yyextra->docBlockJavaStyle = FALSE;
1226 yyextra->docBlock.clear();
1227
1228 BEGIN(ClassInheritance);
1229 }
1230
1231<ClassInheritance>{
1232 ({BB}|[\‍(,\‍)]) { // syntactic sugar for the list
1233 }
1234
1235 ":" { // begin of the class definition
1236 yyextra->specialBlock = TRUE; // expecting a docstring
1237 yyextra->current->bodyLine = yyextra->yyLineNr;
1238 yyextra->current->program.str(std::string());
1239 BEGIN(ClassCaptureIndent);
1240 }
1241
1242 {SCOPE} {
1243 yyextra->current->extends.emplace_back(
1245 );
1246 //Has base class-do stuff
1247 }
1248 "'" { // start of a single quoted string
1249 yyextra->stringContext=YY_START;
1250 BEGIN( SingleQuoteStringIgnore );
1251 }
1252 "\"" { // start of a double quoted string
1253 yyextra->stringContext=YY_START;
1254 BEGIN( DoubleQuoteStringIgnore );
1255 }
1256}
1257
1258<SingleQuoteStringIgnore>{
1259 "'" { // end of a single quoted string
1260 BEGIN(yyextra->stringContext);
1261 }
1262 . { }
1263}
1264<DoubleQuoteStringIgnore>{
1265 "\"" { // end of a double quoted string
1266 BEGIN(yyextra->stringContext);
1267 }
1268 . { }
1269}
1270
1271<ClassCaptureIndent>{
1272 "\n"|({BB}"\n") {
1273 // Blankline - ignore, keep looking for indentation.
1274 lineCount(yyscanner);
1275 yyextra->current->program << yytext;
1276 }
1277
1278 {TRIDOUBLEQUOTE} { // start of a comment block
1279 initTriDoubleQuoteBlock(yyscanner);
1280 yyextra->current->program << yytext;
1281 BEGIN(TripleComment);
1282 }
1283 {TRISINGLEQUOTE} { // start of a comment block
1284 initTriSingleQuoteBlock(yyscanner);
1285 yyextra->current->program << yytext;
1286 BEGIN(TripleComment);
1287 }
1288 {STARTDOCSYMS}[#]* { // start of a special comment
1289 initSpecialBlock(yyscanner);
1290 BEGIN(SpecialComment);
1291 }
1292 {POUNDCOMMENT} { // ignore comment with just one #
1293 }
1294 ^{BB} {
1295 yyextra->current->program << yytext;
1296 //yyextra->current->startLine = yyextra->yyLineNr;
1297 yyextra->curIndent=computeIndent(yytext);
1298 yyextra->bodyEntry = yyextra->current;
1299 DBG_CTX((stderr,"setting indent %d\n",yyextra->curIndent));
1300 //printf("yyextra->current->program=[%s]\n",qPrint(yyextra->current->program));
1301 //yyextra->hideClassDocs = TRUE;
1302 BEGIN(ClassBody);
1303 }
1304
1305 ""/({NONEMPTY}|{EXPCHAR}) {
1306 // Just pushback an empty class, and
1307 // resume parsing the body.
1308 newEntry(yyscanner);
1309 yyextra->current->program << yytext;
1310
1311 // printf("Failed to find indent - skipping!");
1312 BEGIN( Search );
1313 }
1314}
1315
1316
1317<VariableDec>{
1318 ":"{B}{IDENTIFIER} { //typing
1319 yyextra->startInit = FALSE;
1320 yyextra->current->type = substitute(yytext,":","");
1321 }
1322 {STARTDOCSYMS}"<"/.* { // start of a special comment
1323 yyextra->curIndent=computeIndent(yytext);
1324 yyextra->packageCommentAllowed = FALSE;
1325 initSpecialBlock(yyscanner);
1326 yyextra->docBlockContext = VariableEnd;
1327 BEGIN(SpecialComment);
1328 }
1329 "#".* { // comment
1330 BEGIN( VariableEnd );
1331 }
1332 \n {
1333 unput('\n');
1334 BEGIN( VariableEnd );
1335 }
1336}
1337
1338<VariableAtom>{
1339 [\‍(\[\{] {
1340 yyextra->current->initializer << *yytext;
1341 if (yyextra->atomStart==*yytext)
1342 {
1343 yyextra->atomCount++;
1344 }
1345 }
1346 [\‍)\]\}] {
1347 yyextra->current->initializer << *yytext;
1348 if (yyextra->atomEnd==*yytext)
1349 {
1350 yyextra->atomCount--;
1351 }
1352 if (yyextra->atomCount==0)
1353 {
1354 yyextra->startInit = FALSE;
1355 BEGIN(yyextra->atomContext);
1356 }
1357 }
1358 {TRIDOUBLEQUOTE} { // start of a comment block
1359 yyextra->specialBlock = FALSE;
1360 yyextra->current->program << yytext;
1361 initTriDoubleQuoteBlock(yyscanner);
1362 BEGIN(TripleComment);
1363 }
1364
1365 {TRISINGLEQUOTE} { // start of a comment block
1366 yyextra->specialBlock = FALSE;
1367 yyextra->current->program << yytext;
1368 initTriSingleQuoteBlock(yyscanner);
1369 BEGIN(TripleComment);
1370 }
1371 "'" {
1372 yyextra->stringContext=YY_START;
1373 yyextra->current->initializer << "'";
1374 yyextra->copyString=&yyextra->current->initializer;
1375 BEGIN( SingleQuoteString );
1376 }
1377 "\"" {
1378 yyextra->stringContext=YY_START;
1379 yyextra->current->initializer << "\"";
1380 yyextra->copyString=&yyextra->current->initializer;
1381 BEGIN( DoubleQuoteString );
1382 }
1383 {IDENTIFIER} {
1384 yyextra->current->initializer << yytext;
1385 }
1386 . {
1387 yyextra->current->initializer << *yytext;
1388 }
1389 \n {
1390 yyextra->current->initializer << *yytext;
1391 incLineNr(yyscanner);
1392 }
1393
1394}
1395
1396<VariableEnd>{
1397 \n {
1398 incLineNr(yyscanner);
1399 if (!stripWhiteSpace(yyextra->current->initializer.str()).empty())
1400 {
1401 newVariable(yyscanner);
1402 }
1403 BEGIN(Search);
1404 }
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
1405 . {
1406 unput(*yytext);
1407 newVariable(yyscanner);
1408 BEGIN(Search);
1409 }
1410 <<EOF>> { yyterminate();
1411 }
1412}
1413
1414<TripleComment>{
1415 {ENDTRIDOUBLEQUOTE} |
1416 {ENDTRISINGLEQUOTE} {
1417 // printf("Expected module block %d special=%d\n",yyextra->expectModuleDocs,yyextra->specialBlock);
1418 if (yyextra->doubleQuote==(yytext[0]=='"'))
1419 {
1420 if (yyextra->specialBlock) // expecting a docstring
1421 {
1422 QCString actualDoc=yyextra->docBlock;
1423 if (!yyextra->docBlockSpecial) // legacy unformatted docstring
1424 {
1425 if (!actualDoc.isEmpty())
1426 {
1427 stripIndentationVerbatim(actualDoc,yyextra->commentIndent);
1428 actualDoc.prepend("@iverbatim\n");
1429 actualDoc.append("@endiverbatim ");
1430 }
1431 }
1432 //printf("-------> yyextra->current=%p yyextra->bodyEntry=%p\n",yyextra->current,yyextra->bodyEntry);
1433 handleCommentBlock(yyscanner, actualDoc, FALSE);
1434 }
1435 else if (yyextra->packageCommentAllowed) // expecting module docs
1436 {
1437 QCString actualDoc=yyextra->docBlock;
1438 if (!yyextra->docBlockSpecial) // legacy unformatted docstring
1439 {
1440 if (!actualDoc.isEmpty())
1441 {
1442 stripIndentationVerbatim(actualDoc,yyextra->commentIndent);
1443 actualDoc.prepend("@iverbatim\n");
1444 actualDoc.append("@endiverbatim ");
1445 }
1446 }
1447 if (yyextra->moduleScope.startsWith("__") && yyextra->moduleScope.endsWith("__"))
1448 {
1449 actualDoc.prepend("\\namespace \\"+yyextra->moduleScope+" ");
1450 }
1451 else
1452 {
1453 actualDoc.prepend("\\namespace "+yyextra->moduleScope+" ");
1454 }
1455 handleCommentBlock(yyscanner, actualDoc, FALSE);
1456 }
1457 if ((yyextra->docBlockContext==ClassBody /*&& !yyextra->hideClassDocs*/) ||
1458 yyextra->docBlockContext==FunctionBody)
1459 {
1460 yyextra->current->program << yyextra->docBlock;
1461 yyextra->current->program << yytext;
1462 }
1463 //if (yyextra->hideClassDocs)
1464 //{
1465 // yyextra->current->startLine = yyextra->yyLineNr;
1466 //}
1467 //yyextra->hideClassDocs=FALSE;
1468 BEGIN(yyextra->docBlockContext);
1469 }
1470 else
1471 {
1472 yyextra->docBlock += yytext;
1473 }
1474 yyextra->packageCommentAllowed = FALSE;
1475 }
QCString & prepend(const char *s)
Definition qcstring.h:407
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
QCString & append(char c)
Definition qcstring.h:381
static void handleCommentBlock(yyscan_t yyscanner, const QCString &doc, bool brief)
void stripIndentationVerbatim(QCString &doc, const int indentationLevel)
Definition util.cpp:6367
1476
1477
1478 ^{BB} { // leading whitespace, compensate for """! / '''!
1479 if (yyextra->docBlockSpecial && yyleng >= yyextra->curIndent)
1480 yyextra->docBlock += yytext + yyextra->curIndent;
1481 else
1482 yyextra->docBlock += yytext;
1483 }
1484 [^"'\n \t\\@]+ {
1485 yyextra->docBlock += yytext;
1486 }
1487 \n {
1488 incLineNr(yyscanner);
1489 yyextra->docBlock += yytext;
1490 }
1491 {CMD}"ifile"{B}+"\""[^\n\"]+"\"" {
1492 yyextra->fileName = &yytext[6];
1493 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1494 yyextra->fileName = yyextra->fileName.mid(1,yyextra->fileName.length()-2);
1495 yyextra->docBlock+=yytext;
1496 }
1497 {CMD}"ifile"{B}+{FILEMASK} {
1498 yyextra->fileName = &yytext[6];
1499 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1500 yyextra->docBlock+=yytext;
1501 }
1502 {CMD}"iline"{LINENR}/[\n\.] |
1503 {CMD}"iline"{LINENR}{B} {
1504 bool ok = false;
1505 int nr = QCString(&yytext[6]).toInt(&ok);
1506 if (!ok)
1507 {
1508 warn(yyextra->fileName,yyextra->yyLineNr,"Invalid line number '%s' for iline command",yytext);
1509 }
1510 else
1511 {
1512 yyextra->yyLineNr = nr;
1513 }
1514 yyextra->docBlock+=yytext;
1515 }
int toInt(bool *ok=nullptr, int base=10) const
Definition qcstring.cpp:249
#define warn(file, line, fmt,...)
Definition message.h:59
1516 ({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command
1517 yyextra->docBlock+=yytext;
1518 }
1519 \\. { // escaped char TO be extended
1520 yyextra->docBlock += yytext;
1521 }
1522 . {
1523 yyextra->docBlock += yytext;
1524 }
1525}
1526
1527<SpecialComment>{
1528 ^{B}"#"("#")* { // skip leading hashes
1529 }
1530 \n/{B}"#" { // continuation of the comment on the next line
1531 yyextra->docBlock+='\n';
1532 yyextra->docBrief = FALSE;
1533 incLineNr(yyscanner);
1534 }
1535 {CMD}"ifile"{B}+"\""[^\n\"]+"\"" {
1536 yyextra->fileName = &yytext[6];
1537 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1538 yyextra->fileName = yyextra->fileName.mid(1,yyextra->fileName.length()-2);
1539 yyextra->docBlock+=yytext;
1540 }
1541 {CMD}"ifile"{B}+{FILEMASK} {
1542 yyextra->fileName = &yytext[6];
1543 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1544 yyextra->docBlock+=yytext;
1545 }
1546 {CMD}"iline"{LINENR}/[\n\.] |
1547 {CMD}"iline"{LINENR}{B} {
1548 bool ok = false;
1549 int nr = QCString(&yytext[6]).toInt(&ok);
1550 if (!ok)
1551 {
1552 warn(yyextra->fileName,yyextra->yyLineNr,"Invalid line number '%s' for iline command",yytext);
1553 }
1554 else
1555 {
1556 yyextra->yyLineNr = nr;
1557 }
1558 yyextra->docBlock+=yytext;
1559 }
1560 ({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command
1561 yyextra->docBlock+=yytext;
1562 }
1563 "\\ilinebr "{B}* {
1564 QCString indent;
1565 int extraSpaces = std::max(0,static_cast<int>(yyleng-9-yyextra->curIndent-2));
1566 indent.fill(' ',extraSpaces);
1567 //printf("extraSpaces=%d\n",extraSpaces);
1568 yyextra->docBlock += "\\ilinebr ";
1569 yyextra->docBlock += indent;
1570 }
void fill(char c, int len=-1)
Fills a string with a predefined character.
Definition qcstring.h:180
1571 [^#\\@\n]+ { // any other stuff
1572 yyextra->docBlock+=yytext;
1573 }
1574 \n { // new line that ends the comment
1575 handleCommentBlock(yyscanner, yyextra->docBlock, yyextra->docBrief);
1576 if (yyextra->docBlockContext == VariableEnd)
1577 {
1578 unput(*yytext);
1579 }
1580 else
1581 {
1582 incLineNr(yyscanner);
1583 }
1584 BEGIN(yyextra->docBlockContext);
1585 }
1586 . { // anything we missed
1587 yyextra->docBlock+=*yytext;
1588 }
1589}
1590
1591<SingleQuoteString>{
1592 \\{B}\n { // line continuation
1593 addToString(yyscanner,yytext);
1594 incLineNr(yyscanner);
1595 }
1596 \\. { // escaped char
1597 addToString(yyscanner,yytext);
1598 }
1599 "\"\"\"" { // triple double quotes
1600 addToString(yyscanner,yytext);
1601 }
1602 "'" { // end of the string
1603 addToString(yyscanner,yytext);
1604 BEGIN(yyextra->stringContext);
1605 }
1606 [^"'\n\\]+ { // normal chars
1607 addToString(yyscanner,yytext);
1608 }
1609 . { // normal char
1610 addToString(yyscanner,yytext);
1611 }
1612}
1613
1614<DoubleQuoteString>{
1615 \\{B}\n { // line continuation
1616 addToString(yyscanner,yytext);
1617 incLineNr(yyscanner);
1618 }
1619 \\. { // escaped char
1620 addToString(yyscanner,yytext);
1621 }
1622 "'''" { // triple single quotes
1623 addToString(yyscanner,yytext);
1624 }
1625 "\"" { // end of the string
1626 addToString(yyscanner,yytext);
1627 BEGIN(yyextra->stringContext);
1628 }
1629 [^"'\n\\]+ { // normal chars
1630 addToString(yyscanner,yytext);
1631 }
1632 . { // normal char
1633 addToString(yyscanner,yytext);
1634 }
1635}
1636
1637<TripleString>{
1638 {ENDTRIDOUBLEQUOTE} |
1639 {ENDTRISINGLEQUOTE} {
1640 *yyextra->copyString << yytext;
1641 if (yyextra->doubleQuote==(yytext[0]=='"'))
1642 {
1643 BEGIN(yyextra->stringContext);
1644 }
1645 }
1646
1647
1648 ({LONGSTRINGBLOCK}) {
1649 lineCount(yyscanner);
1650 *yyextra->copyString << yytext;
1651 }
1652 \n {
1653 incLineNr(yyscanner);
1654 *yyextra->copyString << yytext;
1655 }
1656 . {
1657 *yyextra->copyString << *yytext;
1658 }
1659}
1660
1661<Decorator>{
1662 {TRIDOUBLEQUOTE} { // start of a comment block
1663 yyextra->doubleQuote=TRUE;
1664 yyextra->decoratorCommentStr.str(std::string());
1665 yyextra->copyString=&yyextra->decoratorCommentStr;
1666 yyextra->stringContext=YY_START;
1667 BEGIN(TripleString);
1668 }
1669
1670 {TRISINGLEQUOTE} { // start of a comment block
1671 yyextra->doubleQuote=FALSE;
1672 yyextra->decoratorCommentStr.str(std::string());
1673 yyextra->copyString=&yyextra->decoratorCommentStr;
1674 yyextra->stringContext=YY_START;
1675 BEGIN(TripleString);
1676 }
1677 "'" {
1678 yyextra->stringContext=YY_START;
1679 yyextra->decoratorCommentStr.str(std::string());
1680 yyextra->copyString=&yyextra->decoratorCommentStr;
1681 BEGIN( SingleQuoteString );
1682 }
1683 "\"" {
1684 yyextra->stringContext=YY_START;
1685 yyextra->decoratorCommentStr.str(std::string());
1686 yyextra->copyString=&yyextra->decoratorCommentStr;
1687 BEGIN( DoubleQuoteString );
1688 }
1689 "(" {
1690 yyextra->decoratorRound++;
1691 }
1692 ")" {
1693 yyextra->decoratorRound--;
1694 if (!yyextra->decoratorRound) BEGIN( Search );
1695 }
1696 \n {
1697 incLineNr(yyscanner);
1698 }
1699 . { }
1700}
1701
1702 /* ------------ End rules -------------- */
1703
1704 /*
1705<*>({NONEMPTY}|{EXPCHAR}|{BB}) { // This should go one character at a time.
1706 // printf("[pyscanner] '%s' [ state %d ] [line %d] no match\n",
1707 // yytext, YY_START, yyextra->yyLineNr);
1708
1709 }
1710 */
1711
1712<*>{NEWLINE} {
1713 //printf("[pyscanner] %d NEWLINE [line %d] no match\n",
1714 // YY_START, yyextra->yyLineNr);
1715
1716 lineCount(yyscanner);
1717 }
1718
1719<*>"'" {
1720 //fprintf(stderr,"Quote: %d\n",YY_START);
1721 }
1722
1723<*>. {
1724 //printf("[pyscanner] '%s' [ state %d ] [line %d] no match\n",
1725 // yytext, YY_START, yyextra->yyLineNr);
1726
1727 }
1728
1729
1730%%
1731
1732//----------------------------------------------------------------------------
1733
1734static int yyread(yyscan_t yyscanner,char *buf,int max_size)
1735{
1736 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1737 int c=0;
1738 const char *p = yyextra->inputString + yyextra->inputPosition;
1739 while ( c < max_size && *p ) { *buf++ = *p++; c++; }
1740 yyextra->inputPosition+=c;
1741 return c;
1742}
1743
1744static void initParser(yyscan_t yyscanner)
1745{
1746 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1747 yyextra->protection = Protection::Public;
1748 yyextra->mtype = MethodTypes::Method;
1749 yyextra->isStatic = FALSE;
1750 yyextra->virt = Specifier::Normal;
1751 yyextra->previous = 0;
1752 yyextra->packageCommentAllowed = TRUE;
1753}
1754
1755static void initEntry(yyscan_t yyscanner)
1756{
1757 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1758 //yyextra->current->python = TRUE;
1759 yyextra->current->protection = yyextra->protection ;
1760 yyextra->current->mtype = yyextra->mtype;
1761 yyextra->current->virt = yyextra->virt;
1762 yyextra->current->isStatic = yyextra->isStatic;
1763 yyextra->current->lang = SrcLangExt::Python;
1764 yyextra->current->type.clear();
1765 yyextra->current->name.clear();
1766 yyextra->commentScanner.initGroupInfo(yyextra->current.get());
1767 yyextra->isStatic = FALSE;
1768}
1769
1770static void newEntry(yyscan_t yyscanner)
1771{
1772 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1773 bool found = false;
1774 if (yyextra->checkDupEntry)
1775 {
1776 for (auto &v : yyextra->current_root->children())
1777 {
1778 //printf("candidate %s<->%s section=%s!\n",qPrint(v->name),qPrint(yyextra->current->name), v->section.to_string().c_str());
1779 if (v->name==yyextra->current->name && v->section==yyextra->current->section) // name is already added, don't add it again
1780 {
1781 if (v->doc.isEmpty() && !yyextra->current->doc.isEmpty())
1782 {
1783 v->doc = yyextra->current->doc;
1784 v->docLine = yyextra->current->docLine;
1785 v->docFile = yyextra->current->docFile;
1786 }
1787 if (v->brief.isEmpty() && !yyextra->current->brief.isEmpty())
1788 {
1789 v->brief = yyextra->current->brief;
1790 v->briefLine = yyextra->current->briefLine;
1791 v->briefFile = yyextra->current->briefFile;
1792 }
1793 if (v->type.isEmpty() && !yyextra->current->type.isEmpty())
1794 {
1795 //printf("copying type '%s' from '%s' to '%s'\n",qPrint(yyextra->current->type),qPrint(yyextra->current->name),qPrint(v->name));
1796 v->type = yyextra->current->type;
1797 }
1798 found=true;
1799 break;
1800 }
1801 }
1802 }
1803 if (!found)
1804 {
1805 yyextra->previous = yyextra->current;
1806 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
1807 }
1808 initEntry(yyscanner);
1809}
1810
1811static void addEntry(yyscan_t yyscanner)
1812{
1813 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1814
1815 auto doc = yyextra->current->doc;
1816 auto docLine = yyextra->current->docLine;
1817 auto docFile = yyextra->current->docFile;
1818 auto brief = yyextra->current->brief;
1819 auto briefLine = yyextra->current->briefLine;
1820 auto briefFile = yyextra->current->briefFile;
1821
1822 yyextra->previous = yyextra->current;
1823 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
1824 initEntry(yyscanner);
1825
1826 yyextra->current->doc = doc;
1827 yyextra->current->docLine = docLine;
1828 yyextra->current->docFile = docFile;
1829 yyextra->current->brief = brief;
1830 yyextra->current->briefLine = briefLine;
1831 yyextra->current->briefFile = briefFile;
1832}
1833
1834static void setProtection(yyscan_t yyscanner)
1835{
1836 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1837 if (!yyextra->current->name.isEmpty() && yyextra->current->name.at(0)=='_')
1838 {
1839 if (yyextra->current->name.at(1)=='_') // mark as private
1840 {
1841 yyextra->current->protection=Protection::Private;
1842 }
1843 else // mark as protected
1844 {
1845 yyextra->current->protection=Protection::Protected;
1846 }
1847 }
1848}
1849
1850static void docVariable(yyscan_t yyscanner,const char *name)
1851{
1852 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1853 yyextra->current->name = name;
1854 yyextra->current->section=EntryType::makeVariable();
1855 yyextra->current->fileName = yyextra->fileName;
1856 yyextra->current->startLine = yyextra->yyLineNr;
1857 yyextra->current->bodyLine = yyextra->yyLineNr;
1858 yyextra->current->type.clear();
1859 setProtection(yyscanner);
1860 yyextra->checkDupEntry = true;
1861}
1862
1863static void newVariable(yyscan_t yyscanner)
1864{
1865 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1866 setProtection(yyscanner);
1867 if (yyextra->current_root->section.isCompound()) // mark as class variable
1868 {
1869 yyextra->current->isStatic = TRUE;
1870 }
1871 newEntry(yyscanner);
1872}
1873
1874static void addVariable(yyscan_t yyscanner)
1875{
1876 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1877 setProtection(yyscanner);
1878 if (yyextra->current_root->section.isCompound()) // mark as class variable
1879 {
1880 yyextra->current->isStatic = TRUE;
1881 }
1882 addEntry(yyscanner);
1883}
1884
1885static void newFunction(yyscan_t yyscanner)
1886{
1887 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1888 if (yyextra->current->name.startsWith("__") && yyextra->current->name.endsWith("__"))
1889 {
1890 // special method name, see
1891 // http://docs.python.org/ref/specialnames.html
1892 yyextra->current->protection=Protection::Public;
1893 }
1894 else
1895 {
1896 setProtection(yyscanner);
1897 }
1898}
1899
1900static inline int computeIndent(const char *s)
1901{
1902 int col=0;
1903 int tabSize=Config_getInt(TAB_SIZE);
1904 const char *p=s;
1905 char c;
1906 while ((c=*p++))
1907 {
1908 if (c==' ') col++;
1909 else if (c=='\t') col+=tabSize-(col%tabSize);
1910 else break;
1911 }
1912 return col;
1913}
1914
1916{
1917 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1918 auto it = yyextra->packageNameCache.find(path.str());
1919 if (it!=yyextra->packageNameCache.end())
1920 {
1921 return QCString(it->second);
1922 }
1923 FileInfo pf(path.str()+"/__init__.py"); // found package initialization file
1924 if (pf.exists())
1925 {
1926 int i=path.findRev('/');
1927 if (i!=-1)
1928 {
1929 QCString scope = findPackageScopeFromPath(yyscanner,path.left(i));
1930 if (!scope.isEmpty())
1931 {
1932 scope+="::";
1933 }
1934 scope+=path.mid(i+1);
1935 yyextra->packageNameCache.emplace(path.str(),scope.str());
1936 return scope;
1937 }
1938 }
1939 return "";
1940}
1941
1942static QCString findPackageScope(yyscan_t yyscanner,const QCString &fileName)
1943{
1944 if (fileName.isEmpty()) return fileName;
1945 FileInfo fi(fileName.str());
1946 return findPackageScopeFromPath(yyscanner,fi.dirPath(true).c_str());
1947}
1948
1949static void addFrom(yyscan_t yyscanner,bool all)
1950{
1951 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1952 QCString item=all ? yyextra->packageName : yyextra->packageName+"."+yytext;
1953 yyextra->current->name=removeRedundantWhiteSpace(substitute(item,".","::"));
1954 yyextra->current->fileName = yyextra->fileName;
1955 //printf("Adding using declaration: found:%s:%d name=%s\n",qPrint(yyextra->fileName),yyextra->yyLineNr,qPrint(yyextra->current->name));
1956 yyextra->current->section=all ? EntryType::makeUsingDir() : EntryType::makeUsingDecl();
1957 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
1958 initEntry(yyscanner);
1959}
1960//-----------------------------------------------------------------------------
1961
1962static void lineCount(yyscan_t yyscanner)
1963{
1964 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1965 DBG_CTX((stderr,"yyextra->yyLineNr=%d\n",yyextra->yyLineNr));
1966 for (const char *p = yytext; *p; ++p)
1967 {
1968 yyextra->yyLineNr += (*p == '\n') ;
1969 }
1970}
1971
1972static void incLineNr(yyscan_t yyscanner)
1973{
1974 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1975 DBG_CTX((stderr,"yyextra->yyLineNr=%d\n",yyextra->yyLineNr));
1976 yyextra->yyLineNr++;
1977}
1978
1979//-----------------------------------------------------------------
1980static void startCommentBlock(yyscan_t yyscanner,bool brief)
1981{
1982 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1983 if (brief)
1984 {
1985 yyextra->current->briefFile = yyextra->fileName;
1986 yyextra->current->briefLine = yyextra->yyLineNr;
1987 }
1988 else
1989 {
1990 yyextra->current->docFile = yyextra->fileName;
1991 yyextra->current->docLine = yyextra->yyLineNr;
1992 }
1993}
1994
1995static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief)
1996{
1997 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1998 //printf("handleCommentBlock(doc=[%s] brief=%d yyextra->docBlockInBody=%d yyextra->docBlockJavaStyle=%d\n",
1999 // qPrint(doc),brief,yyextra->docBlockInBody,yyextra->docBlockJavaStyle);
2000
2001 // TODO: Fix me
2002 yyextra->docBlockInBody=FALSE;
2003
2004 if (!yyextra->current->doc.isEmpty())
2005 {
2006 yyextra->current->doc=yyextra->current->doc.stripWhiteSpace()+"\n\n";
2007 }
2008 if (yyextra->docBlockInBody && yyextra->previous && !yyextra->previous->doc.isEmpty())
2009 {
2010 yyextra->previous->doc=yyextra->previous->doc.stripWhiteSpace()+"\n\n";
2011 }
2012
2013 int position = 0;
2014 bool needsEntry = false;
2015 int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine;
2016 Markdown markdown(yyextra->fileName,lineNr);
2017 GuardedSectionStack guards;
2018 QCString strippedDoc = stripIndentation(doc);
2019 QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(strippedDoc,lineNr) : strippedDoc;
2020 while (yyextra->commentScanner.parseCommentBlock(
2021 yyextra->thisParser,
2022 (yyextra->docBlockInBody && yyextra->previous) ? yyextra->previous.get() : yyextra->current.get(),
2023 processedDoc, // text
2024 yyextra->fileName, // file
2025 lineNr,
2026 yyextra->docBlockInBody ? FALSE : brief,
2027 yyextra->docBlockJavaStyle, // javadoc style // or FALSE,
2028 yyextra->docBlockInBody,
2029 yyextra->protection,
2030 position,
2031 needsEntry,
2032 Config_getBool(MARKDOWN_SUPPORT),
2033 &guards
2034 )
2035 ) // need to start a new entry
2036 {
2037 if (needsEntry)
2038 {
2039 newEntry(yyscanner);
2040 }
2041 }
2042 if (needsEntry)
2043 {
2044 newEntry(yyscanner);
2045 }
2046
2047}
2048
2049static void endOfDef(yyscan_t yyscanner,int correction)
2050{
2051 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2052 //printf("endOfDef at=%d\n",yyextra->yyLineNr);
2053 if (yyextra->bodyEntry)
2054 {
2055 yyextra->bodyEntry->endBodyLine = yyextra->yyLineNr-correction;
2056 yyextra->bodyEntry = 0;
2057 }
2058 newEntry(yyscanner);
2059 //yyextra->insideConstructor = FALSE;
2060}
2061
2062static inline void addToString(yyscan_t yyscanner,const char *s)
2063{
2064 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2065 if (yyextra->copyString) (*yyextra->copyString) << s;
2066}
2067
2068static void initTriDoubleQuoteBlock(yyscan_t yyscanner)
2069{
2070 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2071 yyextra->docBlockContext = YY_START;
2072 yyextra->docBlockInBody = FALSE;
2073 yyextra->docBlockJavaStyle = TRUE;
2074 yyextra->docBlockSpecial = yytext[strlen(yytext) - 1]=='!' || !Config_getBool(PYTHON_DOCSTRING);
2075 yyextra->docBlock.clear();
2076 yyextra->commentIndent = yyextra->curIndent;
2077 yyextra->doubleQuote = TRUE;
2078 if (yyextra->docBlockSpecial)
2079 {
2080 yyextra->docBlock.fill(' ',yyextra->indent);
2081 }
2082 startCommentBlock(yyscanner,FALSE);
2083}
2084
2085static void initTriSingleQuoteBlock(yyscan_t yyscanner)
2086{
2087 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2088 yyextra->docBlockContext = YY_START;
2089 yyextra->docBlockInBody = FALSE;
2090 yyextra->docBlockJavaStyle = TRUE;
2091 yyextra->docBlockSpecial = yytext[strlen(yytext) - 1]=='!' || !Config_getBool(PYTHON_DOCSTRING);
2092 yyextra->docBlock.clear();
2093 yyextra->commentIndent = yyextra->curIndent;
2094 yyextra->doubleQuote = FALSE;
2095 if (yyextra->docBlockSpecial)
2096 {
2097 yyextra->docBlock.fill(' ',yyextra->indent);
2098 }
2099 startCommentBlock(yyscanner,FALSE);
2100}
2101
2102static void initSpecialBlock(yyscan_t yyscanner)
2103{
2104 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2105 yyextra->docBlockContext = YY_START;
2106 yyextra->docBlockInBody = FALSE;
2107 yyextra->docBlockJavaStyle = TRUE;
2108 yyextra->docBrief = TRUE;
2109 yyextra->docBlock.clear();
2110 yyextra->commentIndent = yyextra->curIndent;
2111 startCommentBlock(yyscanner,FALSE);
2112}
2113
2114static void searchFoundDef(yyscan_t yyscanner)
2115{
2116 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2117 yyextra->current->fileName = yyextra->fileName;
2118 yyextra->current->startLine = yyextra->yyLineNr;
2119 yyextra->current->bodyLine = yyextra->yyLineNr;
2120 yyextra->current->section = EntryType::makeFunction();
2121 yyextra->current->lang = SrcLangExt::Python;
2122 yyextra->current->virt = Specifier::Normal;
2123 yyextra->current->isStatic = yyextra->isStatic;
2124 yyextra->current->mtype = yyextra->mtype = MethodTypes::Method;
2125 yyextra->current->type.clear();
2126 yyextra->current->name.clear();
2127 yyextra->current->args.clear();
2128 yyextra->current->argList.clear();
2129 yyextra->packageCommentAllowed = FALSE;
2130 yyextra->isStatic=FALSE;
2131 //printf("searchFoundDef at=%d\n",yyextra->yyLineNr);
2132}
2133
2134static void searchFoundClass(yyscan_t yyscanner)
2135{
2136 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2137 yyextra->current->section = EntryType::makeClass();
2138 yyextra->current->argList.clear();
2139 yyextra->current->type += "class" ;
2140 yyextra->current->fileName = yyextra->fileName;
2141 yyextra->current->startLine = yyextra->yyLineNr;
2142 yyextra->current->bodyLine = yyextra->yyLineNr;
2143 yyextra->packageCommentAllowed = FALSE;
2144}
2145
2146//----------------------------------------------------------------------------
2147
2148static void parseCompounds(yyscan_t yyscanner,std::shared_ptr<Entry> rt)
2149{
2150 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2151 //printf("parseCompounds(%s)\n",qPrint(rt->name));
2152 for (size_t i=0; i<rt->children().size(); ++i)
2153 {
2154 std::shared_ptr<Entry> ce = rt->children()[i];
2155 if (!ce->program.empty())
2156 {
2157 //fprintf(stderr,"parseCompounds: -- %s (line %d) ---------\n%s\n---------------\n",
2158 // qPrint(ce->name), ce->bodyLine, qPrint(ce->program));
2159 // init scanner state
2160 yyextra->programStr = ce->program.str();
2161 yyextra->inputString = yyextra->programStr.data();
2162 yyextra->inputPosition = 0;
2163 pyscannerYYrestart( nullptr, yyscanner );
2164 if (ce->section.isCompound())
2165 {
2166 yyextra->specialBlock = false;
2167 yyextra->current_root = ce;
2168 BEGIN( Search );
2169 }
2170 else if (ce->parent())
2171 {
2172 yyextra->current_root = rt;
2173 //printf("Searching for member variables in %s parent=%s\n",
2174 // qPrint(ce->name),qPrint(ce->parent->name));
2175 BEGIN( SearchMemVars );
2176 }
2177 yyextra->fileName = ce->fileName;
2178 yyextra->yyLineNr = ce->bodyLine ;
2179 yyextra->current = std::make_shared<Entry>();
2180 initEntry(yyscanner);
2181
2182 yyextra->checkDupEntry = false;
2183
2184 QCString name = ce->name;
2185 yyextra->commentScanner.enterCompound(yyextra->fileName,yyextra->yyLineNr,name);
2186
2187 pyscannerYYlex(yyscanner) ;
2188 yyextra->lexInit=TRUE;
2189
2190 yyextra->programStr.clear();
2191 ce->program.str(std::string());
2192
2193 yyextra->commentScanner.leaveCompound(yyextra->fileName,yyextra->yyLineNr,name);
2194
2195 }
2196 parseCompounds(yyscanner,ce);
2197 }
2198}
2199
2200//----------------------------------------------------------------------------
2201
2202
2203static void parseMain(yyscan_t yyscanner, const QCString &fileName,const char *fileBuf,const std::shared_ptr<Entry> &rt)
2204{
2205 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2206 initParser(yyscanner);
2207
2208 if (fileBuf==nullptr || fileBuf[0]=='\0') return;
2209
2210 yyextra->inputString = fileBuf;
2211 yyextra->inputPosition = 0;
2212
2213 yyextra->protection = Protection::Public;
2214 yyextra->mtype = MethodTypes::Method;
2215 yyextra->isStatic = false;
2216 yyextra->virt = Specifier::Normal;
2217 yyextra->current_root = rt;
2218 yyextra->specialBlock = false;
2219
2220 yyextra->yyLineNr= 1 ;
2221 yyextra->fileName = fileName;
2222 yyextra->checkDupEntry = false;
2223 //setContext();
2224 msg("Parsing file %s...\n",qPrint(yyextra->fileName));
2225
2226 FileInfo fi(fileName.str());
2227 yyextra->moduleScope = findPackageScope(yyscanner,fileName);
2228 QCString baseName=fi.baseName();
2229 if (baseName!="__init__") // package initializer file is not a package itself
2230 {
2231 if (!yyextra->moduleScope.isEmpty())
2232 {
2233 yyextra->moduleScope+="::";
2234 }
2235 yyextra->moduleScope+=baseName;
2236 }
2237
2238 // add namespaces for each scope
2239 QCString scope = yyextra->moduleScope;
2240 int startPos = 0;
2241 int pos = 0;
2242 do
2243 {
2244 pos = scope.find("::",startPos);
2245 startPos=pos+2;
2246 if (pos==-1) pos=(int)scope.length();
2247 yyextra->current = std::make_shared<Entry>();
2248 initEntry(yyscanner);
2249 yyextra->current->name = scope.left(pos);
2250 yyextra->current->section = EntryType::makeNamespace();
2251 yyextra->current->type = "namespace";
2252 yyextra->current->fileName = yyextra->fileName;
2253 yyextra->current->startLine = yyextra->yyLineNr;
2254 yyextra->current->bodyLine = yyextra->yyLineNr;
2255 yyextra->current_root = yyextra->current;
2256 rt->moveToSubEntryAndRefresh(yyextra->current);
2257 } while (pos<(int)scope.length());
2258
2259 initParser(yyscanner);
2260
2261 yyextra->commentScanner.enterFile(yyextra->fileName,yyextra->yyLineNr);
2262
2263 yyextra->current->reset();
2264 initEntry(yyscanner);
2265 pyscannerYYrestart(nullptr,yyscanner);
2266 BEGIN( Search );
2267 pyscannerYYlex(yyscanner);
2268 yyextra->lexInit=TRUE;
2269
2270 yyextra->commentScanner.leaveFile(yyextra->fileName,yyextra->yyLineNr);
2271
2272 yyextra->programStr.clear();
2273 yyextra->current_root->program.str(std::string());
2274
2275 parseCompounds(yyscanner, yyextra->current_root);
2276}
2277
2278//----------------------------------------------------------------------------
2279
2280static void parsePrototype(yyscan_t yyscanner,const QCString &text)
2281{
2282 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2283 //printf("**** parsePrototype(%s) begin\n",qPrint(text));
2284 if (text.isEmpty())
2285 {
2286 warn(yyextra->fileName,yyextra->yyLineNr,"Empty prototype found!");
2287 return;
2288 }
2289
2290 yyextra->specialBlock = FALSE;
2291 yyextra->packageCommentAllowed = FALSE;
2292
2293 // save scanner state
2294 YY_BUFFER_STATE orgState = YY_CURRENT_BUFFER;
2295 yy_switch_to_buffer(yy_create_buffer(nullptr, YY_BUF_SIZE, yyscanner), yyscanner);
2296 const char *orgInputString = yyextra->inputString;
2297 int orgInputPosition = yyextra->inputPosition;
2298
2299 // set new string
2300 yyextra->inputString = text.data();
2301 yyextra->inputPosition = 0;
2302 pyscannerYYrestart( nullptr, yyscanner );
2303
2304 BEGIN( FunctionDec );
2305
2306 pyscannerYYlex(yyscanner);
2307 yyextra->lexInit=TRUE;
2308
2309 yyextra->current->name = yyextra->current->name.stripWhiteSpace();
2310 if (yyextra->current->section.isMemberDoc() && yyextra->current->args.isEmpty())
2311 {
2312 yyextra->current->section = EntryType::makeVariableDoc();
2313 }
2314
2315 // restore original scanner state
2316
2317 yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner);
2318 yy_switch_to_buffer(orgState, yyscanner);
2319
2320 yyextra->inputString = orgInputString;
2321 yyextra->inputPosition = orgInputPosition;
2322
2323 //printf("**** parsePrototype end\n");
2324}
2325
2326//----------------------------------------------------------------------------
2327
2333
2335{
2336 pyscannerYYlex_init_extra(&p->state,&p->yyscanner);
2337#ifdef FLEX_DEBUG
2338 pyscannerYYset_debug(Debug::isFlagSet(Debug::Lex_pyscanner)?1:0,p->yyscanner);
2339#endif
2340}
2341
2343{
2344 pyscannerYYlex_destroy(p->yyscanner);
2345}
2346
2347
2349 const char *fileBuf,
2350 const std::shared_ptr<Entry> &root,
2351 ClangTUParser * /*clangParser*/)
2352{
2353 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
2354 yyextra->thisParser = this;
2355 DebugLex debugLex(Debug::Lex_pyscanner, __FILE__, qPrint(fileName));
2356 ::parseMain(p->yyscanner, fileName,fileBuf,root);
2357
2358 // May print the AST for debugging purposes
2359 // printAST(global_root);
2360}
2361
2363{
2364 return FALSE;
2365}
2366
2368{
2369 ::parsePrototype(p->yyscanner,text);
2370}
2371
2372//----------------------------------------------------------------------------
2373
2374#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:65
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:135
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:2362
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:2348
std::unique_ptr< Private > p
Definition pyscanner.h:48
~PythonOutlineParser() override
Definition pyscanner.l:2342
void parsePrototype(const QCString &text) override
Callback function called by the comment block scanner.
Definition pyscanner.l:2367
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:153
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:226
const std::string & str() const
Definition qcstring.h:537
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:91
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:159
QCString left(size_t len) const
Definition qcstring.h:214
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
Definition code.l:3980
#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)
void msg(const char *fmt,...)
Definition message.cpp:98
static void parsePrototype(yyscan_t yyscanner, const QCString &text)
Definition pyscanner.l:2280
static void parseCompounds(yyscan_t yyscanner, std::shared_ptr< Entry > rt)
Definition pyscanner.l:2148
pyscannerYY_state state
Definition pyscanner.l:2331
@ Private
Definition types.h:26
@ Protected
Definition types.h:26
@ Python
Definition types.h:52
bool found
Definition util.cpp:984
QCString stripIndentation(const QCString &s)
Definition util.cpp:6282