1 /******************************************************************************
3 * Copyright (C) 1997-2020 by Dimitri van Heesch.
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.
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
16 %option never-interactive
17 %option prefix="sqlcodeYY"
21 %option extra-type="struct sqlcodeYY_state *"
24 // forward declare yyscan_t to improve type safety
25 #define YY_TYPEDEF_YY_SCANNER_T
27 typedef yyguts_t *yyscan_t;
38 #include "outputlist.h"
40 #include "membername.h"
41 #include "searchindex.h"
47 #define YY_NEVER_INTERACTIVE 1
49 #define YY_NO_UNISTD_H 1
51 #define USE_STATE2STRING 0
53 struct sqlcodeYY_state
55 CodeOutputInterface * code;
56 const char *inputString; //!< the code fragment as text
57 yy_size_t inputPosition; //!< read offset during parsing
58 int inputLines; //!< number of line in the code fragment
59 int yyLineNr; //!< current line number
60 bool needsTermination;
61 const Definition *searchCtx;
67 const FileDef *sourceFileDef;
68 const Definition *currentDefinition;
69 const MemberDef *currentMemberDef;
70 bool includeCodeFragment;
71 const char *currentFontClass;
75 static const char *stateToString(int state);
78 static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor);
79 static void startCodeLine(yyscan_t yyscanner);
80 static void endFontClass(yyscan_t yyscanner);
81 static void endCodeLine(yyscan_t yyscanner);
82 static void nextCodeLine(yyscan_t yyscanner);
83 static void codifyLines(yyscan_t yyscanner,const char *text);
84 static void startFontClass(yyscan_t yyscanner,const char *s);
85 static int countLines(yyscan_t yyscanner);
86 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
89 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
95 idchar [A-Za-z0-9\-_]+
96 keywords1 ("ADD"|"ALL"|"ALLOCATE"|"ALTER"|"AND"|"ANY"|"ARE"|"AS"|"ASENSITIVE"|"ASYMMETRIC"|"AT"|"ATOMIC"|"AUTHORIZATION"|"BETWEEN"|"BOTH"|"BY"|"CALL"|"CALLED"|"CASCADED"|"CAST")
97 keywords2 ("CHECK"|"CLOSE"|"COLLATE"|"COLUMN"|"COMMIT"|"CONNECT"|"CONSTRAINT"|"CONTINUE"|"CORRESPONDING"|"CREATE"|"CROSS"|"CUBE"|"CURRENT"|"CURRENT_DATE"|"CURRENT_DEFAULT_TRANSFORM_GROUP")
98 keywords3 ("CURRENT_PATH"|"CURRENT_ROLE"|"CURRENT_TIME"|"CURRENT_TIMESTAMP"|"CURRENT_TRANSFORM_GROUP_FOR_TYPE"|"CURRENT_USER")
99 keywords4 ("CURSOR"|"CYCLE"|"DAY"|"DEALLOCATE"|"DECLARE"|"DEFAULT"|"DELETE"|"DEREF"|"DESCRIBE"|"DETERMINISTIC"|"DISCONNECT"|"DISTINCT"|"DROP"|"DYNAMIC")
100 keywords5 ("EACH"|"ELEMENT"|"END-EXEC"|"ESCAPE"|"EXCEPT"|"EXEC"|"EXECUTE"|"EXISTS"|"EXTERNAL"|"FETCH"|"FILTER"|"FOR"|"FOREIGN"|"FREE"|"FROM"|"FULL"|"FUNCTION")
101 keywords6 ("GET"|"GLOBAL"|"GRANT"|"GROUP"|"GROUPING"|"HAVING"|"HOLD"|"HOUR"|"IDENTITY"|"IMMEDIATE"|"IN"|"INDICATOR"|"INNER"|"INOUT"|"INPUT"|"INSENSITIVE"|"INSERT"|"INTERSECT")
102 keywords7 ("INTERVAL"|"INTO"|"IS"|"ISOLATION"|"JOIN"|"LANGUAGE"|"LARGE"|"LATERAL"|"LEADING"|"LEFT"|"LIKE"|"LOCAL"|"LOCALTIME"|"LOCALTIMESTAMP"|"MATCH"|"MEMBER"|"MERGE"|"METHOD"|"MINUTE")
103 keywords8 ("MODIFIES"|"MODULE"|"MONTH"|"MULTISET"|"NATIONAL"|"NATURAL"|"NEW"|"NO"|"NONE"|"NOT"|"OF"|"OLD"|"ON"|"ONLY"|"OPEN"|"OR"|"ORDER"|"OUT"|"OUTER"|"OUTPUT")
104 keywords9 ("OVER"|"OVERLAPS"|"PARAMETER"|"PARTITION"|"PRECISION"|"PREPARE"|"PRIMARY"|"PROCEDURE"|"RANGE"|"READS"|"RECURSIVE"|"REF"|"REFERENCES"|"REFERENCING"|"REGR_AVGX"|"REGR_AVGY")
105 keywords10 ("REGR_COUNT"|"REGR_INTERCEPT"|"REGR_R2"|"REGR_SLOPE"|"REGR_SXX"|"REGR_SXY"|"REGR_SYY"|"RELEASE"|"RESULT"|"RETURN"|"RETURNS"|"REVOKE"|"RIGHT"|"ROLLBACK"|"ROLLUP"|"ROW"|"ROWS"|"SAVEPOINT")
106 keywords11 ("SCROLL"|"SEARCH"|"SECOND"|"SELECT"|"SENSITIVE"|"SESSION_USER"|"SET"|"SIMILAR"|"SOME"|"SPECIFIC"|"SPECIFICTYPE"|"SQL"|"SQLEXCEPTION"|"SQLSTATE"|"SQLWARNING"|"START"|"STATIC")
107 keywords12 ("SUBMULTISET"|"SYMMETRIC"|"SYSTEM"|"SYSTEM_USER"|"TABLE"|"THEN"|"TIMEZONE_HOUR"|"TIMEZONE_MINUTE"|"TO"|"TRAILING"|"TRANSLATION"|"TREAT"|"TRIGGER"|"UESCAPE"|"UNION")
108 keywords13 ("UNIQUE"|"UNNEST"|"UPDATE"|"UPPER"|"USER"|"USING"|"VALUE"|"VALUES"|"VAR_POP"|"VAR_SAMP"|"VARYING"|"WHEN"|"WHENEVER"|"WHERE"|"WIDTH_BUCKET"|"WINDOW"|"WITH"|"WITHIN"|"WITHOUT"|"YEAR")
110 /* Need multiple keyword definitions due to max length */
111 keyword (?i:{keywords1}|{keywords2}|{keywords3}|{keywords4}|{keywords5}|{keywords6}|{keywords7}|{keywords8}|{keywords9}|{keywords10}|{keywords11}|{keywords12}|{keywords13})
113 typekeyword (?i:"ARRAY"|"BIGINT"|"BINARY"|"BLOB"|"BOOLEAN"|"CHAR"|"CHARACTER"|"CLOB"|"DATE"|"DEC"|"DECIMAL"|"DOUBLE"|"FLOAT"|"INT"|"INTEGER"|"NCHAR"|"NCLOB"|"NUMERIC"|"NVARCHAR"|"REAL"|"SMALLINT"|"TIME"|"TIMESTAMP"|"VARCHAR")
115 flowkeyword (?i:"CASE"|"IF"|"ELSE"|"BEGIN"|"END"|"WHILE")
117 literalkeyword (?i:"false"|"true"|"NULL"|"UNKNOWN")
118 stringliteral (\"[^"]*\")|('[^']*')
120 literals ({literalkeyword}|{stringliteral}|{number})
133 startFontClass(yyscanner,"stringliteral");
134 codifyLines(yyscanner,yytext);
135 endFontClass(yyscanner);
140 startFontClass(yyscanner,"keyword");
141 codifyLines(yyscanner,yytext);
142 endFontClass(yyscanner);
146 startFontClass(yyscanner,"keywordflow");
147 codifyLines(yyscanner,yytext);
148 endFontClass(yyscanner);
152 startFontClass(yyscanner,"keywordtype");
153 codifyLines(yyscanner,yytext);
154 endFontClass(yyscanner);
158 startFontClass(yyscanner,"preprocessor");
159 codifyLines(yyscanner,yytext);
160 endFontClass(yyscanner);
164 startFontClass(yyscanner,"comment");
165 codifyLines(yyscanner,yytext);
166 endFontClass(yyscanner);
170 startFontClass(yyscanner,"comment");
171 codifyLines(yyscanner,yytext);
176 codifyLines(yyscanner,yytext);
180 codifyLines(yyscanner,yytext);
183 <COMMENT>{commentclose} {
184 codifyLines(yyscanner,yytext);
185 endFontClass(yyscanner);
190 codifyLines(yyscanner,yytext);
194 codifyLines(yyscanner,yytext);
197 [\x80-\xFF]* { // keep utf8 characters together...
198 codifyLines(yyscanner,yytext);
201 codifyLines(yyscanner,yytext);
207 static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor)
209 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
210 if (Doxygen::searchIndex)
212 if (yyextra->searchCtx)
214 yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false);
218 yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,true);
223 /*! start a new line of code, inserting a line number if yyextra->sourceFileDef
224 * is true. If a definition starts at the current line, then the line
225 * number is linked to the documentation of that definition.
227 static void startCodeLine(yyscan_t yyscanner)
229 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
230 if (yyextra->sourceFileDef)
232 const Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr);
234 if (!yyextra->includeCodeFragment && d && d->isLinkableInProject())
236 yyextra->currentDefinition = d;
237 yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr);
238 yyextra->classScope = d->name();
240 lineAnchor.sprintf("l%05d",yyextra->yyLineNr);
241 if (yyextra->currentMemberDef)
243 yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
244 yyextra->currentMemberDef->getOutputFileBase(),
245 yyextra->currentMemberDef->anchor(),yyextra->yyLineNr,
246 !yyextra->includeCodeFragment);
247 setCurrentDoc(yyscanner,lineAnchor);
251 yyextra->code->writeLineNumber(d->getReference(),
252 d->getOutputFileBase(),
253 QCString(),yyextra->yyLineNr,
254 !yyextra->includeCodeFragment);
255 setCurrentDoc(yyscanner,lineAnchor);
260 yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr,
261 !yyextra->includeCodeFragment);
265 yyextra->code->startCodeLine(yyextra->sourceFileDef);
267 if (yyextra->currentFontClass)
269 yyextra->code->startFontClass(yyextra->currentFontClass);
273 static void endFontClass(yyscan_t yyscanner)
275 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
276 if (yyextra->currentFontClass)
278 yyextra->code->endFontClass();
279 yyextra->currentFontClass=0;
283 static void endCodeLine(yyscan_t yyscanner)
285 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
286 endFontClass(yyscanner);
287 yyextra->code->endCodeLine();
290 static void nextCodeLine(yyscan_t yyscanner)
292 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
293 const char *fc = yyextra->currentFontClass;
294 endCodeLine(yyscanner);
295 if (yyextra->yyLineNr<yyextra->inputLines)
297 yyextra->currentFontClass = fc;
298 startCodeLine(yyscanner);
302 static void codifyLines(yyscan_t yyscanner,const char *text)
304 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
305 const char *p=text,*sp=p;
311 while ((c=*p++) && c!='\n') { }
315 int l = (int)(p-sp-1);
316 char *tmp = (char*)malloc(l+1);
319 yyextra->code->codify(tmp);
321 nextCodeLine(yyscanner);
325 yyextra->code->codify(sp);
331 static void startFontClass(yyscan_t yyscanner,const char *s)
333 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
334 endFontClass(yyscanner);
335 yyextra->code->startFontClass(s);
336 yyextra->currentFontClass=s;
339 /*! counts the number of lines in the input */
340 static int countLines(yyscan_t yyscanner)
342 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
343 const char *p=yyextra->inputString;
349 if (c=='\n') count++;
351 if (p>yyextra->inputString && *(p-1)!='\n')
352 { // last line does not end with a \n, so we add an extra
353 // line and explicitly terminate the line after parsing.
355 yyextra->needsTermination=true;
360 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size)
362 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
363 yy_size_t inputPosition = yyextra->inputPosition;
364 const char *s = yyextra->inputString + inputPosition;
366 while( c < max_size && *s )
371 yyextra->inputPosition += c;
376 // public interface -----------------------------------------------------------
378 struct SQLCodeParser::Private
381 sqlcodeYY_state state;
384 SQLCodeParser::SQLCodeParser() : p(std::make_unique<Private>())
386 sqlcodeYYlex_init_extra(&p->state, &p->yyscanner);
388 sqlcodeYYset_debug(1,p->yyscanner);
390 resetCodeParserState();
393 SQLCodeParser::~SQLCodeParser()
395 sqlcodeYYlex_destroy(p->yyscanner);
398 void SQLCodeParser::resetCodeParserState()
400 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
401 yyextra->currentDefinition = 0;
402 yyextra->currentMemberDef = 0;
405 void SQLCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
406 const QCString &scopeName,
407 const QCString &input,
410 const QCString &exampleName,
411 const FileDef *fileDef,
415 const MemberDef *memberDef,
416 bool showLineNumbers,
417 const Definition *searchCtx,
421 yyscan_t yyscanner = p->yyscanner;
422 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
424 if (input.isEmpty()) return;
426 printlex(yy_flex_debug, true, __FILE__, fileDef ? qPrint(fileDef->fileName()): NULL);
428 yyextra->code = &codeOutIntf;
429 yyextra->inputString = input.data();
430 yyextra->inputPosition = 0;
431 yyextra->currentFontClass = 0;
432 yyextra->needsTermination = false;
433 yyextra->searchCtx=searchCtx;
436 yyextra->yyLineNr = startLine;
438 yyextra->yyLineNr = 1;
441 yyextra->inputLines = endLine+1;
443 yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1;
445 yyextra->exampleBlock = isExampleBlock;
446 yyextra->exampleName = exampleName;
447 yyextra->sourceFileDef = fileDef;
449 bool cleanupSourceDef = false;
451 if (isExampleBlock && fileDef==0)
453 // create a dummy filedef for the example
454 yyextra->sourceFileDef = createFileDef(QCString(),!exampleName.isEmpty() ? exampleName : QCString("generated"));
455 cleanupSourceDef = true;
458 if (yyextra->sourceFileDef)
460 setCurrentDoc(yyscanner,"l00001");
463 yyextra->includeCodeFragment = inlineFragment;
464 // Starts line 1 on the output
465 startCodeLine(yyscanner);
467 sqlcodeYYrestart( 0, yyscanner );
469 sqlcodeYYlex(yyscanner);
471 if (yyextra->needsTermination)
473 endCodeLine(yyscanner);
475 if (cleanupSourceDef)
477 // delete the temporary file definition used for this example
478 delete yyextra->sourceFileDef;
479 yyextra->sourceFileDef=0;
482 printlex(yy_flex_debug, false, __FILE__, fileDef ? qPrint(fileDef->fileName()): NULL);
485 //---------------------------------------------------------------------------------
488 #include "sqlcode.l.h"