Doxygen
Loading...
Searching...
No Matches
xmlcode.l
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2020 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/******************************************************************************
16 * Parser for syntax highlighting and references for XML
17 * written by Weston Thayer
18 ******************************************************************************/
19
20%option never-interactive
21%option prefix="xmlcodeYY"
22%option reentrant
23%option extra-type="struct xmlcodeYY_state *"
24%option noyy_top_state
25%option nounput
26%option noyywrap
27%top{
28#include <stdint.h>
29// forward declare yyscan_t to improve type safety
30#define YY_TYPEDEF_YY_SCANNER_T
31struct yyguts_t;
32typedef yyguts_t *yyscan_t;
yyguts_t * yyscan_t
Definition code.l:24
33}
34
35%{
36
37#include <stdio.h>
38
39#include "xmlcode.h"
40
41#include "entry.h"
42#include "doxygen.h"
43#include "outputlist.h"
44#include "util.h"
45#include "membername.h"
46#include "searchindex.h"
47#include "config.h"
48#include "filedef.h"
49#include "tooltip.h"
50#include "message.h"
51#include "debug.h"
52
53#define YY_NEVER_INTERACTIVE 1
54#define YY_NO_INPUT 1
55#define YY_NO_UNISTD_H 1
56
58{
59 OutputCodeList * code;
60 QCString curClassName;
61 QCString parmType;
62 QCString parmName;
63 const char * inputString = nullptr; //!< the code fragment as text
64 int inputPosition = 0; //!< read offset during parsing
65 QCString fileName;
66 int inputLines = 0; //!< number of line in the code fragment
67 int yyLineNr = 0; //!< current line number
68 bool insideCodeLine = false;
69 const Definition *searchCtx = nullptr;
70
71 bool stripCodeComments = true;
72 bool exampleBlock = false;
73 QCString exampleName;
74 QCString exampleFile;
75
76 QCString type;
77 QCString name;
78 QCString args;
79 QCString classScope;
80
81 QCString CurrScope;
82
83 std::unique_ptr<FileDef> exampleFileDef;
84 const FileDef * sourceFileDef = nullptr;
85 const Definition * currentDefinition = nullptr;
86 const MemberDef * currentMemberDef = nullptr;
87 bool includeCodeFragment = false;
88 const char * currentFontClass = nullptr;
89};
90
91[[maybe_unused]] static const char *stateToString(int state);
92
93static void codify(yyscan_t yyscanner,const char* text);
94static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor);
95static void startCodeLine(yyscan_t yyscanner);
96static void endFontClass(yyscan_t yyscanner);
97static void endCodeLine(yyscan_t yyscanner);
98static void nextCodeLine(yyscan_t yyscanner);
99static void codifyLines(yyscan_t yyscanner,const char *text);
100static void startFontClass(yyscan_t yyscanner,const char *s);
101static int countLines(yyscan_t yyscanner);
102static int yyread(yyscan_t yyscanner,char *buf,int max_size);
103
104#undef YY_INPUT
105#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
106
107// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
108static inline const char *getLexerFILE() {return __FILE__;}
109#include "doxygen_lex.h"
110
This is an alternative implementation of QCString.
Definition qcstring.h:101
Web server based search engine.
QCString exampleName
Definition xmlcode.l:73
QCString fileName
Definition xmlcode.l:65
QCString args
Definition xmlcode.l:78
const char * currentFontClass
Definition xmlcode.l:88
OutputCodeList * code
Definition xmlcode.l:59
QCString name
Definition xmlcode.l:77
QCString CurrScope
Definition xmlcode.l:81
const Definition * currentDefinition
Definition xmlcode.l:85
const FileDef * sourceFileDef
Definition xmlcode.l:84
const MemberDef * currentMemberDef
Definition xmlcode.l:86
int yyLineNr
current line number
Definition xmlcode.l:67
int inputPosition
read offset during parsing
Definition xmlcode.l:64
std::unique_ptr< FileDef > exampleFileDef
Definition xmlcode.l:83
QCString parmType
Definition xmlcode.l:61
QCString exampleFile
Definition xmlcode.l:74
const char * inputString
the code fragment as text
Definition xmlcode.l:63
QCString classScope
Definition xmlcode.l:79
QCString parmName
Definition xmlcode.l:62
int inputLines
number of line in the code fragment
Definition xmlcode.l:66
QCString type
Definition xmlcode.l:76
bool includeCodeFragment
Definition xmlcode.l:87
bool stripCodeComments
Definition xmlcode.l:71
QCString curClassName
Definition xmlcode.l:60
const Definition * searchCtx
Definition xmlcode.l:69
bool exampleBlock
Definition xmlcode.l:72
bool insideCodeLine
Definition xmlcode.l:68
A bunch of utility functions.
static void endCodeLine(yyscan_t yyscanner)
Definition xmlcode.l:310
static void nextCodeLine(yyscan_t yyscanner)
Definition xmlcode.l:318
static void startCodeLine(yyscan_t yyscanner)
Definition xmlcode.l:252
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
Definition xmlcode.l:211
static int countLines(yyscan_t yyscanner)
Definition xmlcode.l:368
static const char * stateToString(int state)
static void startFontClass(yyscan_t yyscanner, const char *s)
Definition xmlcode.l:359
static void codifyLines(yyscan_t yyscanner, const char *text)
Definition xmlcode.l:333
static const char * getLexerFILE()
Definition xmlcode.l:108
static void setCurrentDoc(yyscan_t yyscanner, const QCString &anchor)
Definition xmlcode.l:232
static void codify(yyscan_t yyscanner, const char *text)
Definition xmlcode.l:226
static void endFontClass(yyscan_t yyscanner)
Definition xmlcode.l:300
111%}
112
113nl (\r\n|\r|\n)
114ws [ \t]+
115open "<"
116close ">"
117namestart [A-Za-z\200-\377_]
118namechar [:A-Za-z\200-\377_0-9.-]
119esc "&#"[0-9]+";"|"&#x"[0-9a-fA-F]+";"
120name {namestart}{namechar}*
121comment {open}"!--"([^-]|"-"[^-])*"--"{close}
122cdata {open}"![CDATA["([^\]]|"\]"[^\]])*"]]"{close}
123string \"([^\"&]|{esc})*\"|\'([^'&]|{esc})*\'
124
125%option noyywrap
126%option nounput
127
129
130<INITIAL>{ws} {
131 codifyLines(yyscanner,yytext);
132 }
static void codifyLines(yyscan_t yyscanner, const QCString &text)
Definition code.l:2508
133<INITIAL>"/" {
134 endFontClass(yyscanner);
135 codify(yyscanner,yytext);
136 }
static void endFontClass(yyscan_t yyscanner, bool specialComment=false)
Definition code.l:3483
static void codify(yyscan_t yyscanner, const QCString &text)
Definition pycode.l:1016
137<INITIAL>"=" {
138 endFontClass(yyscanner);
139 codify(yyscanner,yytext);
140 }
141<INITIAL>{close} {
142 endFontClass(yyscanner);
143 codify(yyscanner,yytext);
144 }
145<INITIAL>{name} {
146 startFontClass(yyscanner,"keyword");
147 codify(yyscanner,yytext);
148 endFontClass(yyscanner);
149 }
static void startFontClass(yyscan_t yyscanner, const char *s, bool specialComment=false)
Definition code.l:3498
150<INITIAL>{string} {
151 startFontClass(yyscanner,"stringliteral");
152 codifyLines(yyscanner,yytext);
153 endFontClass(yyscanner);
154 }
155{cdata} {
156 startFontClass(yyscanner,"xmlcdata");
157 codifyLines(yyscanner,yytext);
158 endFontClass(yyscanner);
159 }
160
161{open}{ws}?{name} {
162 // Write the < in a different color
163 char openBracket[] = { yytext[0], '\0' };
164 codify(yyscanner,openBracket);
165
166 // Then write the rest
167 yytext++;
168 startFontClass(yyscanner,"keywordtype");
169 codify(yyscanner,yytext);
170 endFontClass(yyscanner);
171
172 BEGIN(INITIAL);
173 }
174{open}{ws}?"/"{name} {
175 // Write the "</" in a different color
176 char closeBracket[] = { yytext[0], yytext[1], '\0' };
177 endFontClass(yyscanner);
178 codify(yyscanner,closeBracket);
179
180 // Then write the rest
181 yytext++; // skip the '<'
182 yytext++; // skip the '/'
183 startFontClass(yyscanner,"keywordtype");
184 codify(yyscanner,yytext);
185 endFontClass(yyscanner);
186
187 BEGIN(INITIAL);
188 }
189{comment} {
190 // Strip off the extra '!'
191 // yytext++; // <
192 // *yytext = '<'; // replace '!' with '<'
193
194 startFontClass(yyscanner,"comment");
195 codifyLines(yyscanner,yytext);
196 endFontClass(yyscanner);
197 }
198{nl} {
199 codifyLines(yyscanner,yytext);
200 }
201
202. {
203 //printf("!ERROR(%c)\n", *yytext);
204 codifyLines(yyscanner,yytext);
205 }
206
207%%
208
209//----------------------------------------------------------------------------------------
210
211static int yyread(yyscan_t yyscanner,char *buf,int max_size)
212{
213 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
214 int inputPosition = yyextra->inputPosition;
215 const char *s = yyextra->inputString + inputPosition;
216 int c=0;
217 while( c < max_size && *s)
218 {
219 *buf++ = *s++;
220 c++;
221 }
222 yyextra->inputPosition += c;
223 return c;
224}
225
226static void codify(yyscan_t yyscanner,const char* text)
227{
228 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
229 yyextra->code->codify(text);
230}
231
232static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor)
233{
234 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
235 if (Doxygen::searchIndex.enabled())
236 {
237 if (yyextra->searchCtx)
238 {
239 Doxygen::searchIndex.setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false);
240 }
241 else
242 {
243 Doxygen::searchIndex.setCurrentDoc(yyextra->sourceFileDef,anchor,true);
244 }
245 }
246}
247
248/*! start a new line of code, inserting a line number if yyextra->sourceFileDef
249 * is true. If a definition starts at the current line, then the line
250 * number is linked to the documentation of that definition.
251 */
252static void startCodeLine(yyscan_t yyscanner)
253{
254 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
255 if (yyextra->sourceFileDef)
256 {
257 const Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr);
258
259 if (!yyextra->includeCodeFragment && d && d->isLinkableInProject())
260 {
261 yyextra->currentDefinition = d;
262 yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr);
263 //yyextra->insideBody = false;
264 yyextra->classScope = d->name();
265 QCString lineAnchor;
266 lineAnchor.sprintf("l%05d",yyextra->yyLineNr);
267 if (yyextra->currentMemberDef)
268 {
269 yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
270 yyextra->currentMemberDef->getOutputFileBase(),
271 yyextra->currentMemberDef->anchor(),yyextra->yyLineNr,
272 !yyextra->includeCodeFragment);
273 setCurrentDoc(yyscanner,lineAnchor);
274 }
275 else
276 {
277 yyextra->code->writeLineNumber(d->getReference(),
279 QCString(),yyextra->yyLineNr,
280 !yyextra->includeCodeFragment);
281 setCurrentDoc(yyscanner,lineAnchor);
282 }
283 }
284 else
285 {
286 yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr,
287 !yyextra->includeCodeFragment);
288 }
289 }
290
291 yyextra->code->startCodeLine(yyextra->yyLineNr);
292 yyextra->insideCodeLine = true;
293
294 if (yyextra->currentFontClass)
295 {
296 yyextra->code->startFontClass(yyextra->currentFontClass);
297 }
298}
299
300static void endFontClass(yyscan_t yyscanner)
301{
302 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
303 if (yyextra->currentFontClass)
304 {
305 yyextra->code->endFontClass();
306 yyextra->currentFontClass=0;
307 }
308}
309
310static void endCodeLine(yyscan_t yyscanner)
311{
312 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
313 endFontClass(yyscanner);
314 yyextra->code->endCodeLine();
315 yyextra->insideCodeLine = false;
316}
317
318static void nextCodeLine(yyscan_t yyscanner)
319{
320 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
321 const char *fc = yyextra->currentFontClass;
322 if (yyextra->insideCodeLine)
323 {
324 endCodeLine(yyscanner);
325 }
326 if (yyextra->yyLineNr<yyextra->inputLines)
327 {
328 yyextra->currentFontClass = fc;
329 startCodeLine(yyscanner);
330 }
331}
332
333static void codifyLines(yyscan_t yyscanner,const char *text)
334{
335 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
336 const char *p=text,*sp=p;
337 char c;
338 bool done=false;
339 while (!done)
340 {
341 sp=p;
342 while ((c=*p++) && c!='\n') { }
343 if (c=='\n')
344 {
345 yyextra->yyLineNr++;
346 size_t l = static_cast<size_t>(p-sp-1);
347 std::string tmp(sp,l);
348 yyextra->code->codify(tmp.c_str());
349 nextCodeLine(yyscanner);
350 }
351 else
352 {
353 yyextra->code->codify(sp);
354 done=true;
355 }
356 }
357}
358
359static void startFontClass(yyscan_t yyscanner,const char *s)
360{
361 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
362 endFontClass(yyscanner);
363 yyextra->code->startFontClass(s);
364 yyextra->currentFontClass=s;
365}
366
367/*! counts the number of lines in the input */
368static int countLines(yyscan_t yyscanner)
369{
370 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
371 const char *p=yyextra->inputString;
372 char c;
373 int count=1;
374 while ((c=*p))
375 {
376 p++ ;
377 if (c=='\n') count++;
378 }
379 if (p>yyextra->inputString && *(p-1)!='\n')
380 { // last line does not end with a \n, so we add an extra
381 // line and explicitly terminate the line after parsing.
382 count++;
383 }
384 return count;
385}
386
387//----------------------------------------------------------------------------------------
388
390{
392 xmlcodeYY_state state;
393};
394
395XMLCodeParser::XMLCodeParser() : p(std::make_unique<Private>())
396{
397 xmlcodeYYlex_init_extra(&p->state,&p->yyscanner);
398#ifdef FLEX_DEBUG
399 xmlcodeYYset_debug(Debug::isFlagSet(Debug::Lex_xmlcode)?1:0,p->yyscanner);
400#endif
402}
403
405{
406 xmlcodeYYlex_destroy(p->yyscanner);
407}
408
410{
411 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
412 yyextra->currentDefinition = nullptr;
413 yyextra->currentMemberDef = nullptr;
414}
415
417 const QCString &/* scopeName */,
418 const QCString &input,
420 bool stripCodeComments,
421 bool isExampleBlock,
422 const QCString &exampleName,
423 const FileDef *fileDef,
424 int startLine,
425 int endLine,
426 bool inlineFragment,
427 const MemberDef * /* memberDef */,
428 bool /* showLineNumbers */,
429 const Definition *searchCtx,
430 bool/* collectXRefs */
431 )
432{
433 yyscan_t yyscanner = p->yyscanner;
434 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
435
436 if (input.isEmpty()) return;
437
438 DebugLex debugLex(Debug::Lex_xmlcode, __FILE__, fileDef ? qPrint(fileDef->fileName()): nullptr);
439 yyextra->fileName = fileDef ? fileDef->fileName():"";
440
441 yyextra->code = &codeOutIntf;
442 yyextra->inputString = input.data();
443 yyextra->inputPosition = 0;
444 yyextra->currentFontClass = nullptr;
445 yyextra->insideCodeLine = false;
446 yyextra->searchCtx = searchCtx;
447
448 if (startLine!=-1)
449 yyextra->yyLineNr = startLine;
450 else
451 yyextra->yyLineNr = 1;
452
453 if (endLine!=-1)
454 yyextra->inputLines = endLine+1;
455 else
456 yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1;
457
458 yyextra->stripCodeComments = stripCodeComments;
459 yyextra->exampleBlock = isExampleBlock;
460 yyextra->exampleName = exampleName;
461 yyextra->sourceFileDef = fileDef;
462
463 if (isExampleBlock && fileDef==0)
464 {
465 // create a dummy filedef for the example
466 yyextra->exampleFileDef = createFileDef("",(!exampleName.isEmpty()?exampleName:QCString("generated")));
467 yyextra->sourceFileDef = yyextra->exampleFileDef.get();
468 }
469
470 if (yyextra->sourceFileDef)
471 {
472 setCurrentDoc(yyscanner,"l00001");
473 }
474
475 yyextra->includeCodeFragment = inlineFragment;
476 // Starts line 1 on the output
477 startCodeLine(yyscanner);
478
479 xmlcodeYYrestart( nullptr, yyscanner );
480
481 xmlcodeYYlex(yyscanner);
482
483 if (yyextra->insideCodeLine)
484 {
485 endCodeLine(yyscanner);
486 }
487 if (yyextra->exampleFileDef)
488 {
489 // delete the temporary file definition used for this example
490 yyextra->exampleFileDef.reset();
491 yyextra->sourceFileDef=nullptr;
492 }
493}
494
495
496#include "xmlcode.l.h"
@ Lex_xmlcode
Definition debug.h:70
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:135
The common base class of all entity definitions found in the sources.
Definition definition.h:76
virtual bool isLinkableInProject() const =0
virtual QCString getReference() const =0
virtual QCString getOutputFileBase() const =0
virtual const QCString & name() const =0
static SearchIndexIntf searchIndex
Definition doxygen.h:124
A model of a file symbol.
Definition filedef.h:99
virtual QCString fileName() const =0
A model of a class/file/namespace member symbol.
Definition memberdef.h:48
Class representing a list of different code generators.
Definition outputlist.h:164
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
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
std::unique_ptr< Private > p
Definition xmlcode.h:57
void parseCode(OutputCodeList &codeOutIntf, const QCString &scopeName, const QCString &input, SrcLangExt, bool stripCodeComments, bool isExampleBlock, const QCString &exampleName=QCString(), const FileDef *fileDef=nullptr, int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, const MemberDef *memberDef=nullptr, bool showLineNumbers=TRUE, const Definition *searchCtx=nullptr, bool collectXRefs=TRUE) override
Parses a source file or fragment with the goal to produce highlighted and cross-referenced output.
Definition xmlcode.l:416
~XMLCodeParser() override
Definition xmlcode.l:404
void resetCodeParserState() override
Resets the state of the code parser.
Definition xmlcode.l:409
static void endCodeLine(yyscan_t yyscanner)
Definition code.l:2481
static void nextCodeLine(yyscan_t yyscanner)
Definition code.l:2490
static void startCodeLine(yyscan_t yyscanner)
Definition code.l:2412
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
Definition code.l:3974
static int countLines(yyscan_t yyscanner)
Definition code.l:3465
static void setCurrentDoc(yyscan_t yyscanner, const QCString &anchor)
Definition code.l:2274
std::unique_ptr< FileDef > createFileDef(const QCString &p, const QCString &n, const QCString &ref, const QCString &dn)
Definition filedef.cpp:265
const char * qPrint(const char *s)
Definition qcstring.h:661
xmlcodeYY_state state
Definition xmlcode.l:392
SrcLangExt
Language as given by extension.
Definition types.h:42