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