CppParser
Loading...
Searching...
No Matches
parser.l
Go to the documentation of this file.
1/*
2 The MIT License (MIT)
3
4 Copyright (c) 2018 Satya Das
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy of
7 this software and associated documentation files (the "Software"), to deal in
8 the Software without restriction, including without limitation the rights to
9 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 the Software, and to permit persons to whom the Software is furnished to do so,
11 subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24/* clang-format off */
25
26/*
27IMPORTANT: This file contains code to tokenify the input using flex
28For simplicity and ease of tracking error in input lexer's output is always a string (represented by CppToken).
29Responsiblity of token synthesis is solely on parser.
30For this very reason this file does not use any class that are defined in cppast.h
31*/
32
33%{
34// C++17 causes problem when register is used and flex uses register in generated code
35#define register
36
37#include "cpptoken.h"
38#include "cppvarinit.h"
39#include "parser.l.h"
40#include "lexer-helper.h"
41#include <iostream>
42
45
46// Externally controlled data
47// These do not get reset on change of input file
48extern bool gParseEnumBodyAsBlob;
49extern bool gParseFunctionBodyAsBlob;
50
51extern std::set<std::string> gMacroNames;
52extern std::set<std::string> gKnownApiDecorNames;
53extern std::map<std::string, int> gDefinedNames;
54extern std::set<std::string> gUndefinedNames;
55extern std::set<std::string> gIgnorableMacroNames;
56extern std::map<std::string, int> gRenamedKeywords;
58
59const char* contextNameFromState(int ctx);
60
61 // Easy MACRO to quickly push current context and switch to another one.
62#define BEGINCONTEXT(ctx) { \
63 int prevState = YYSTATE; \
64 yy_push_state(ctx); \
65 if (g.mLexLog) \
66 printf("parser.l line#%4d: pushed %s(%d) and started %s(%d) from input-line#%d\n", __LINE__, contextNameFromState(prevState), prevState, contextNameFromState(YYSTATE), YYSTATE, g.mLineNo); \
67}
68
69#define ENDCONTEXT() { \
70 int prevState = YYSTATE; \
71 yy_pop_state(); \
72 if (g.mLexLog) \
73 printf("parser.l line#%4d: ended %s(%d) and starting %s(%d) from input-line#%d\n", __LINE__, contextNameFromState(prevState), prevState, contextNameFromState(YYSTATE), YYSTATE, g.mLineNo); \
74}
75
76static int LogAndReturn(int ret, int codelinenum, int srclinenum)
77{
78 if (g.mLexLog)
79 {
80 printf("parser.l line#%4d: returning token %d with value '%s' found @input-line#%d\n",
81 codelinenum, ret, yytext, srclinenum);
82 }
83 return ret;
84}
85
86static void Log(int codelinenum, int srclinenum)
87{
88 if (g.mLexLog)
89 {
90 printf("parser.l line#%4d and input line#%d\n",
91 codelinenum, srclinenum);
92 }
93}
94
95#define RETURN(ret) return LogAndReturn(ret, __LINE__, g.mLineNo)
96#define LOG() Log(__LINE__, g.mLineNo)
97#define INCREMENT_INPUT_LINE_NUM() \
98{\
99 if (g.mLexLog) \
100 { \
101 printf("parser.l line#%4d: Incrementing g.mLineNo, found @input-line#%d\n", __LINE__, g.mLineNo); \
102 } \
103 ++g.mLineNo; \
104}
105
107
108#ifdef WIN32
109# define fileno _fileno /* Avoid compiler warning for VS. */
110#endif //#ifdef WIN32
111
113{
114 return YYSTATE;
115}
116
117static void setOldYytext(const char* p)
118{
119 g.mOldYytext = p;
120}
121
123{
124 switch(flag)
125 {
127 g.mTokenizeComment = false;
128 break;
130 g.mTokenizeComment = true;
131 break;
133 g.mTokenizeComment = (!g.mBracketDepthStack.empty()) && (g.mBracketDepthStack.back() == 0);
134 break;
136 // Nothing to do
137 break;
138 }
139}
140
141static void setupToken(const char* text, size_t len, TokenSetupFlag flag = TokenSetupFlag::DisableCommentTokenization)
142{
143 extern char* yyposn;
144 yyposn = const_cast<char*>(text);
145 yylval.str = makeCppToken(text, len);
146
148}
149
151{
152 setupToken(yytext, yyleng, flag);
153}
154
156{
157 setupToken(g.mOldYytext, yytext+yyleng-g.mOldYytext, flag);
158}
159
160using YYLessProc = std::function<void(int)>;
161
162// yyless is not available outside of lexing context.
163// So, yylessfn is the callback that caller needs to pass
164// that just calls yyless();
166{
167 // yyinput() has bug (see https://github.com/westes/flex/pull/396)
168 // So, I am exploiting yyless() by passing value bigger than yyleng.
169 const auto savedlen = yyleng;
170 const auto input = [&]() {
171 yylessfn(yyleng+1);
172 return yytext[yyleng-1];
173 };
174 int c = 0;
175 while (isspace(c = input()))
176 ;
177 if (c == '(')
178 {
179 int openBracket = 1;
180 for (c = input(); openBracket && (c != EOF); c = input())
181 {
182 if (c == '(')
183 {
184 ++openBracket;
185 }
186 else if (c == ')')
187 {
188 --openBracket;
189 if (!openBracket)
190 break;
191 }
192 else if (c == '\n')
193 {
195 }
196 }
197 }
198 else
199 {
200 yylessfn(savedlen);
201 }
202 setupToken();
203}
204
205static const char* findMatchedClosingBracket(const char* start, char openingBracketType = '(')
206{
207 const char openingBracket = (openingBracketType != '{') ? '(' : '{';
208 const char closingBracket = (openingBracket == '{') ? '}' : ')';
209
210 // Since '(' / '{' should be used in trailing context, it's location will contain '\0'
211 assert(*start == '\0');
212 auto end = g.mInputBuffer + g.mInputBufferSize;
213 int openBracket = 1;
214 for (auto p = start+1; p != end; ++p)
215 {
216 if (*p == openingBracket)
217 {
218 ++openBracket;
219 }
220 else if (*p == closingBracket)
221 {
222 --openBracket;
223 if (!openBracket)
224 return p;
225 }
226 }
227
228 return end;
229}
230
232{
234}
235
237{
240 }
242}
243
245{
246 if (!g.codeEnablementInfoStack.empty()) {
249 } else {
251 }
252}
253
CppToken makeCppToken(const char *sz, size_t len)
Since CppToken cannot have ctor (because it is intended to be used inside union).
Definition: cpptoken.h:67
TokenSetupFlag
Definition: parser.l.h:50
@ DisableCommentTokenization
static void setOldYytext(const char *p)
Definition: parser.l:117
int getLexerContext()
Definition: parser.l:112
static void Log(int codelinenum, int srclinenum)
Definition: parser.l:86
static int LogAndReturn(int ret, int codelinenum, int srclinenum)
Definition: parser.l:76
std::set< std::string > gMacroNames
Definition: cppparser.cpp:42
static void startNewMacroDependentParsing()
Definition: parser.l:236
LexerData g
Global data.
Definition: parser.l:44
std::set< std::string > gKnownApiDecorNames
Definition: cppparser.cpp:43
#define INCREMENT_INPUT_LINE_NUM()
Definition: parser.l:97
std::map< std::string, int > gDefinedNames
Definition: cppparser.cpp:44
bool gParseFunctionBodyAsBlob
Definition: cppparser.cpp:50
static void setBlobToken(TokenSetupFlag flag=TokenSetupFlag::None)
Definition: parser.l:155
static void tokenizeBracketedContent(YYLessProc yylessfn)
Definition: parser.l:165
static void setupToken(const char *text, size_t len, TokenSetupFlag flag=TokenSetupFlag::DisableCommentTokenization)
Definition: parser.l:141
std::set< std::string > gIgnorableMacroNames
Definition: cppparser.cpp:46
static void setCommentTokenizationState(TokenSetupFlag flag)
Definition: parser.l:122
std::map< std::string, int > gRenamedKeywords
Definition: cppparser.cpp:47
static bool codeSegmentDependsOnMacroDefinition()
Definition: parser.l:231
std::function< void(int)> YYLessProc
Definition: parser.l:160
std::set< std::string > gUndefinedNames
Definition: cppparser.cpp:45
bool gParseEnumBodyAsBlob
Definition: cppparser.cpp:49
const char * contextNameFromState(int ctx)
Definition: parser.l:1871
static void updateMacroDependence()
Definition: parser.l:244
static const char * findMatchedClosingBracket(const char *start, char openingBracketType='(')
Definition: parser.l:205
MacroDependentCodeEnablement macroDependentCodeEnablement
Definition: parser.l.h:73
BracketDepthStack mBracketDepthStack
Definition: parser.l.h:130
int mLexLog
Definition: parser.l.h:86
const char * mInputBuffer
Definition: parser.l.h:89
CodeEnablementInfo currentCodeEnablementInfo
Definition: parser.l.h:140
size_t mInputBufferSize
Definition: parser.l.h:90
const char * mOldYytext
Definition: parser.l.h:92
bool mTokenizeComment
Comments can appear anywhere in a C/C++ program and unfortunately not all coments can be preserved.
Definition: parser.l.h:117
CodeEnablementInfoStack codeEnablementInfoStack
Definition: parser.l.h:139
254%}
255
256%option never-interactive
257%option stack
258%option noyy_top_state
259%option noyywrap
260
261/************************************************************************/
262
263/*@ { Comonly used regular expressions. */
264
265/* White space. It doesn't account for new line which is tracked seperately
266 so that we can count line number for reporting error precisely */
267WS [ \t]
268
269/* New line */
270NL (\r\n|\r|\n)
271
272/* White space or new line chars. Should only be used in trainling context so that
273 new lines are always get tracked. */
274WSNL " "|\r\n|\r|\n|\t
275
276/* Token sparator */
277TS [^_a-zA-Z0-9]
278
279/* C/C++ identifier */
280ID [_a-zA-Z]+[_0-9a-zA-Z]*
281
282ID2 ({ID}"::"{WS}*)*{ID}
283
284/* Number */
285NUM ([0-9]+((l|L|u|U)*|(\.[0-9]*)?))|\.[0-9]+|(0(b|B)[01']*)|(0(x|X)[0-9a-fA-F]*)|0(x|X)[0-9a-zA-Z]+
286
287DECNUMLIT (([0-9]+(\.[0-9]*)?)|([0-9]*(\.[0-9]+)))(f|F)?
288
289/* String literal */
290SL "\""([^"\\]|\\.)*\"
291
292/* Char literal */
293CL \'([^'\\]|\\.)*\'
294
295/* Comma separated parameter list */
296CSP (({WS}*{ID}{WS}*,{WS}*)*{ID}{WS}*)*
297
298/* Function Trailing Attributes. Should be only used in trailing context.*/
299FTA ("const"|"final"|"override"|{ID})
300
301IgnorableTrailingContext {WS}*("//".*)?
302
303
304
305%x ctxGeneral
306%x ctxFreeStandingBlockComment
307%x ctxSideBlockComment
308%x ctxBlockCommentInsideMacroDefn
309
310/* This context starts when # is encountered as first thing in line while state is ctxGeneral */
311%x ctxPreprocessor
312
313/* This context starts when include is encountered while state is ctxPreprocessor */
314%x ctxInclude
315
316/* This context starts when define is encountered while state is ctxPreprocessor */
317%x ctxDefine
318
319/* This context starts when definition name is found after #define */
320%x ctxDefineDefn
321
322/*
323This context starts after #if, #elif, and #pragma to capture everyting till a new line is not found.
324*/
325%x ctxPreProBody
326
327/* When we are inside enum body */
328%x ctxEnumBody
329
330/* When we are inside function implementation body */
331%x ctxFunctionBody
332
333/* Code within and including '#if 0 ... #endif'
334 Also includes (TO BE IMPLEMENTED) the following cases:
335 '#if undefined_macro ... #endif',
336 '#ifdef undefined_macro ... #endif',
337 '#ifndef defined_macro ... #endif'
338*/
339%x ctxDisabledCode
340
341%x ctxMemInitList
342
343%x ctxObjectiveC
344
346
347<ctxGeneral>^{WS}*{NL} {
348 LOG();
350}
#define LOG()
Definition: parser.l:96
351
352<ctxGeneral,ctxFreeStandingBlockComment,ctxSideBlockComment>{NL} {
353 LOG();
355}
356
357<ctxPreprocessor>{ID} {
358 LOG();
359 setupToken();
360 RETURN(tknName);
361}
#define RETURN(ret)
Definition: parser.l:95
362
363<ctxGeneral>"__declspec"{WS}*"("{WS}*{ID}{WS}*")" {
364 LOG();
365 setupToken();
366 RETURN(tknApiDecor);
367}
368
369<ctxGeneral>__cdecl {
370 LOG();
371 setupToken();
372 RETURN(tknApiDecor);
373}
374
375<ctxGeneral>__stdcall {
376 LOG();
377 setupToken();
378 RETURN(tknApiDecor);
379}
380
381<ctxGeneral>afx_msg {
382 LOG();
383 setupToken();
384 RETURN(tknApiDecor);
385}
386
387<ctxGeneral>"alignas"{WS}*"("{WS}*{ID}{WS}*")" {
388 LOG();
389 setupToken();
390 RETURN(tknApiDecor);
391}
392
393<ctxGeneral>"alignas"{WS}*"("{WS}*{NUM}{WS}*")" {
394 LOG();
395 setupToken();
396 RETURN(tknApiDecor);
397}
398
399<ctxGeneral>{ID} {
400 LOG();
401 if (gIgnorableMacroNames.count(yytext))
402 {
403 tokenizeBracketedContent([&](int l) { yyless(l); } );
404 // Nothing to return. Just ignore
405 }
406 else
407 {
408 if (gMacroNames.count(yytext))
409 {
410 tokenizeBracketedContent([&](int l) { yyless(l); } );
411 RETURN(tknMacro);
412 }
413
414 if (gKnownApiDecorNames.count(yytext))
415 {
416 setupToken();
417 RETURN(tknApiDecor);
418 }
419
420 setupToken();
421 auto itr = gRenamedKeywords.find(yylval.str);
422 if (itr != gRenamedKeywords.end())
423 return itr->second;
424 RETURN(tknName);
425 }
426}
427
428<ctxGeneral>")"{WSNL}*({FTA}{WSNL}*)*{WSNL}*"{" {
429 LOG();
431 {
433 g.mExpectedBracePosition = yytext + yyleng-1;
434 }
435
436 REJECT;
437}
const char * mExpectedBracePosition
Definition: parser.l.h:102
bool mFunctionBodyWillBeEncountered
Definition: parser.l.h:100
438
439<ctxGeneral>")"{WSNL}*":"/{WSNL}{ID2}("("|"{") {
440 LOG();
442 {
444 g.mExpectedColonPosition = yytext + yyleng-1;
445 }
446
447 REJECT;
448}
bool mMemInitListWillBeEncountered
Definition: parser.l.h:101
const char * mExpectedColonPosition
Definition: parser.l.h:103
449
450<ctxGeneral>asm/{TS} {
451 LOG();
452 tokenizeBracketedContent([&](int l) { yyless(l); } );
453 RETURN(tknAsm);
454}
455
456<ctxGeneral>goto/{TS} {
457 LOG();
458 RETURN(tknGoto);
459}
460
461<ctxGeneral>signed|unsigned/{TS} {
462 LOG();
463 setupToken();
464 RETURN(tknNumSignSpec);
465}
466
467<ctxGeneral>long{WS}+long{WS}+int|long{WS}+long|long{WS}+int|long|int|short{WS}+int|short/{TS} {
468 LOG();
469 setupToken();
470 RETURN(tknInteger);
471}
472
473<ctxGeneral>__int8|__int16|__int32|__int64|__int128/{TS} {
474 LOG();
475 setupToken();
476 RETURN(tknInteger);
477}
478
479<ctxGeneral>char/{TS} {
480 LOG();
481 setupToken();
482 RETURN(tknChar);
483}
484
485<ctxGeneral>long{WS}+double|double/{TS} {
486 LOG();
487 setupToken();
488 RETURN(tknDouble);
489}
490
491<ctxGeneral>long{WS}+float|float/{TS} {
492 LOG();
493 setupToken();
494 RETURN(tknFloat);
495}
496
497<ctxGeneral>auto/{TS} {
498 LOG();
499 setupToken();
500 RETURN(tknAuto);
501}
502
503<ctxGeneral>typedef{TS}+ {
504 LOG();
505 setupToken();
506 RETURN(tknTypedef);
507}
508
509<ctxGeneral>using{TS}+ {
510 LOG();
511 setupToken();
512 RETURN(tknUsing);
513}
514
515<ctxGeneral>class/{TS} {
516 LOG();
517 setupToken();
518 RETURN(tknClass);
519}
520
521<ctxGeneral>namespace/{TS} {
522 LOG();
523 setupToken();
524 RETURN(tknNamespace);
525}
526
527<ctxGeneral>struct/{TS} {
528 LOG();
529 setupToken();
530 RETURN(tknStruct);
531}
532
533<ctxGeneral>union/{TS} {
534 LOG();
535 setupToken();
536 RETURN(tknUnion);
537}
538
539<ctxGeneral>enum/{WS}+(class{WS}+)?{ID}?({WS}*":"{WS}*{ID})?{WSNL}*"{" {
540 LOG();
541 setupToken();
544 RETURN(tknEnum);
545}
bool mEnumBodyWillBeEncountered
Definition: parser.l.h:95
546
547<ctxGeneral>enum/{TS} {
548 LOG();
549 setupToken();
550 RETURN(tknEnum);
551}
552
553<ctxGeneral>public/{WS}*":" {
554 LOG();
556 RETURN(tknPublic);
557}
558
559<ctxGeneral>public/{TS} {
560 LOG();
561 setupToken();
562 RETURN(tknPublic);
563}
564
565<ctxGeneral>protected/{WS}*":" {
566 LOG();
568 RETURN(tknProtected);
569}
570
571<ctxGeneral>protected/{TS} {
572 LOG();
573 setupToken();
574 RETURN(tknProtected);
575}
576
577<ctxGeneral>private/{WS}*":" {
578 LOG();
580 RETURN(tknPrivate);
581}
582
583<ctxGeneral>private/{TS} {
584 LOG();
585 setupToken();
586 RETURN(tknPrivate);
587}
588
589<ctxGeneral>template/{TS} {
590 LOG();
591 setupToken();
592 RETURN(tknTemplate);
593}
594
595<ctxGeneral>typename/{TS} {
596 LOG();
597 setupToken();
598 RETURN(tknTypename);
599}
600
601<ctxGeneral>decltype/{TS} {
602 LOG();
603 setupToken();
604 RETURN(tknDecltype);
605}
606
607<ctxGeneral>^{WS}*"/*" {
608 LOG();
609 setOldYytext(yytext);
610 BEGINCONTEXT(ctxFreeStandingBlockComment);
611}
#define BEGINCONTEXT(ctx)
Definition: parser.l:62
612
613<*>"/*" {
614 /*
615 Ignore side comments for time being
616 setOldYytext(yytext);
617 */
618 BEGINCONTEXT(ctxSideBlockComment);
619}
620
621<ctxFreeStandingBlockComment>[^*\n]*"*"+"/"/{WS}*{NL} {
622 LOG();
623 ENDCONTEXT();
625 {
627 RETURN(tknFreeStandingBlockComment);
628 }
629}
#define ENDCONTEXT()
Definition: parser.l:69
630<ctxFreeStandingBlockComment>[^*\n]*"*"+"/" {
631 LOG();
632 ENDCONTEXT();
633}
634
635<ctxSideBlockComment>[^*\n]*"*"+"/" {
636 LOG();
637 ENDCONTEXT();
638
639 /*
640 Ignore side comments for time being
641 if (g.mTokenizeComment)
642 setupToken(g.mOldYytext, yytext+yyleng-g.mOldYytext, TokenSetupFlag::None);
643 RETURN(tknSideBlockComment);
644 }
645 */
646}
647
648<ctxSideBlockComment,ctxFreeStandingBlockComment,ctxBlockCommentInsideMacroDefn>[^*\n]* {
649 LOG();
650}
651<ctxSideBlockComment,ctxFreeStandingBlockComment,ctxBlockCommentInsideMacroDefn>[^*\n]*\n {
652 LOG();
654}
655<ctxSideBlockComment,ctxFreeStandingBlockComment,ctxBlockCommentInsideMacroDefn>{WS}*"*"+[^*/\n]* {
656 LOG();
657}
658<ctxSideBlockComment,ctxFreeStandingBlockComment,ctxBlockCommentInsideMacroDefn>{WS}*"*"+[^*/\n]*\n {
659 LOG();
661}
662<ctxSideBlockComment,ctxFreeStandingBlockComment,ctxBlockCommentInsideMacroDefn>. {
663 LOG();
664}
665
666<*>^{WS}*"//"[^\n]* {
668 {
670 RETURN(tknFreeStandingLineComment);
671 }
672}
673
674<*>"//"[^\n]* {
676 {
678 // Ignore side comments for time being
679 // RETURN(tknSideLineComment);
680 }
681}
682
683<ctxGeneral>^{WS}*# {
684 LOG();
685 setupToken();
686 BEGINCONTEXT(ctxPreprocessor);
687 RETURN(tknPreProHash);
688}
689
690<ctxPreprocessor>define/{WS} {
691 LOG();
692 setupToken();
693 ENDCONTEXT();
694 BEGINCONTEXT(ctxDefine);
695 RETURN(tknDefine);
696
697 /*
698 Parsing of #define is tricky
699 We want to know if #define is used to define simple constants.
700 For all other cases it is OK to capture the entire block as one BLOB.
701 An attempt to parse MACRO is difficult because we can have things like:
702 #define GLUT_BITMAP_HELVETICA_18 ((void*)8)
703 In this case '(' is part of definition rather than used to specify parameter of MACRO.
704 MACRO can be used to define partial expression like:
705 #define BEGIN yy_start = 1 + 2 *
706 So, if we want to parse the definition as an expression then that too will fail.
707 Basically #define can be used in myriad ways which will be too difficult for us to parse.
708 */
709}
710
711<ctxDefine>{ID}\‍({CSP}\‍) {
712 LOG();
713 setupToken();
714 ENDCONTEXT();
715 BEGINCONTEXT(ctxDefineDefn);
717 setOldYytext(yytext + yyleng);
718 RETURN(tknName);
719}
@ kComplexDef
Definition: parser.l.h:46
DefineLooksLike mDefLooksLike
Definition: parser.l.h:137
720
721<ctxDefine>{ID}\‍(.*"...".*\‍) {
722 LOG();
723 setupToken();
724 ENDCONTEXT();
725 BEGINCONTEXT(ctxDefineDefn);
727 setOldYytext(yytext + yyleng);
728 RETURN(tknName);
729}
730
731<ctxDefine>{ID} {
732 LOG();
733 setupToken();
734 ENDCONTEXT();
735 BEGINCONTEXT(ctxDefineDefn);
737 setOldYytext(0);
738 RETURN(tknName);
739}
@ kNoDef
Definition: parser.l.h:41
740
741<ctxDefineDefn>{ID} {
742 LOG();
743 if(g.mDefLooksLike == kNoDef)
744 {
746 setOldYytext(yytext);
747 }
749 {
750 // Looks like string literal definition by concatination of different token
751 // e.g. #define APP_NAME PROD_NAME VER_STR
752 // Where PROD_NAME and VER_STR are already #defined as string literals.
754 }
755 else
756 { // It does not look like simple #define.
757 if (g.mOldYytext == 0)
758 setOldYytext(yytext);
760 }
761}
@ kStrLitDef
Definition: parser.l.h:43
@ kReDef
Definition: parser.l.h:45
762
763<ctxDefineDefn>{SL} {
764 LOG();
766 {
768 if(g.mOldYytext == 0)
769 setOldYytext(yytext);
770 }
771 else
772 { // It does not look like simple #define.
774 }
775}
776
777<ctxDefineDefn>{CL} {
778 LOG();
779 if(g.mDefLooksLike == kNoDef)
780 {
782 setOldYytext(yytext);
783 }
784 else
785 { // It does not look like simple #define.
787 }
788}
@ kCharLitDef
Definition: parser.l.h:44
789
790<ctxDefineDefn>{NUM} {
791 LOG();
792 if(g.mDefLooksLike == kNoDef)
793 {
795 setOldYytext(yytext);
796 }
797 else
798 { // It does not look like simple #define.
800 }
801}
@ kNumDef
Definition: parser.l.h:42
802
803<ctxDefineDefn>[^\t\r\n ] { // Any unrecognized character other than whitespace indicates a complex #define
804 LOG();
806 if(g.mOldYytext == 0)
807 setOldYytext(yytext);
808}
809
810<ctxDefineDefn>{NL} {
811 LOG();
813 ENDCONTEXT();
815 if(g.mDefLooksLike != kNoDef)
817}
818
819<ctxDefineDefn>"//".*{NL} {
820 LOG();
821 /* Ignore line comment when it does not stand alone in a line. */
822 // We are also ignoring the last new-line character
823 // It is because we want the #define to conclude if C++ comment is present at the end of #define.
824 yyless((yyleng-1));
825}
826
827<ctxDefineDefn>{WS}*"/*"[^\n]*"*/"{WS}*/{NL} {
828 LOG();
829}
830
831<ctxDefineDefn>{WS}*"/*" {
832 LOG();
833 BEGINCONTEXT(ctxBlockCommentInsideMacroDefn);
834}
835
836<ctxBlockCommentInsideMacroDefn>{NL} {
837 LOG();
839 ENDCONTEXT(); // End ctxBlockCommentInsideMacroDefn
840 ENDCONTEXT(); // End ctxDefineDefn
841 BEGINCONTEXT(ctxSideBlockComment);
843 if(g.mDefLooksLike != kNoDef)
845}
846
847<ctxBlockCommentInsideMacroDefn>[^*\n]*"*"+"/" {
848 LOG();
849 ENDCONTEXT();
850}
851
852<ctxBlockCommentInsideMacroDefn>.*"*/"/{WS}*"\\"{WS}*{NL} {
853 LOG();
854 ENDCONTEXT();
855}
856
857<ctxBlockCommentInsideMacroDefn>.*"\\"{WS}*{NL} {
858 LOG();
860}
861
862<ctxPreprocessor>undef/{WS} {
863 LOG();
864 setupToken();
865 RETURN(tknUndef);
866}
867
868<ctxPreprocessor>include/{WS} {
869 LOG();
870 ENDCONTEXT();
871 setupToken();
872 BEGINCONTEXT(ctxInclude);
873 RETURN(tknInclude);
874}
875
876<ctxPreprocessor>import/{WS} {
877 LOG();
878 ENDCONTEXT();
879 setupToken();
880 BEGINCONTEXT(ctxInclude);
881 RETURN(tknImport);
882}
883
884<ctxInclude><.*> {
885 LOG();
886 setupToken();
887 RETURN(tknStdHdrInclude);
888}
889
890<ctxInclude>{ID} {
891 LOG();
892 setupToken();
893 RETURN(tknStdHdrInclude);
894}
895
896<ctxInclude>{NL} {
897 LOG();
899 ENDCONTEXT();
901}
902
903<ctxPreprocessor>if/{WS} {
904 LOG();
905
908
909 setupToken();
910 setOldYytext(yytext+yyleng);
911 ENDCONTEXT();
912 BEGINCONTEXT(ctxPreProBody);
913 RETURN(tknIf);
914}
int numHashIfInMacroDependentCode
Counting of # to keep track of when we need to consider the code outside of disabled segment.
Definition: parser.l.h:78
915
916<ctxPreprocessor>ifdef/{WS} {
917 LOG();
918
921
922 setupToken();
923 RETURN(tknIfDef);
924}
925
926<ctxPreprocessor>ifndef/{WS} {
927 LOG();
928
931
933 RETURN(tknIfNDef);
934}
935
936<ctxPreprocessor>else/{TS} {
937 LOG();
938 setupToken();
939 RETURN(tknElse);
940}
941
942<ctxPreprocessor>elif/{WS} {
943 LOG();
944 setupToken();
945 setOldYytext(yytext+yyleng);
946 ENDCONTEXT();
947 BEGINCONTEXT(ctxPreProBody);
948 RETURN(tknElIf);
949}
950
951<ctxPreprocessor>endif/{TS} {
952 LOG();
953
957
959 ENDCONTEXT();
960 RETURN(tknEndIf);
961 }
962}
963
964<ctxGeneral>^{WS}*#{WS}*if/{WS}+"0" {
965 LOG();
966 setOldYytext(yytext);
967 BEGINCONTEXT(ctxDisabledCode);
969
971}
972
973<ctxGeneral>^{WS}*"#"{WS}*"if"{WS}+{ID}{WS}*("//"|"/*")?{NL} {
974 LOG();
975
976 std::string id(yyleng, '\0');
977 sscanf(yytext, " # if %[a-zA-Z0-9_]", id.data());
978 id.resize(strlen(id.data()));
979 const auto idVal = getIdValue(id);
980 if (!idVal.has_value()) {
981 REJECT;
982 }
983 LOG();
984
989
991 BEGINCONTEXT(ctxDisabledCode);
992 }
993}
std::optional< int > getIdValue(const std::string &id)
994
995<ctxGeneral>^{WS}*"#"{WS}*"if"{WS}+{ID}{WS}*">="{WS}*{NUM}{IgnorableTrailingContext}{NL} {
996 LOG();
997
998 std::string id(yyleng, '\0');
999 int n=0;
1000 sscanf(yytext, " # if %[a-zA-Z0-9_] >= %d", id.data(), &n);
1001 id.resize(strlen(id.data()));
1002 const auto idVal = getIdValue(id);
1003 if (!idVal.has_value()) {
1004 REJECT;
1005 }
1006
1011
1013 BEGINCONTEXT(ctxDisabledCode);
1014 }
1015}
1016
1017<ctxGeneral>^{WS}*#{WS}*if{WS}+"!"{ID}{IgnorableTrailingContext}{NL} {
1018 LOG();
1019
1020 std::string id(yyleng, '\0');
1021 sscanf(yytext, " # if ! %[a-zA-Z0-9_]", id.data());
1022 id.resize(strlen(id.data()));
1023 const auto idVal = getIdValue(id);
1024
1025 if (!idVal.has_value()) {
1026 REJECT;
1027 }
1028
1030 g.currentCodeEnablementInfo.macroDependentCodeEnablement = (!idVal.has_value() || idVal.value() == 0)
1033
1035 LOG();
1036 BEGINCONTEXT(ctxDisabledCode);
1037 }
1038}
1039
1040<ctxGeneral>^{WS}*#{WS}*ifdef{WS}+{ID}{IgnorableTrailingContext}{NL} {
1041 LOG();
1042
1043 std::string id(yyleng, '\0');
1044 sscanf(yytext, " # ifdef %[a-zA-Z0-9_]", id.data());
1045 id.resize(strlen(id.data()));
1046
1047 const auto macroDefineInfo = getMacroDefineInfo(id);
1048 if (macroDefineInfo == MacroDefineInfo::kNoInfo) {
1049 REJECT;
1050 }
1051
1056
1058 LOG();
1059 BEGINCONTEXT(ctxDisabledCode);
1060 }
1061}
MacroDefineInfo getMacroDefineInfo(const std::string &id)
1062
1063<ctxGeneral>^{WS}*#{WS}*if{WS}+"defined("{WS}*{ID}{WS}*")"{IgnorableTrailingContext}{NL} {
1064 LOG();
1065
1066 std::string id(yyleng, '\0');
1067 sscanf(yytext, " # if defined( %[a-zA-Z0-9_])", id.data());
1068 id.resize(strlen(id.data()));
1069
1070 const auto macroDefineInfo = getMacroDefineInfo(id);
1071 if (macroDefineInfo == MacroDefineInfo::kNoInfo) {
1072 REJECT;
1073 }
1074
1079
1081 LOG();
1082 BEGINCONTEXT(ctxDisabledCode);
1083 }
1084}
1085
1086<ctxGeneral>^{WS}*#{WS}*ifndef{WS}+{ID}{IgnorableTrailingContext}{NL} {
1087 LOG();
1088
1089 std::string id(yyleng, '\0');
1090 sscanf(yytext, " # ifndef %[a-zA-Z0-9_]", id.data());
1091 id.resize(strlen(id.data()));
1092
1093 const auto macroDefineInfo = getMacroDefineInfo(id);
1094 if (macroDefineInfo == MacroDefineInfo::kNoInfo) {
1095 REJECT;
1096 }
1097
1102
1104 LOG();
1105 BEGINCONTEXT(ctxDisabledCode);
1106 }
1107}
1108
1109<ctxGeneral,ctxDisabledCode>^{WS}*#{WS}*else{TS} {
1110 LOG();
1112 LOG();
1113 REJECT;
1114 }
1115
1116 LOG();
1120 BEGINCONTEXT(ctxDisabledCode);
1121 } else {
1122 ENDCONTEXT();
1123 }
1124 }
1125}
MacroDependentCodeEnablement invert(MacroDependentCodeEnablement enabledCodeDecision)
Definition: lexer-helper.h:9
1126
1127<ctxDisabledCode>. {
1128 LOG();
1129}
1130
1131<ctxDisabledCode>{NL} {
1132 LOG();
1134}
1135
1136<ctxDisabledCode>^{WS}*#{WS}*if {
1138}
1139
1140<*>^{WS}*#{WS}*endif{IgnorableTrailingContext}{NL}* {
1141 LOG();
1142
1144 REJECT;
1145 }
1146
1147 if ((g.currentCodeEnablementInfo.numHashIfInMacroDependentCode != 0) && (YYSTATE != ctxDisabledCode)) {
1148 REJECT;
1149 }
1150
1153 if (YYSTATE == ctxDisabledCode) {
1154 ENDCONTEXT();
1156 setBlobToken();
1157 RETURN(tknBlob);
1158 }
1159 }
1160 } else {
1162 }
1163}
bool parseDisabledCodeAsBlob
Definition: parser.l.h:142
1164
1165<ctxPreprocessor>pragma/{WS} {
1166 LOG();
1167 setupToken();
1168 setOldYytext(yytext+yyleng);
1169 ENDCONTEXT();
1170 BEGINCONTEXT(ctxPreProBody);
1171 RETURN(tknPragma);
1172}
1173
1174<ctxPreProBody>.*\\{WS}*{NL} {
1175 LOG();
1177}
1178
1179<ctxPreProBody>.* {
1180 LOG();
1181}
1182
1183<ctxPreProBody>{NL} {
1184 LOG();
1186 ENDCONTEXT();
1188 RETURN(tknPreProDef);
1189}
1190
1191<ctxPreprocessor>{NL} {
1192 LOG();
1194 ENDCONTEXT();
1196}
1197
1198<ctxPreprocessor>error{WS}[^\n]*{NL} {
1199 LOG();
1201 ENDCONTEXT();
1203 RETURN(tknHashError);
1204}
1205
1206<ctxPreprocessor>warning{WS}[^\n]*{NL} {
1207 LOG();
1209 ENDCONTEXT();
1211 RETURN(tknHashWarning);
1212}
1213
1214<ctxGeneral>"::" {
1215 LOG();
1216 setupToken();
1217 RETURN(tknScopeResOp);
1218}
1219
1220<ctxGeneral>const/{TS} {
1221 LOG();
1222 setupToken();
1223 RETURN(tknConst);
1224}
1225
1226<ctxGeneral>constexpr/{TS} {
1227 LOG();
1228 setupToken();
1229 RETURN(tknConstExpr);
1230}
1231
1232<ctxGeneral>static/{TS} {
1233 LOG();
1234 setupToken();
1235 RETURN(tknStatic);
1236}
1237
1238<ctxGeneral>inline/{TS} {
1239 LOG();
1240 setupToken();
1241 RETURN(tknInline);
1242}
1243
1244<ctxGeneral>virtual/{TS} {
1245 LOG();
1246 setupToken();
1247 RETURN(tknVirtual);
1248}
1249
1250<ctxGeneral>override/{TS} {
1251 LOG();
1252 setupToken();
1253 RETURN(tknOverride);
1254}
1255
1256<ctxGeneral>final/{TS} {
1257 LOG();
1258 setupToken();
1259 RETURN(tknFinal);
1260}
1261
1262<ctxGeneral>noexcept/{TS} {
1263 LOG();
1264 setupToken();
1265 RETURN(tknNoExcept);
1266}
1267
1268<ctxGeneral>extern/{TS} {
1269 LOG();
1270 setupToken();
1271 RETURN(tknExtern);
1272}
1273
1274<ctxGeneral>explicit/{TS} {
1275 LOG();
1276 setupToken();
1277 RETURN(tknExplicit);
1278}
1279
1280<ctxGeneral>friend/{TS} {
1281 LOG();
1282 setupToken();
1283 RETURN(tknFriend);
1284}
1285
1286<ctxGeneral>"extern"{WS}+"\"C\"" {
1287 LOG();
1288 setupToken();
1289 RETURN(tknExternC);
1290}
1291
1292<ctxGeneral>volatile/{TS} {
1293 LOG();
1294 setupToken();
1295 RETURN(tknVolatile);
1296}
1297
1298<ctxGeneral>mutable/{TS} {
1299 LOG();
1300 setupToken();
1301 RETURN(tknMutable);
1302}
1303
1304<ctxGeneral>new/{TS} {
1305 LOG();
1306 setupToken();
1307 RETURN(tknNew);
1308}
1309
1310<ctxGeneral>delete/{TS} {
1311 LOG();
1312 setupToken();
1313 RETURN(tknDelete);
1314}
1315
1316<ctxGeneral>default/{TS} {
1317 LOG();
1318 setupToken();
1319 RETURN(tknDefault);
1320}
1321
1322<ctxGeneral>return/{TS} {
1323 LOG();
1324 setupToken();
1325 RETURN(tknReturn);
1326}
1327
1328<ctxGeneral>if/{TS} {
1329 LOG();
1330 setupToken();
1331 RETURN(tknIf);
1332}
1333
1334<ctxGeneral>else/{TS} {
1335 LOG();
1336 setupToken();
1337 RETURN(tknElse);
1338}
1339
1340<ctxGeneral>for/{TS} {
1341 LOG();
1342 setupToken();
1343 RETURN(tknFor);
1344}
1345
1346<ctxGeneral>do/{TS} {
1347 LOG();
1348 setupToken();
1349 RETURN(tknDo);
1350}
1351
1352<ctxGeneral>while/{TS} {
1353 LOG();
1354 setupToken();
1355 RETURN(tknWhile);
1356}
1357
1358<ctxGeneral>switch/{TS} {
1359 LOG();
1360 setupToken();
1361 RETURN(tknSwitch);
1362}
1363
1364<ctxGeneral>case/{TS} {
1365 LOG();
1366 setupToken();
1367 RETURN(tknCase);
1368}
1369
1370<ctxGeneral>const_cast/{TS} {
1371 LOG();
1372 setupToken();
1373 RETURN(tknConstCast);
1374}
1375
1376<ctxGeneral>static_cast/{TS} {
1377 LOG();
1378 setupToken();
1379 RETURN(tknStaticCast);
1380}
1381
1382<ctxGeneral>dynamic_cast/{TS} {
1383 LOG();
1384 setupToken();
1385 RETURN(tknDynamicCast);
1386}
1387
1388<ctxGeneral>reinterpret_cast/{TS} {
1389 LOG();
1390 setupToken();
1391 RETURN(tknReinterpretCast);
1392}
1393
1394<ctxGeneral>try/{TS} {
1395 LOG();
1396 setupToken();
1397 RETURN(tknTry);
1398}
1399
1400<ctxGeneral>catch/{TS} {
1401 LOG();
1402 setupToken();
1403 RETURN(tknCatch);
1404}
1405
1406<ctxGeneral>throw/{TS} {
1407 LOG();
1408 setupToken();
1409 RETURN(tknThrow);
1410}
1411
1412<ctxGeneral>sizeof/{TS} {
1413 LOG();
1414 setupToken();
1415 RETURN(tknSizeOf);
1416}
1417
1418<ctxGeneral>operator/{TS} {
1419 LOG();
1420 setupToken();
1421 RETURN(tknOperator);
1422}
1423
1424<ctxGeneral>operator{WSNL}*/">>" {
1425 LOG();
1426 setupToken();
1427 g.mExpectedRShiftOperator = yytext + yyleng;
1428 RETURN(tknOperator);
1429}
const char * mExpectedRShiftOperator
Definition: parser.l.h:107
1430
1431<ctxGeneral>void/{TS} {
1432 LOG();
1433 setupToken();
1434 RETURN(tknVoid);
1435}
1436
1437<ctxGeneral>"+=" {
1438 LOG();
1439 setupToken();
1440 RETURN(tknPlusEq);
1441}
1442
1443<ctxGeneral>"-=" {
1444 LOG();
1445 setupToken();
1446 RETURN(tknMinusEq);
1447}
1448
1449<ctxGeneral>"*=" {
1450 LOG();
1451 setupToken();
1452 RETURN(tknMulEq);
1453}
1454
1455<ctxGeneral>"*=" {
1456 LOG();
1457 setupToken();
1458 RETURN(tknMulEq);
1459}
1460
1461<ctxGeneral>"/=" {
1462 LOG();
1463 setupToken();
1464 RETURN(tknDivEq);
1465}
1466
1467<ctxGeneral>"%=" {
1468 LOG();
1469 setupToken();
1470 RETURN(tknPerEq);
1471}
1472
1473<ctxGeneral>"^=" {
1474 LOG();
1475 setupToken();
1476 RETURN(tknXorEq);
1477}
1478
1479<ctxGeneral>"&=" {
1480 LOG();
1481 setupToken();
1482 RETURN(tknAndEq);
1483}
1484
1485<ctxGeneral>"|=" {
1486 LOG();
1487 setupToken();
1488 RETURN(tknOrEq);
1489}
1490
1491<ctxGeneral>"<<" {
1492 LOG();
1493 setupToken();
1494 RETURN(tknLShift);
1495}
1496
1497<ctxGeneral>"<<=" {
1498 LOG();
1499 setupToken();
1500 RETURN(tknLShiftEq);
1501}
1502
1503<ctxGeneral>">>" {
1504 LOG();
1505 if (g.mExpectedRShiftOperator == yytext) {
1506 g.mExpectedRShiftOperator = nullptr;
1507 setupToken();
1508 RETURN(tknRShift);
1509 } else {
1510 yyless(1);
1511 setupToken();
1512 RETURN(tknGT);
1513 }
1514}
1515
1516<ctxGeneral>">>=" {
1517 LOG();
1518 setupToken();
1519 RETURN(tknRShiftEq);
1520}
1521
1522<ctxGeneral>"==" {
1523 LOG();
1524 setupToken();
1525 RETURN(tknCmpEq);
1526}
1527
1528<ctxGeneral>"!=" {
1529 LOG();
1530 setupToken();
1531 RETURN(tknNotEq);
1532}
1533
1534<ctxGeneral>"<=" {
1535 LOG();
1536 setupToken();
1537 RETURN(tknLessEq);
1538}
1539
1540<ctxGeneral>">=" {
1541 LOG();
1542 setupToken();
1543 RETURN(tknGreaterEq);
1544}
1545
1546<ctxGeneral>"<=>" {
1547 LOG();
1548 setupToken();
1549 RETURN(tkn3WayCmp);
1550}
1551
1552<ctxGeneral>"&&" {
1553 LOG();
1554 setupToken();
1555 RETURN(tknAnd);
1556}
1557
1558<ctxGeneral>"||" {
1559 LOG();
1560 setupToken();
1561 RETURN(tknOr);
1562}
1563
1564<ctxGeneral>"++" {
1565 LOG();
1566 setupToken();
1567 RETURN(tknInc);
1568}
1569
1570<ctxGeneral>"--" {
1571 LOG();
1572 setupToken();
1573 RETURN(tknDec);
1574}
1575
1576<ctxGeneral>"->" {
1577 LOG();
1578 setupToken();
1579 RETURN(tknArrow);
1580}
1581
1582<ctxGeneral>"->*" {
1583 LOG();
1584 setupToken();
1585 RETURN(tknArrowStar);
1586}
1587
1588<ctxGeneral,ctxDefine>{NUM} {
1589 LOG();
1590 setupToken();
1591 RETURN(tknNumber);
1592}
1593
1594<ctxGeneral>{DECNUMLIT}((e|E)[+-]?{DECNUMLIT})? {
1595 LOG();
1596 setupToken();
1597 RETURN(tknNumber);
1598}
1599
1600<ctxGeneral,ctxInclude>{SL} {
1601 LOG();
1602 setupToken();
1603 RETURN(tknStrLit);
1604}
1605
1606<ctxGeneral>(L)?{SL} {
1607 LOG();
1608 setupToken();
1609 RETURN(tknStrLit);
1610}
1611
1612<ctxGeneral>(L)?{CL} {
1613 LOG();
1614 setupToken();
1615 RETURN(tknCharLit);
1616}
1617
1618<ctxGeneral>"("|"[" {
1619 LOG();
1621 g.mBracketDepthStack.back() = g.mBracketDepthStack.back() + 1;
1622 RETURN(yytext[0]);
1623}
1624
1625<ctxGeneral>")"|"]" {
1626 LOG();
1628 g.mBracketDepthStack.back() = g.mBracketDepthStack.back() - 1;
1629 RETURN(yytext[0]);
1630}
1631
1632<ctxGeneral>"{" {
1633 LOG();
1635 {
1637 BEGINCONTEXT(ctxEnumBody);
1639 setOldYytext(yytext+1);
1640 }
1642 {
1643
1645 BEGINCONTEXT(ctxFunctionBody);
1647 setOldYytext(yytext+1);
1648 }
1649 else
1650 {
1651
1652 g.mBracketDepthStack.push_back(0);
1654 }
1655 RETURN(yytext[0]);
1656}
1657
1658<ctxGeneral>"}" {
1659 LOG();
1660 g.mBracketDepthStack.resize(g.mBracketDepthStack.size() - 1);
1662 RETURN(yytext[0]);
1663}
1664
1665<ctxEnumBody>"}" {
1666 LOG();
1668 ENDCONTEXT();
1669 RETURN(yytext[0]);
1670}
1671
1672<ctxEnumBody>[^\}\n]* {
1673 LOG();
1674 // printf("%s", yytext);
1675}
1676
1677<ctxEnumBody>{NL} {
1678 LOG();
1680}
1681
1682<ctxEnumBody>{NL}/"}" {
1683 LOG();
1685 setBlobToken();
1686 RETURN(tknBlob);
1687}
1688
1689<ctxEnumBody>([^\}\n]*|^{WS}*)/"}" {
1690 LOG();
1691 setBlobToken();
1692 RETURN(tknBlob);
1693}
1694
1695<ctxFunctionBody>"{" {
1696 LOG();
1698}
int mNestedCurlyBracketDepth
It is currently used for parsing function body as a blob.
Definition: parser.l.h:135
1699
1700<ctxFunctionBody>"}" {
1701 LOG();
1702 if (g.mNestedCurlyBracketDepth == 0)
1703 {
1704 ENDCONTEXT();
1706 RETURN(yytext[0]);
1707 }
1708 else
1709 {
1711 }
1712}
1713
1714<ctxFunctionBody>{NL}/"}" {
1715 LOG();
1717 if (g.mNestedCurlyBracketDepth == 0)
1718 {
1719 setBlobToken();
1720 RETURN(tknBlob);
1721 }
1722}
1723
1724<ctxFunctionBody>([^{}\n]|{WS}*)/"}" {
1725 LOG();
1726 if (g.mNestedCurlyBracketDepth == 0)
1727 {
1728 setBlobToken();
1729 RETURN(tknBlob);
1730 }
1731}
1732
1733<ctxFunctionBody>{NL} {
1734 LOG();
1736}
1737
1738<ctxFunctionBody>. {
1739 LOG();
1740 // printf("%s", yytext);
1741}
1742
1743<ctxGeneral>":" {
1744 LOG();
1746 {
1747
1749 setOldYytext(yytext+1);
1750 BEGINCONTEXT(ctxMemInitList);
1751 }
1753 RETURN(yytext[0]);
1754}
1755
1756<ctxMemInitList>({ID2}{WSNL}*)/"(" {
1757 LOG();
1759 yyless((g.mPossibleFuncImplStartBracePosition - yytext));
1760}
const char * mPossibleFuncImplStartBracePosition
Definition: parser.l.h:104
1761
1762<ctxMemInitList>({ID2}{WSNL}*)/"{" {
1763 LOG();
1765 yyless((g.mPossibleFuncImplStartBracePosition - yytext));
1766}
1767
1768<ctxMemInitList>^{WS}*"#"{WS}*"if"(.*)/{TS} {
1769 LOG();
1770}
1771
1772<ctxMemInitList>^{WS}*"#"{WS}*"endif"/{TS} {
1773 LOG();
1774}
1775
1776<ctxMemInitList>({NL}) {
1777 LOG();
1779}
1780
1781<ctxMemInitList>(.) {
1782 LOG();
1783 if (yytext[0] == '\n')
1784 {
1786 }
1787 else if(yytext[0] == '{')
1788 {
1789 LOG();
1790 if (yytext+yyleng >= g.mPossibleFuncImplStartBracePosition)
1791 {
1792 LOG();
1793 ENDCONTEXT();
1794 g.mExpectedBracePosition = yytext;
1796 yyless(0); // Return back the '{' to be processed
1797 setBlobToken();
1798 RETURN(tknBlob);
1799 }
1800 }
1801}
1802
1803<ctxGeneral>; {
1804 LOG();
1805 setupToken();
1806 g.mTokenizeComment = true;
1807 RETURN(yytext[0]);
1808}
1809
1810<ctxGeneral>, {
1811 LOG();
1813 RETURN(yytext[0]);
1814}
1815
1816<ctxGeneral>\‍)|\]|#|=|\*|\+|-|\.|\/|\~|%|\^|&|\||\?|\! {
1817 LOG();
1818 setupToken();
1819 RETURN(yytext[0]);
1820}
1821
1822<ctxGeneral>">" {
1823 LOG();
1824 setupToken();
1825 RETURN(tknGT);
1826}
1827
1828<ctxGeneral>"<" {
1829 LOG();
1830 setupToken();
1831 RETURN(tknLT);
1832}
1833
1834<ctxGeneral>\.\.\. {
1835 LOG();
1836 setupToken();
1837 RETURN(tknEllipsis);
1838}
1839
1840<*>{WS}+ {
1841 /* Ignore white spaces */
1842}
1843
1844<*>\\{WS}*{NL} {
1845 // We will always ignore line continuation character
1847}
1848
1849<*>__attribute__{WS}*\‍(\‍(.*\‍)\‍) {
1850 /* Ignore as of now */
1851}
1852
1853<ctxGeneral>^"@interface" {
1854 BEGINCONTEXT(ctxObjectiveC);
1855}
1856
1857<ctxObjectiveC>{NL} {
1859}
1860
1861<ctxObjectiveC>. {
1862 /* Ignore everything Objective C */
1863}
1864
1865<ctxObjectiveC>^"@end" {
1866 ENDCONTEXT();
1867}
1868
1869%%
1870
1871const char* contextNameFromState(int ctx)
1872{
1873 switch (ctx) {
1874 case INITIAL :
1875 return "INITIAL";
1876 case ctxGeneral :
1877 return "ctxGeneral";
1878 case ctxFreeStandingBlockComment :
1879 return "ctxFreeStandingBlockComment";
1880 case ctxSideBlockComment :
1881 return "ctxSideBlockComment";
1882 case ctxBlockCommentInsideMacroDefn :
1883 return "ctxBlockCommentInsideMacroDefn";
1884 case ctxPreprocessor :
1885 return "ctxPreprocessor";
1886 case ctxInclude :
1887 return "ctxInclude";
1888 case ctxDefine :
1889 return "ctxDefine";
1890 case ctxDefineDefn :
1891 return "ctxDefineDefn";
1892 case ctxPreProBody :
1893 return "ctxPreProBody";
1894 case ctxEnumBody :
1895 return "ctxEnumBody";
1896 case ctxFunctionBody :
1897 return "ctxFunctionBody";
1898 case ctxDisabledCode :
1899 return "ctxDisabledCode";
1900 case ctxMemInitList :
1901 return "ctxMemInitList";
1902 }
1903
1904 return "UNKNOWNCONTEXT";
1905}
1906
1907static YY_BUFFER_STATE gParseBuffer = nullptr;
1908void setupScanBuffer(char* buf, size_t bufsize)
1909{
1910 gParseBuffer = yy_scan_buffer(buf, bufsize);
1911 g = LexerData();
1912 g.mInputBuffer = buf;
1913 g.mInputBufferSize = bufsize;
1914 BEGIN(ctxGeneral);
1915}
1916
1918{
1919 yy_delete_buffer(gParseBuffer);
1920 gParseBuffer = nullptr;
1921 g.mInputBuffer = nullptr;
1922 g.mInputBufferSize = 0;
1923
1924 g = LexerData();
1925}
static YY_BUFFER_STATE gParseBuffer
Definition: parser.l:1907
void setupScanBuffer(char *buf, size_t bufsize)
Definition: parser.l:1908
void cleanupScanBuffer()
Definition: parser.l:1917