Doxygen
lexscanner.l
浏览该文件的文档.
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 %option never-interactive
16 %option prefix="lexscannerYY"
17 %option reentrant
18 %option extra-type="struct lexscannerYY_state *"
19 %option noyywrap
20 
21 %top{
22 #include <stdint.h>
23 // forward declare yyscan_t to improve type safety
24 #define YY_TYPEDEF_YY_SCANNER_T
25 struct yyguts_t;
26 typedef yyguts_t *yyscan_t;
27 }
28 
29 %{
30 
31 /*
32  * includes
33  */
34 
35 #include <algorithm>
36 #include <vector>
37 #include <utility>
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <assert.h>
42 #include <ctype.h>
43 
44 #include "config.h"
45 #include "lexscanner.h"
46 #include "entry.h"
47 #include "message.h"
48 #include "util.h"
49 #include "scanner.h"
50 
51 #define YY_NO_INPUT 1
52 #define YY_NO_UNISTD_H 1
53 
54 #define USE_STATE2STRING 0
55 
56 #define repeatChar(chr, cnt) std::string(cnt, chr).c_str()
57 
58 struct lexscannerYY_state
59 {
60  COutlineParser cOutlineParser;
61  const char * inputString = 0;
62  int inputPosition = 0;
63 
64  int lastContext = 0;
65  int lastCContext = 0;
66  int lastStringContext = 0;
67  int docBlockContext = 0;
68  int lastPreLineCtrlContext = 0;
69  int lastRawStringContext = 0;
70  int curlyCount = 0;
71 
72  bool insideCode = FALSE;
73  QCString delimiter;
74  QCString docBlockName;
75  uint fencedSize = 0;
76  bool nestedComment = false;
77 
78  QCString prefix = "yy";
79  bool reentrant = false;
80  bool bison_bridge = false;
81  bool bison_locations = false;
82  QCString cCodeBuffer;
83  int roundCount = 0;
84 
85  QCString yyFileName;
86  ClangTUParser *clangParser = 0;
87 
88  std::shared_ptr<Entry> current;
89  std::shared_ptr<Entry> current_root;
90  SrcLangExt language;
91 };
92 
93 #if USE_STATE2STRING
94 static const char *stateToString(int state);
95 #endif
96 //-----------------------------------------------------------------------------
97 
98 // forward declarations for statefull functions
99 static void handleCCode(yyscan_t yyscanner);
100 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
101 
102 /* ----------------------------------------------------------------- */
103 #undef YY_INPUT
104 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
105 
106 %}
107 
108 nl (\r\n|\r|\n)
109 ws [ \t]
110 nws [^ \t\n]
111 TopStart "%top{"{nl}
112 TopEnd "}"{nl}
113 LiteralStart "%{"{nl}
114 LiteralEnd "%}"{nl}
115 Option "%option"
116 RulesStart "%%"{nl}
117 RulesEnd "%%"{nl}
118 RulesSharp "<"[^>\n]*">"
119 RulesCurly "{"[^{}\n]*"}"
120 StartSquare "["
121 StartDouble "\""
122 StartRound "("
123 StartRoundQuest "(?"
124 EscapeRulesCharOpen "\\["|"\<"|"\\{"|"\\("|"\\\""|"\\ "|"\\\\"
125 EscapeRulesCharClose "\\]"|"\>"|"\\}"|"\\)"
126 EscapeRulesChar {EscapeRulesCharOpen}|{EscapeRulesCharClose}
127 
128 CMD ("\\"|"@")
129 BN [ \t\n\r]
130 BL [ \t\r]*"\n"
131 B [ \t]
132 Bopt {B}*
133 ID [$a-z_A-Z\x80-\xFF][$a-z_A-Z0-9\x80-\xFF]*
134 PRE [pP][rR][eE]
135 CODE [cC][oO][dD][eE]
136 RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"("
137 RAWEND ")"[^ \t\(\)\\]{0,16}\"
138 CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'"))
139 CHARCE "[:"[^:]*":]"
140  /* no comment start / end signs inside square brackets */
141 NCOMM [^/\*]
142  // C start comment
143 CCS "/\*"
144  // C end comment
145 CCE "*\/"
146  // Cpp comment
147 CPPC "/\/"
148  // doxygen start comment
149 DCOMM ("/\*!"|"/\**"|"/\/!"|"/\/\/")
150 
151  // Optional any character
152 ANYopt .*
153  // Optional all but newline
154 NONLopt [^\n]*
155 
156 %x DefSection
157 %x Option
158 %x OptPrefix
159 %x DefSectionLine
160 %x RulesSectionInit
161 %x RulesPattern
162 %x RulesDouble
163 %x RulesRoundDouble
164 %x RulesSquare
165 %x RulesRoundSquare
166 %x RulesRound
167 %x RulesRoundQuest
168 %x UserSection
169 
170 %x TopSection
171 %x LiteralSection
172 
173 %x COMMENT
174 
175 %x SkipCurly
176 %x SkipCurlyEndDoc
177 %x PreLineCtrl
178 %x DocLine
179 %x DocBlock
180 %x DocCopyBlock
181 %x SkipString
182 %x RawString
183 %x SkipComment
184 %x SkipCxxComment
185 %x Comment
186 
187 %%
188 
189 <*>\x0d
190 <DefSection>{Option} {
191  BEGIN (Option);
192  }
193 <Option>"prefix"{ws}*"="{ws}* {
194  BEGIN (OptPrefix);
195  }
196 <OptPrefix>"\""[^\"]*"\"" {
197  yyextra->prefix = yytext;
198  yyextra->prefix = yyextra->prefix.mid(1,yyleng-2);
199  BEGIN (Option);
200  }
201 <Option>"reentrant" {
202  yyextra-> reentrant = true;
203  }
204 <Option>"bison-bridge" {
205  yyextra-> bison_bridge = true;
206  }
207 <Option>"bison-locations" {
208  yyextra-> bison_bridge = true;
209  yyextra-> bison_locations = true;
210  }
211 <Option>{nws}+
212 <Option>{ws}+
213 <Option>{nl} {
214  yyextra->cCodeBuffer += yytext;
215  BEGIN (DefSection);
216  }
217 <DefSection>^{RulesStart} {
218  {
219  bool fill = false;
220  yyextra->cCodeBuffer += "int " + yyextra->prefix + "lex (";
221  if (yyextra->bison_bridge )
222  {
223  if (fill) yyextra->cCodeBuffer += ",";
224  yyextra->cCodeBuffer += "YYSTYPE * yylval_param";
225  fill = true;
226  }
227  if (yyextra->bison_locations)
228  {
229  if (fill) yyextra->cCodeBuffer += ",";
230  yyextra->cCodeBuffer += "YYLTYPE * yylloc_param";
231  fill = true;
232  }
233  if (yyextra->reentrant)
234  {
235  if (fill) yyextra->cCodeBuffer += ",";
236  yyextra->cCodeBuffer += "yyscan_t yyscanner";
237  fill = true;
238  }
239  if (!yyextra->bison_bridge && !yyextra->bison_locations && !yyextra->reentrant)
240  {
241  yyextra->cCodeBuffer += "void";
242  }
243  yyextra->cCodeBuffer += ") {\n";
244  }
245  BEGIN (RulesSectionInit);
246  }
247 <DefSection>^{TopStart} {
248  yyextra->cCodeBuffer += "\n";
249  yyextra->lastContext = YY_START;
250  BEGIN (TopSection);
251  }
252 <DefSection>^{LiteralStart} {
253  yyextra->cCodeBuffer += "\n";
254  yyextra->lastContext = YY_START;
255  BEGIN (LiteralSection);
256  }
257 <TopSection>^{TopEnd} {
258  yyextra->cCodeBuffer += "\n";
259  BEGIN( yyextra->lastContext ) ;
260  }
261 <TopSection>.*{nl} {
262  yyextra->cCodeBuffer += yytext;
263  }
264 <LiteralSection>^{LiteralEnd} {
265  yyextra->cCodeBuffer += "\n";
266  BEGIN( yyextra->lastContext ) ;
267  }
268 <LiteralSection>.*{nl} {
269  yyextra->cCodeBuffer += yytext;
270  }
271 <DefSection>^{nws} {
272  BEGIN(DefSectionLine);
273  }
274 <DefSection>{CPPC}.*{nl} {
275  yyextra->cCodeBuffer += yytext;
276  }
277 <DefSection>^{ws}*{CCS} {
278  yyextra->cCodeBuffer += yytext;
279  yyextra->lastContext = YY_START;
280  BEGIN(COMMENT);
281  }
282 <COMMENT>{CCE}{ws}*{nl} {
283  yyextra->cCodeBuffer+=yytext;
284  BEGIN(yyextra->lastContext);
285  }
286 <COMMENT>{CCE} {
287  yyextra->cCodeBuffer+=yytext;
288  BEGIN(yyextra->lastContext);
289  }
290 <COMMENT>[^*\n]+ {
291  yyextra->cCodeBuffer += yytext;
292  }
293 <COMMENT>{CPPC}|{CCS} {
294  yyextra->cCodeBuffer += yytext;
295  }
296 <COMMENT>{nl} {
297  yyextra->cCodeBuffer += yytext;
298  }
299 <COMMENT>. {
300  yyextra->cCodeBuffer += yytext;
301  }
302 <DefSection>^{nl} {
303  yyextra->cCodeBuffer += "\n";
304  }
305 <DefSection>^{ws}.*{nl} {
306  yyextra->cCodeBuffer += yytext;
307  }
308 <DefSectionLine>.*{nl} {
309  yyextra->cCodeBuffer += "\n";
310  BEGIN(DefSection);
311  }
312 <RulesSectionInit,RulesPattern>^{RulesEnd} {
313  yyextra->cCodeBuffer += "}\n";
314  BEGIN (UserSection);
315  }
316 <RulesSectionInit>^{nws} {
317  unput(*yytext);
318  BEGIN(RulesPattern);
319  }
320 <RulesSectionInit>^{ws}.*{nl} {
321  yyextra->cCodeBuffer += yytext;
322  }
323 <RulesSectionInit>^{nl} {
324  yyextra->cCodeBuffer += yytext;
325  }
326 <RulesPattern>"<<EOF>>" {
327  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
328  }
329 <RulesPattern>{EscapeRulesChar} {
330  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
331  }
332 <RulesPattern>{RulesSharp} {
333  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
334  }
335 <RulesPattern>{RulesCurly} {
336  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
337  }
338 <RulesPattern>{StartDouble} {
339  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
340  yyextra->lastContext = YY_START;
341  BEGIN(RulesDouble);
342  }
343 <RulesDouble,RulesRoundDouble>"\\\\" {
344  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
345  }
346 <RulesDouble,RulesRoundDouble>"\\\"" {
347  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
348  }
349 <RulesDouble>"\"" {
350  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
351  BEGIN( yyextra->lastContext ) ;
352  }
353 <RulesRoundDouble>"\"" {
354  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
355  BEGIN(RulesRound) ;
356  }
357 <RulesDouble,RulesRoundDouble>. {
358  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
359  }
360 <RulesPattern>{StartSquare} {
361  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
362  yyextra->lastContext = YY_START;
363  BEGIN(RulesSquare);
364  }
365 <RulesSquare,RulesRoundSquare>{CHARCE} {
366  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
367  }
368 <RulesSquare,RulesRoundSquare>"\\[" |
369 <RulesSquare,RulesRoundSquare>"\\]" {
370  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
371  }
372 <RulesSquare>"]" {
373  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
374  BEGIN(RulesPattern);
375  }
376 <RulesRoundSquare>"]" {
377  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
378  BEGIN(RulesRound) ;
379  }
380 <RulesSquare,RulesRoundSquare>"\\\\" {
381  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
382  }
383 <RulesSquare,RulesRoundSquare>. {
384  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
385  }
386 <RulesPattern>{StartRoundQuest} {
387  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
388  yyextra->lastContext = YY_START;
389  BEGIN(RulesRoundQuest);
390  }
391 <RulesRoundQuest>{nl} {
392  yyextra->cCodeBuffer += "\n";
393  }
394 <RulesRoundQuest>[^)] {
395  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
396  }
397 <RulesRoundQuest>")" {
398  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
399  BEGIN(yyextra->lastContext);
400  }
401 <RulesPattern>{StartRound} {
402  yyextra->roundCount++;
403  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
404  yyextra->lastContext = YY_START;
405  BEGIN(RulesRound);
406  }
407 <RulesRound>{RulesCurly} {
408  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
409  }
410 <RulesRound>{StartSquare} {
411  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
412  BEGIN(RulesRoundSquare);
413  }
414 <RulesRound>{StartDouble} {
415  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
416  BEGIN(RulesRoundDouble);
417  }
418 <RulesRound>{EscapeRulesChar} {
419  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
420  }
421 <RulesRound>"(" {
422  yyextra->roundCount++;
423  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
424  }
425 <RulesRound>")" {
426  yyextra->roundCount--;
427  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
428  if (!yyextra->roundCount) BEGIN( yyextra->lastContext ) ;
429  }
430 <RulesRound>{nl} {
431  yyextra->cCodeBuffer += "\n";
432  }
433 <RulesRound>{ws} {
434  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
435  }
436 <RulesRound>. {
437  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
438  }
439 <RulesPattern>{ws}+"|" {
440  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
441  yyextra->curlyCount = 0;
442  BEGIN(SkipCurly);
443  }
444 <RulesPattern>^{ws}*{nl} {
445  yyextra->cCodeBuffer += "\n";
446  }
447 <RulesPattern>^{ws}+ {
448  }
449 
450 <RulesPattern>({ws}|{nl}) {
451  unput(*yytext);
452  yyextra->curlyCount = 0;
453  BEGIN(SkipCurly);
454  }
455 <RulesPattern>"\\\\" {
456  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
457  }
458 <RulesPattern>{CCS} {
459  yyextra->cCodeBuffer += yytext;
460  yyextra->lastContext = YY_START;
461  BEGIN(COMMENT);
462  }
463 <RulesPattern>. {
464  yyextra->cCodeBuffer += repeatChar(' ', yyleng);
465  }
466 <SkipCurly>{B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */
467  yyextra->cCodeBuffer += yytext;
468  yyextra->lastPreLineCtrlContext = YY_START;
469  BEGIN( PreLineCtrl );
470  }
471 <PreLineCtrl>"\""[^\n\"]*"\"" {
472  yyextra->cCodeBuffer += yytext;
473  }
474 <PreLineCtrl>. {
475  yyextra->cCodeBuffer += yytext;
476  }
477 <PreLineCtrl>\n {
478  yyextra->cCodeBuffer += yytext;
479  BEGIN( yyextra->lastPreLineCtrlContext );
480  }
481 <SkipCurly>"{" {
482  yyextra->cCodeBuffer += yytext;
483  ++yyextra->curlyCount ;
484  }
485 <SkipCurly>"}"/{BN}*{DCOMM}"<!--" | /* see bug710917 */
486 <SkipCurly>"}" {
487  yyextra->cCodeBuffer += yytext;
488  if( yyextra->curlyCount )
489  {
490  --yyextra->curlyCount ;
491  }
492  }
493 <SkipCurly>"}"{BN}*{DCOMM}"<" {
494  yyextra->cCodeBuffer += yytext;
495  if ( yyextra->curlyCount )
496  {
497  --yyextra->curlyCount ;
498  }
499  else
500  {
501  yyextra->docBlockContext = SkipCurlyEndDoc;
502  if (yytext[yyleng-3]=='/')
503  {
504  BEGIN( DocLine );
505  }
506  else
507  {
508  BEGIN( DocBlock );
509  }
510  }
511  }
512 <SkipCurly>\" {
513  yyextra->cCodeBuffer += yytext;
514  yyextra->lastStringContext=SkipCurly;
515  BEGIN( SkipString );
516  }
517 <SkipCurly>^{B}*"#" {
518  yyextra->cCodeBuffer += yytext;
519  yyextra->lastPreLineCtrlContext = YY_START;
520  BEGIN( PreLineCtrl );
521  }
522 <SkipCurly>{B}*{RAWBEGIN} {
523  QCString raw=QCString(yytext).stripWhiteSpace();
524  yyextra->delimiter = raw.mid(2);
525  yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1);
526  yyextra->lastRawStringContext = YY_START;
527  yyextra->cCodeBuffer += yytext;
528  BEGIN(RawString);
529  }
530 <SkipCurly>[^\n#"'@\\/{}<]+ {
531  yyextra->cCodeBuffer += yytext;
532  }
533 <SkipCurly>{CCS} {
534  yyextra->cCodeBuffer += yytext;
535  yyextra->lastCContext = YY_START;
536  BEGIN(SkipComment);
537  }
538 <SkipCurly>{CPPC} {
539  yyextra->cCodeBuffer += yytext;
540  yyextra->lastCContext = YY_START;
541  BEGIN(SkipCxxComment);
542  }
543 <SkipCurly>{CHARLIT} {
544  yyextra->cCodeBuffer += yytext;
545  }
546 <SkipCurly>\' {
547  yyextra->cCodeBuffer += yytext;
548  }
549 <SkipCurly>. {
550  yyextra->cCodeBuffer += yytext;
551  }
552 <SkipCurly>({CPPC}{B}*)?{CCS}"!" {
553  yyextra->cCodeBuffer += yytext;
554  yyextra->docBlockContext = YY_START;
555  BEGIN( DocBlock );
556  }
557 <SkipCurly>{CCS}"*"[*]+{BL} {
558  bool javadocBanner = Config_getBool(JAVADOC_BANNER);
559  yyextra->cCodeBuffer += yytext;
560  if( javadocBanner )
561  {
562  yyextra->docBlockContext = YY_START;
563  BEGIN( DocBlock );
564  }
565  else
566  {
567  BEGIN( Comment ) ;
568  }
569  }
570 <SkipCurly>({CPPC}{B}*)?{CCS}"*"/{NCOMM} {
571  yyextra->cCodeBuffer += yytext;
572  yyextra->docBlockContext = YY_START;
573  BEGIN( DocBlock );
574  }
575 <SkipCurly>{CPPC}"!" {
576  yyextra->cCodeBuffer += yytext;
577  yyextra->docBlockContext = YY_START;
578  BEGIN( DocLine );
579  }
580 <SkipCurly>{CPPC}"/"/[^/] {
581  yyextra->cCodeBuffer += yytext;
582  yyextra->docBlockContext = YY_START;
583  BEGIN( DocLine );
584  }
585 
586 <SkipCurly>\n {
587  yyextra->cCodeBuffer += yytext;
588  if (yyextra->curlyCount<=0)
589  {
590  BEGIN(RulesPattern);
591  }
592  }
593 <SkipString>\\. {
594  yyextra->cCodeBuffer += yytext;
595  }
596 <SkipString>\" {
597  yyextra->cCodeBuffer += yytext;
598  BEGIN( yyextra->lastStringContext );
599  }
600 <SkipString>{CCS}|{CCE}|{CPPC} {
601  yyextra->cCodeBuffer += yytext;
602  }
603 <SkipString>\n {
604  yyextra->cCodeBuffer += yytext;
605  }
606 <SkipString>. {
607  yyextra->cCodeBuffer += yytext;
608  }
609 <SkipCxxComment>.*"\\\n" { // line continuation
610  yyextra->cCodeBuffer += yytext;
611  }
612 <SkipCxxComment>{ANYopt}/\n {
613  yyextra->cCodeBuffer += yytext;
614  BEGIN( yyextra->lastCContext ) ;
615  }
616 <Comment>{BN}+ {
617  yyextra->cCodeBuffer += yytext ;
618  }
619 <Comment>{CCS} { yyextra->cCodeBuffer += yytext ; }
620 <Comment>{CPPC} { yyextra->cCodeBuffer += yytext ; }
621 <Comment>{CMD}("code"|"verbatim") {
622  yyextra->insideCode=TRUE;
623  yyextra->cCodeBuffer += yytext ;
624  }
625 <Comment>{CMD}("endcode"|"endverbatim") {
626  yyextra->insideCode=FALSE;
627  yyextra->cCodeBuffer += yytext ;
628  }
629 <Comment>[^ \.\t\r\n\/\*]+ { yyextra->cCodeBuffer += yytext ; }
630 <Comment>{CCE} { yyextra->cCodeBuffer += yytext ;
631  if (!yyextra->insideCode) BEGIN( yyextra->lastContext ) ;
632  }
633 <Comment>. { yyextra->cCodeBuffer += *yytext ; }
634 
635 <SkipComment>{CPPC}|{CCS} {
636  yyextra->cCodeBuffer += yytext;
637  }
638 <SkipComment>[^\*\n]+ {
639  yyextra->cCodeBuffer += yytext;
640  }
641 <SkipComment>\n {
642  yyextra->cCodeBuffer += yytext;
643  }
644 <SkipComment>{B}*{CCE} {
645  yyextra->cCodeBuffer += yytext;
646  BEGIN( yyextra->lastCContext );
647  }
648 <SkipComment>"*" {
649  yyextra->cCodeBuffer += yytext;
650  }
651 <RawString>{RAWEND} {
652  yyextra->cCodeBuffer += yytext;
653  QCString delimiter = yytext+1;
654  delimiter=delimiter.left(delimiter.length()-1);
655  if (delimiter==yyextra->delimiter)
656  {
657  BEGIN(yyextra->lastRawStringContext);
658  }
659  }
660 <RawString>[^)\n]+ {
661  yyextra->cCodeBuffer += yytext;
662  }
663 <RawString>. {
664  yyextra->cCodeBuffer += yytext;
665  }
666 <RawString>\n {
667  yyextra->cCodeBuffer += yytext;
668  }
669 
670 
671  /* ---- Single line comments ------ */
672 <DocLine>[^\n]*"\n"[ \t]*{CPPC}[/!][<]? { // continuation of multiline C++-style comment
673  yyextra->cCodeBuffer += yytext;
674  }
675 <DocLine>{B}*{CPPC}"/"[/]+{Bopt}/"\n" { // ignore marker line (see bug700345)
676  yyextra->cCodeBuffer += yytext;
677  BEGIN( yyextra->docBlockContext );
678  }
679 <DocLine>{NONLopt}/"\n"{B}*{CPPC}[!/]{B}*{CMD}"}" { // next line is an end group marker, see bug 752712
680  yyextra->cCodeBuffer += yytext;
681  BEGIN( yyextra->docBlockContext );
682  }
683 <DocLine>{NONLopt}/"\n" { // whole line
684  yyextra->cCodeBuffer += yytext;
685  BEGIN( yyextra->docBlockContext );
686  }
687 
688  /* ---- Comments blocks ------ */
689 
690 <DocBlock>"*"*{CCE} { // end of comment block
691  yyextra->cCodeBuffer += yytext;
692  BEGIN(yyextra->docBlockContext);
693  }
694 <DocBlock>^{B}*"*"+/[^/] {
695  yyextra->cCodeBuffer += yytext;
696  }
697 <DocBlock>^{B}*({CPPC})?{B}*"*"+/[^/a-z_A-Z0-9*] { // start of a comment line
698  yyextra->cCodeBuffer += yytext;
699  }
700 <DocBlock>^{B}*({CPPC}){B}* { // strip embedded C++ comments if at the start of a line
701  yyextra->cCodeBuffer += yytext;
702  }
703 <DocBlock>{CPPC} { // slashes in the middle of a comment block
704  yyextra->cCodeBuffer += yytext;
705  }
706 <DocBlock>{CCS} { // start of a new comment in the
707  // middle of a comment block
708  yyextra->cCodeBuffer += yytext;
709  }
710 <DocBlock>({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command
711  yyextra->cCodeBuffer += yytext;
712  }
713 <DocBlock>{CMD}("f$"|"f["|"f{"|"f(") {
714  yyextra->cCodeBuffer += yytext;
715  yyextra->docBlockName=&yytext[1];
716  if (yyextra->docBlockName.at(1)=='[')
717  {
718  yyextra->docBlockName.at(1)=']';
719  }
720  if (yyextra->docBlockName.at(1)=='{')
721  {
722  yyextra->docBlockName.at(1)='}';
723  }
724  if (yyextra->docBlockName.at(1)=='(')
725  {
726  yyextra->docBlockName.at(1)=')';
727  }
728  yyextra->fencedSize=0;
729  yyextra->nestedComment=FALSE;
730  BEGIN(DocCopyBlock);
731  }
732 <DocBlock>{B}*"<"{PRE}">" {
733  yyextra->cCodeBuffer += yytext;
734  yyextra->docBlockName="<pre>";
735  yyextra->fencedSize=0;
736  yyextra->nestedComment=FALSE;
737  BEGIN(DocCopyBlock);
738  }
739 <DocBlock>{CMD}"startuml"/[^a-z_A-Z0-9\-] { // verbatim type command (which could contain nested comments!)
740  yyextra->cCodeBuffer += yytext;
741  yyextra->docBlockName="uml";
742  yyextra->fencedSize=0;
743  yyextra->nestedComment=FALSE;
744  BEGIN(DocCopyBlock);
745  }
746 <DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!)
747  yyextra->cCodeBuffer += yytext;
748  yyextra->docBlockName=&yytext[1];
749  yyextra->fencedSize=0;
750  yyextra->nestedComment=FALSE;
751  BEGIN(DocCopyBlock);
752  }
753 <DocBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* {
754  yyextra->cCodeBuffer += yytext;
755  QCString pat = substitute(yytext,"*"," ");
756  yyextra->docBlockName="~~~";
757  yyextra->fencedSize=pat.stripWhiteSpace().length();
758  yyextra->nestedComment=FALSE;
759  BEGIN(DocCopyBlock);
760  }
761 <DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* {
762  yyextra->cCodeBuffer += yytext;
763  QCString pat = substitute(yytext,"*"," ");
764  yyextra->docBlockName="```";
765  yyextra->fencedSize=pat.stripWhiteSpace().length();
766  yyextra->nestedComment=FALSE;
767  BEGIN(DocCopyBlock);
768  }
769 <DocBlock>{B}*"<code>" {
770  REJECT;
771  }
772 <DocBlock>[^@*~\/\\\n]+ { // any character that isn't special
773  yyextra->cCodeBuffer += yytext;
774  }
775 <DocBlock>\n { // newline
776  yyextra->cCodeBuffer += yytext;
777  }
778 <DocBlock>. { // command block
779  yyextra->cCodeBuffer += yytext;
780  }
781  /* ---- Copy verbatim sections ------ */
782 
783 <DocCopyBlock>"</"{PRE}">" { // end of a <pre> block
784  yyextra->cCodeBuffer += yytext;
785  if (yyextra->docBlockName=="<pre>")
786  {
787  BEGIN(DocBlock);
788  }
789  }
790 <DocCopyBlock>"</"{CODE}">" { // end of a <code> block
791  yyextra->cCodeBuffer += yytext;
792  if (yyextra->docBlockName=="<code>")
793  {
794  BEGIN(DocBlock);
795  }
796  }
797 <DocCopyBlock>[\\@]("f$"|"f]"|"f}"|"f)") {
798  yyextra->cCodeBuffer += yytext;
799  if (yyextra->docBlockName==&yytext[1])
800  {
801  BEGIN(DocBlock);
802  }
803  }
804 <DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block
805  yyextra->cCodeBuffer += yytext;
806  if (yyextra->docBlockName==&yytext[4])
807  {
808  BEGIN(DocBlock);
809  }
810  }
811 <DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line
812  yyextra->cCodeBuffer += yytext;
813  if (yyextra->docBlockName=="verbatim")
814  {
815  REJECT;
816  }
817  else if (yyextra->docBlockName=="code")
818  {
819  REJECT;
820  }
821  else
822  {
823  yyextra->cCodeBuffer += yytext;
824  }
825  }
826 <DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s
827  if (yyextra->docBlockName=="code")
828  {
829  yyextra->cCodeBuffer += yytext;
830  }
831  else
832  {
833  REJECT;
834  }
835  }
836 <DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516)
837  if (yyextra->docBlockName=="code")
838  {
839  yyextra->cCodeBuffer += yytext;
840  }
841  else
842  {
843  REJECT;
844  }
845  }
846 <DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one *
847  if (yyextra->docBlockName=="code")
848  {
849  if (yyextra->nestedComment) // keep * it is part of the code
850  {
851  yyextra->cCodeBuffer += yytext;
852  }
853  else // remove * it is part of the comment block
854  {
855  yyextra->cCodeBuffer += yytext;
856  }
857  }
858  else
859  {
860  REJECT;
861  }
862  }
863 <DocCopyBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* {
864  yyextra->cCodeBuffer += yytext;
865  QCString pat = substitute(yytext,"*"," ");
866  if (yyextra->fencedSize==pat.stripWhiteSpace().length())
867  {
868  BEGIN(DocBlock);
869  }
870  }
871 <DocCopyBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* {
872  yyextra->cCodeBuffer += yytext;
873  QCString pat = substitute(yytext,"*"," ");
874  if (yyextra->fencedSize==pat.stripWhiteSpace().length())
875  {
876  BEGIN(DocBlock);
877  }
878  }
879 <DocCopyBlock>[^<@/\*\]~\$\\\n]+ { // any character that is not special
880  yyextra->cCodeBuffer += yytext;
881  }
882 <DocCopyBlock>{CCS}|{CCE}|{CPPC} {
883  if (yytext[1]=='*')
884  {
885  yyextra->nestedComment=TRUE;
886  }
887  else if (yytext[0]=='*')
888  {
889  yyextra->nestedComment=FALSE;
890  }
891  yyextra->cCodeBuffer += yytext;
892  }
893 <DocCopyBlock>\n { // newline
894  yyextra->cCodeBuffer += yytext;
895  }
896 <DocCopyBlock>. { // any other character
897  yyextra->cCodeBuffer += yytext;
898  }
899 <SkipCurlyEndDoc>"}"{BN}*{DCOMM}"<" { // desc is followed by another one
900  yyextra->docBlockContext = SkipCurlyEndDoc;
901  yyextra->cCodeBuffer += yytext;
902  if (yytext[yyleng-3]=='/')
903  {
904  BEGIN( DocLine );
905  }
906  else
907  {
908  BEGIN( DocBlock );
909  }
910  }
911 <SkipCurlyEndDoc>"}" {
912  yyextra->cCodeBuffer += yytext;
913  BEGIN(SkipCurly);
914  }
915 
916 <UserSection>.*{nl} {
917  yyextra->cCodeBuffer += yytext;
918  }
919 
920 
921  /*
922 <*>. { fprintf(stderr,"Lex scanner Def rule for %s: #%s#\n",stateToString(YY_START),yytext);}
923 <*>{nl} { fprintf(stderr,"Lex scanner Def rule for newline %s: #%s#\n",stateToString(YY_START),yytext);}
924  */
925 <*><<EOF>> {
926  handleCCode(yyscanner);
927  yyterminate();
928  }
929 %%
930 
931 //----------------------------------------------------------------------------
932 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size)
933 {
934  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
935  yy_size_t c=0;
936  while( c < max_size && yyextra->inputString[yyextra->inputPosition] )
937  {
938  *buf = yyextra->inputString[yyextra->inputPosition++] ;
939  //printf("%d (%c)\n",*buf,*buf);
940  c++; buf++;
941  }
942  return c;
943 }
944 
945 //-----------------------------------------------------------------------------
946 
947 static void parseMain(yyscan_t yyscanner,
948  const QCString &fileName,
949  const char *fileBuf,
950  const std::shared_ptr<Entry> &rt,
951  ClangTUParser *clangParser)
952 {
953  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
954 
955  yyextra->inputString = fileBuf;
956  yyextra->inputPosition = 0;
957  lexscannerYYrestart(0,yyscanner);
958 
959  yyextra->current_root = rt;
960  yyextra->yyFileName = fileName;
961  yyextra->clangParser = clangParser;
962  yyextra->language = getLanguageFromFileName(yyextra->yyFileName);
963  rt->lang = yyextra->language;
964  msg("Parsing file %s...\n",qPrint(yyextra->yyFileName));
965 
966  yyextra->current_root = rt;
967  yyextra->current = std::make_shared<Entry>();
968  int sec=guessSection(yyextra->yyFileName);
969  if (sec)
970  {
971  yyextra->current->name = yyextra->yyFileName;
972  yyextra->current->section = sec;
973  yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
974  }
975  yyextra->current->reset();
976  BEGIN( DefSection );
977 
978  lexscannerYYlex(yyscanner);
979 
980  rt->program.str(std::string());
981 }
982 
983 //----------------------------------------------------------------------------
984 
985 
986 static void handleCCode(yyscan_t yyscanner)
987 {
988  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
989 
990  if (yyextra->cCodeBuffer.isEmpty()) return;
991  yyextra->cOutlineParser.parseInput(yyextra->yyFileName,
992  yyextra->cCodeBuffer.data(),
993  yyextra->current_root,
994  yyextra->clangParser);
995  yyextra->cCodeBuffer.resize(0);
996  return;
997 }
998 //----------------------------------------------------------------------------
999 
1000 struct LexOutlineParser::Private
1001 {
1002  yyscan_t yyscanner;
1003  lexscannerYY_state state;
1004 };
1005 
1006 LexOutlineParser::LexOutlineParser() : p(std::make_unique<LexOutlineParser::Private>())
1007 {
1008  lexscannerYYlex_init_extra(&p->state,&p->yyscanner);
1009 #ifdef FLEX_DEBUG
1010  lexscannerYYset_debug(1,p->yyscanner);
1011 #endif
1012 }
1013 
1014 LexOutlineParser::~LexOutlineParser()
1015 {
1016  lexscannerYYlex_destroy(p->yyscanner);
1017 }
1018 
1019 void LexOutlineParser::parseInput(const QCString &fileName,
1020  const char *fileBuf,
1021  const std::shared_ptr<Entry> &root,
1022  ClangTUParser *clangParser)
1023 {
1024  struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
1025 
1026  printlex(yy_flex_debug, TRUE, __FILE__, qPrint(fileName));
1027 
1028  ::parseMain(p->yyscanner,fileName,fileBuf,root,clangParser);
1029 
1030  printlex(yy_flex_debug, FALSE, __FILE__, qPrint(fileName));
1031 }
1032 
1033 
1034 //----------------------------------------------------------------------------
1035 
1036 #if USE_STATE2STRING
1037 #include "lexscanner.l.h"
1038 #endif