From 77c63397e832a7ad5c618b1aed7fc5de25ff6e89 Mon Sep 17 00:00:00 2001 From: albert-github Date: Fri, 12 Feb 2021 18:02:11 +0100 Subject: Adding support for lex files Adding support for lex. The lex files consist of a mixture of lex specific structures, that are handled in the the lexcode.l and lexscanner.l, abd C code that is handled by the C parsers (hence the rules used are partly copied from scanner.l). Special attention has been paid to memberdef.cpp as the initial values should not be handled by the lex parsers but by the C parsers. --- Doxyfile | 4 +- doc/features.doc | 2 +- doc/starting.doc | 4 +- src/CMakeLists.txt | 6 + src/code.h | 1 + src/code.l | 14 +- src/config.xml | 3 +- src/context.cpp | 1 + src/defargs.l | 4 +- src/docsets.cpp | 1 + src/doxygen.cpp | 4 + src/lexcode.h | 57 +++ src/lexcode.l | 1223 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lexscanner.h | 43 ++ src/lexscanner.l | 938 ++++++++++++++++++++++++++++++++++++++++ src/memberdef.cpp | 11 +- src/pre.l | 275 ++++++------ src/scanner.l | 5 +- src/types.h | 3 +- src/util.cpp | 6 + 20 files changed, 2459 insertions(+), 146 deletions(-) create mode 100644 src/lexcode.h create mode 100644 src/lexcode.l create mode 100644 src/lexscanner.h create mode 100644 src/lexscanner.l diff --git a/Doxyfile b/Doxyfile index 44eb5b5..100347b 100644 --- a/Doxyfile +++ b/Doxyfile @@ -106,10 +106,12 @@ WARN_LOGFILE = warnings.log # Configuration options related to the input files #--------------------------------------------------------------------------- INPUT = src \ - vhdlparser + vhdlparser \ + xml INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.h \ *.cpp \ + *.l \ *.md RECURSIVE = NO EXCLUDE = diff --git a/doc/features.doc b/doc/features.doc index e746ac3..9c42d5b 100644 --- a/doc/features.doc +++ b/doc/features.doc @@ -28,7 +28,7 @@ output even from undocumented code.
  • Generates structured XML output for parsed sources, which can be used by external tools. -
  • Supports C/C++, Java, (Corba and Microsoft) Java, Python, VHDL, PHP +
  • Supports C/C++, Lex, Java, (Corba and Microsoft) Java, Python, VHDL, PHP IDL, C#, Fortran, Objective-C 2.0, and to some extent D sources.
  • Supports documentation of files, namespaces, packages, classes, structs, unions, templates, variables, functions, typedefs, enums and diff --git a/doc/starting.doc b/doc/starting.doc index ad34af3..44f2a92 100644 --- a/doc/starting.doc +++ b/doc/starting.doc @@ -37,7 +37,7 @@ tries to be complete): \section step0 Step 0: Check if doxygen supports your programming language First, assure that your programming language has a reasonable chance of being -recognized by doxygen. These languages are supported by default: C, C++, C#, +recognized by doxygen. These languages are supported by default: C, C++, Lex, C#, Objective-C, IDL, Java, VHDL, PHP, Python, Fortran and D. It is possible to configure certain file type extensions to use certain parsers: see the \ref cfg_extension_mapping "Configuration/ExtensionMappings" for details. @@ -120,7 +120,7 @@ Extension | Language | Extension | Language | Extension | Language .ixx |C / C++ | .php5 |PHP | .vhdl |VHDL .ipp |C / C++ | .inc |PHP | .ucf |VHDL .i++ |C / C++ | .phtml |PHP | .qsf |VHDL -.inl |C / C++ | .m |Objective-C |   |  +.inl |C / C++ | .m |Objective-C | .l |Lex .h |C / C++ | .M |Objective-C | .md |Markdown .H |C / C++ | .py |Python | .markdown |Markdown .hh |C / C++ | .pyw |Python | .ice |Slice diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c6af813..e85d8f2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -117,6 +117,8 @@ set(LEX_FILES scanner constexp xmlcode sqlcode + lexcode + lexscanner configimpl) # unfortunately ${LEX_FILES_H} and ${LEX_FILES_CPP} don't work in older versions of CMake (like 3.6.2) for add_library @@ -184,6 +186,8 @@ add_library(doxymain STATIC ${GENERATED_SRC}/doctokenizer.l.h ${GENERATED_SRC}/fortrancode.l.h ${GENERATED_SRC}/fortranscanner.l.h + ${GENERATED_SRC}/lexcode.l.h + ${GENERATED_SRC}/lexscanner.l.h ${GENERATED_SRC}/pre.l.h ${GENERATED_SRC}/pycode.l.h ${GENERATED_SRC}/pyscanner.l.h @@ -199,6 +203,8 @@ add_library(doxymain STATIC ${GENERATED_SRC}/doctokenizer.cpp ${GENERATED_SRC}/fortrancode.cpp ${GENERATED_SRC}/fortranscanner.cpp + ${GENERATED_SRC}/lexcode.cpp + ${GENERATED_SRC}/lexscanner.cpp ${GENERATED_SRC}/pre.cpp ${GENERATED_SRC}/pycode.cpp ${GENERATED_SRC}/pyscanner.cpp diff --git a/src/code.h b/src/code.h index 42265ad..ba24242 100644 --- a/src/code.h +++ b/src/code.h @@ -46,6 +46,7 @@ class CCodeParser : public CodeParserInterface bool collectXRefs=TRUE ); void resetCodeParserState(); + void setStartCodeLine(const bool inp); private: struct Private; std::unique_ptr p; diff --git a/src/code.l b/src/code.l index 233a4f0..083660b 100644 --- a/src/code.l +++ b/src/code.l @@ -98,6 +98,11 @@ struct codeYY_state QCString parmType; QCString parmName; + bool beginCodeLine = true; //!< signals whether or not we should with the first line + //!< write a start line code or not. Essential + //!< when this code parser is called from another + //!< code parser. + const char * inputString = 0; //!< the code fragment as text yy_size_t inputPosition = 0; //!< read offset during parsing int inputLines = 0; //!< number of line in the code fragment @@ -3788,6 +3793,12 @@ void CCodeParser::resetCodeParserState() yyextra->anchorCount = 0; } +void CCodeParser::setStartCodeLine(const bool inp) +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->beginCodeLine = inp; +} + void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const QCString &s, SrcLangExt lang,bool exBlock, const char *exName,FileDef *fd, int startLine,int endLine,bool inlineFragment, @@ -3862,7 +3873,8 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const } yyextra->includeCodeFragment = inlineFragment; //printf("** exBlock=%d exName=%s include=%d\n",exBlock,exName,inlineFragment); - startCodeLine(yyscanner); + + if (yyextra->beginCodeLine) startCodeLine(yyscanner); yyextra->type.resize(0); yyextra->name.resize(0); yyextra->args.resize(0); diff --git a/src/config.xml b/src/config.xml index d9b29aa..8526a2b 100644 --- a/src/config.xml +++ b/src/config.xml @@ -647,7 +647,7 @@ Go to the next section or return to the With this tag you can assign which parser to use for a given extension. Doxygen has a built-in mapping, but you can override or extend it using this tag. The format is ext=language, where \c ext is a file extension, and language is one of - the parsers supported by doxygen: IDL, Java, JavaScript, Csharp (C#), C, C++, D, PHP, + the parsers supported by doxygen: IDL, Java, JavaScript, Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: Fortran. In the later case the parser tries to guess whether the code is fixed or free @@ -1434,6 +1434,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn" + diff --git a/src/context.cpp b/src/context.cpp index d2cfa9e..e0017fb 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -1540,6 +1540,7 @@ class DefinitionContext case SrcLangExt_SQL: result="sql"; break; case SrcLangExt_Markdown: result="markdown"; break; case SrcLangExt_Slice: result="slice"; break; + case SrcLangExt_Lex: result="lex"; break; } return result; } diff --git a/src/defargs.l b/src/defargs.l index e25c1fe..76d07ec 100644 --- a/src/defargs.l +++ b/src/defargs.l @@ -27,12 +27,12 @@ * The Argument list as a whole can be pure, constant or volatile. * * Examples of input strings are: - * \code + * \verbatim * "(int a,int b) const" * "(const char *s="hello world",int=5) = 0" * "" * "(char c,const char)" - * \endcode + * \endverbatim * * Note: It is not always possible to distinguish between the name and * type of an argument. In case of doubt the name is added to the diff --git a/src/docsets.cpp b/src/docsets.cpp index 4f04623..9c29818 100644 --- a/src/docsets.cpp +++ b/src/docsets.cpp @@ -328,6 +328,7 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, case SrcLangExt_SQL: lang="sql"; break; // Sql case SrcLangExt_Markdown:lang="markdown"; break; // Markdown case SrcLangExt_Slice: lang="slice"; break; // Slice + case SrcLangExt_Lex: lang="lex"; break; // Lex case SrcLangExt_Unknown: lang="unknown"; break; // should not happen! } diff --git a/src/doxygen.cpp b/src/doxygen.cpp index f5a280b..c268f26 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -77,6 +77,8 @@ #include "fortranscanner.h" #include "xmlcode.h" #include "sqlcode.h" +#include "lexcode.h" +#include "lexscanner.h" #include "code.h" #include "portable.h" #include "vhdljjparser.h" @@ -10058,6 +10060,8 @@ void initDoxygen() make_parser_factory()); Doxygen::parserManager->registerParser("md", make_parser_factory(), make_parser_factory()); + Doxygen::parserManager->registerParser("lex", make_parser_factory(), + make_parser_factory()); // register any additional parsers here... diff --git a/src/lexcode.h b/src/lexcode.h new file mode 100644 index 0000000..38aec50 --- /dev/null +++ b/src/lexcode.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2021 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + + +#ifndef LEXCODE_H +#define LEXCODE_H + +#include "parserintf.h" + +class CodeOutputInterface; +class FileDef; +class MemberDef; +class QCString; +class Definition; + +/** LEX code scanner. + */ +class LexCodeParser : public CodeParserInterface +{ + public: + LexCodeParser(); + virtual ~LexCodeParser(); + void parseCode(CodeOutputInterface &codeOutIntf, + const char *scopeName, + const QCString &input, + SrcLangExt, + bool isExampleBlock, + const char *exampleName=0, + FileDef *fileDef=0, + int startLine=-1, + int endLine=-1, + bool inlineFragment=FALSE, + const MemberDef *memberDef=0, + bool showLineNumbers=TRUE, + const Definition *searchCtx=0, + bool collectXRefs=TRUE + ); + void resetCodeParserState(); + private: + struct Private; + std::unique_ptr p; +}; + + +#endif diff --git a/src/lexcode.l b/src/lexcode.l new file mode 100644 index 0000000..d6b41b0 --- /dev/null +++ b/src/lexcode.l @@ -0,0 +1,1223 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2021 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +%option never-interactive +%option prefix="lexcodeYY" +%option noyywrap +%option reentrant +%option extra-type="struct lexcodeYY_state *" +%top{ +#include +} + +%{ + +#include + +#include "config.h" +#include "doxygen.h" +#include "outputgen.h" +#include "code.h" +#include "lexcode.h" +#include "filedef.h" +#include "message.h" + +#define YY_NEVER_INTERACTIVE 1 +#define YY_NO_INPUT 1 +#define YY_NO_UNISTD_H 1 + +#define USE_STATE2STRING 0 + +struct lexcodeYY_state +{ + CodeOutputInterface * code; + CCodeParser ccodeParser; + const char *inputString; //!< the code fragment as text + yy_size_t inputPosition; //!< read offset during parsing + int inputLines; //!< number of line in the code fragment + int yyLineNr; //!< current line number + bool needsTermination; + + bool lineNumbers = FALSE; + const Definition *searchCtx; + bool collectXRefs = FALSE; + + int lastContext = 0; + int lastCContext = 0; + int lastStringContext = 0; + int docBlockContext = 0; + int lastPreLineCtrlContext = 0; + int lastRawStringContext = 0; + int curlyCount = 0; + + QCString rulesPatternBuffer; + QCString CCodeBuffer; + int startCCodeLine = -1; + int roundCount = 0; + int squareCount = 0; + bool insideCode = FALSE; + QCString delimiter; + QCString docBlockName; + uint fencedSize = 0; + bool nestedComment = false; + + bool exampleBlock; + QCString exampleName; + QCString classScope; + + FileDef *sourceFileDef; + const Definition *currentDefinition; + const MemberDef *currentMemberDef; + bool includeCodeFragment; + const char *currentFontClass; +}; + +#if USE_STATE2STRING +static const char *stateToString(int state); +#endif + +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor); +static void startCodeLine(yyscan_t yyscanner); +static void endFontClass(yyscan_t yyscanner); +static void endCodeLine(yyscan_t yyscanner); +static void nextCodeLine(yyscan_t yyscanner); +static void codifyLines(yyscan_t yyscanner,const char *text); +static void startFontClass(yyscan_t yyscanner,const char *s); +static int countLines(yyscan_t yyscanner); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); +static void lineCount(yyscan_t yyscanner); +static void handleCCode(yyscan_t yyscanner); + +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); + +%} + +nl (\r\n|\r|\n) +ws [ \t] +nws [^ \t\n] +TopStart "%top{"{nl} +TopEnd "}"{nl} +LiteralStart "%{"{nl} +LiteralEnd "%}"{nl} +RulesStart "%%"{nl} +RulesEnd "%%"{nl} +RulesSharp "<"[^>]*">" +RulesCurly "{"[^{}\n]*"}" +StartSquare "[" +StartDouble "\"" +StartRound "(" +EscapeRulesCharOpen "\\["|"\\<"|"\\{"|"\\("|"\\\""|"\\{"|"\\ " +EscapeRulesCharClose "\\]"|"\\>"|"\\}"|"\\)" +EscapeRulesChar {EscapeRulesCharOpen}|{EscapeRulesCharClose} + +CMD ("\\"|"@") +BN [ \t\n\r] +BL [ \t\r]*"\n" +B [ \t] +ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* +PRE [pP][rR][eE] +CODE [cC][oO][dD][eE] +RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"(" +RAWEND ")"[^ \t\(\)\\]{0,16}\" +CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) + +%x DefSection +%x DefSectionLine +%x RulesSectionInit +%x RulesPattern +%x RulesDouble +%x RulesRoundDouble +%x RulesSquare +%x RulesRoundSquare +%x RulesRound +%x UserSection + +%x TopSection +%x LiteralSection + +%x COMMENT + +%x SkipCurly +%x SkipCurlyEndDoc +%x PreLineCtrl +%x DocLine +%x DocBlock +%x DocCopyBlock +%x SkipString +%x RawString +%x SkipComment +%x SkipCxxComment +%x Comment + +%% + +<*>\x0d +^{TopStart} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->lastContext = YY_START; + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN (TopSection); + } +^{LiteralStart} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->lastContext = YY_START; + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN (LiteralSection); + } +^{TopEnd} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + BEGIN( yyextra->lastContext ) ; + } +.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +^{LiteralEnd} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + BEGIN( yyextra->lastContext ) ; + } +.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +"//".*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +^{ws}*"/*" { + yyextra->CCodeBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(COMMENT); + } +"*/"{ws}*{nl} { + yyextra->CCodeBuffer+=yytext; + yyextra->yyLineNr++; + handleCCode(yyscanner); + BEGIN(yyextra->lastContext); + } +"*/" { + yyextra->CCodeBuffer+=yytext; + handleCCode(yyscanner); + BEGIN(yyextra->lastContext); + } +[^*\n]+ { + yyextra->CCodeBuffer += yytext; + } +"//"|"/*" { + yyextra->CCodeBuffer += yytext; + } +{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +. { + yyextra->CCodeBuffer += yytext; + } +^{nl} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + } +^{ws}.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +^{RulesStart} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN (RulesSectionInit); + } +^{nws} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + BEGIN(DefSectionLine); + } +.*{nl} { + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN(DefSection); + } +^{RulesEnd} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN (UserSection); + } +^{nws} { + handleCCode(yyscanner); + unput(*yytext); + BEGIN(RulesPattern); + } +{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +^{ws}.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +"<>" { + yyextra->rulesPatternBuffer += yytext; + } +{EscapeRulesChar} { + yyextra->rulesPatternBuffer += yytext; + } +{RulesSharp} { + yyextra->rulesPatternBuffer += yytext; + } +{RulesCurly} { + yyextra->rulesPatternBuffer += yytext; + } +{StartDouble} { + yyextra->rulesPatternBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(RulesDouble); + } +"\\\\" { + yyextra->rulesPatternBuffer += yytext; + } +"\\\"" { + yyextra->rulesPatternBuffer += yytext; + } +"\"" { + yyextra->rulesPatternBuffer += yytext; + BEGIN( yyextra->lastContext ) ; + } +"\"" { + yyextra->rulesPatternBuffer += yytext; + BEGIN(RulesRound) ; + } +. { + yyextra->rulesPatternBuffer += yytext; + } +{StartSquare} { + yyextra->squareCount++; + yyextra->rulesPatternBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(RulesSquare); + } +"\\[" | +"\\]" { + yyextra->rulesPatternBuffer += yytext; + } +"[" { + yyextra->squareCount++; + yyextra->rulesPatternBuffer += yytext; + } +"]" { + yyextra->squareCount--; + yyextra->rulesPatternBuffer += yytext; + if (!yyextra->squareCount) BEGIN(RulesPattern) ; + } +"]" { + yyextra->squareCount--; + yyextra->rulesPatternBuffer += yytext; + if (!yyextra->squareCount) BEGIN(RulesRound) ; + } +"\\\\" { + yyextra->rulesPatternBuffer += yytext; + } +. { + yyextra->rulesPatternBuffer += yytext; + } +{StartRound} { + yyextra->roundCount++; + yyextra->rulesPatternBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(RulesRound); + } +{RulesCurly} { + yyextra->rulesPatternBuffer += yytext; + } +{StartSquare} { + yyextra->squareCount++; + yyextra->rulesPatternBuffer += yytext; + BEGIN(RulesRoundSquare); + } +{StartDouble} { + yyextra->rulesPatternBuffer += yytext; + BEGIN(RulesRoundDouble); + } +"\\(" | +"\\)" { + yyextra->rulesPatternBuffer += yytext; + } +"(" { + yyextra->roundCount++; + yyextra->rulesPatternBuffer += yytext; + } +")" { + yyextra->roundCount--; + yyextra->rulesPatternBuffer += yytext; + if (!yyextra->roundCount) BEGIN( yyextra->lastContext ) ; + } +. { + yyextra->rulesPatternBuffer += yytext; + } +{ws}+"|" { + if (!yyextra->rulesPatternBuffer.isEmpty()) + { + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yyextra->rulesPatternBuffer.data()); + yyextra->rulesPatternBuffer.resize(0); + endFontClass(yyscanner); + } + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + yyextra->curlyCount = 0; + BEGIN(SkipCurly); + } +^{ws}*{nl} { + codifyLines(yyscanner,"\n"); + } +^{ws}+ { + codifyLines(yyscanner,yytext); + } +({ws}|{nl}) { + unput(*yytext); + if (!yyextra->rulesPatternBuffer.isEmpty()) + { + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yyextra->rulesPatternBuffer.data()); + yyextra->rulesPatternBuffer.resize(0); + endFontClass(yyscanner); + } + yyextra->startCCodeLine=yyextra->yyLineNr; + yyextra->curlyCount = 0; + BEGIN(SkipCurly); + } +"\\\\" { + yyextra->rulesPatternBuffer += yytext; + } +"/*" { + if (!yyextra->rulesPatternBuffer.isEmpty()) + { + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yyextra->rulesPatternBuffer.data()); + yyextra->rulesPatternBuffer.resize(0); + endFontClass(yyscanner); + } + yyextra->CCodeBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(COMMENT); + } +. { + yyextra->rulesPatternBuffer += yytext; + } +{B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */ + yyextra->CCodeBuffer += yytext; + yyextra->lastPreLineCtrlContext = YY_START; + BEGIN( PreLineCtrl ); + } +"\""[^\n\"]*"\"" { + yyextra->CCodeBuffer += yytext; + } +. { + yyextra->CCodeBuffer += yytext; + } +\n { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + BEGIN( yyextra->lastPreLineCtrlContext ); + } +"{" { + yyextra->CCodeBuffer += yytext; + ++yyextra->curlyCount ; + } +"}"/{BN}*("/*!"|"/**"|"//!"|"///")"