diff options
author | Dimitri van Heesch <doxygen@gmail.com> | 2021-03-03 19:14:50 (GMT) |
---|---|---|
committer | Dimitri van Heesch <doxygen@gmail.com> | 2021-03-03 19:14:50 (GMT) |
commit | 93f5398050245c427869d865fe04c43c907666d1 (patch) | |
tree | 4c936747cc3d3029c945a0227f7b45e0dbe07dfe /src | |
parent | cc78ebc6ad3d24d25ac779eeed9fb5fa3c89ee27 (diff) | |
parent | 13a1e0111d210d6688495806af1805997541e9c2 (diff) | |
download | Doxygen-93f5398050245c427869d865fe04c43c907666d1.zip Doxygen-93f5398050245c427869d865fe04c43c907666d1.tar.gz Doxygen-93f5398050245c427869d865fe04c43c907666d1.tar.bz2 |
Merge branch 'albert-github-feature/bug_lex'
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/code.h | 1 | ||||
-rw-r--r-- | src/code.l | 92 | ||||
-rw-r--r-- | src/commentcnv.l | 85 | ||||
-rw-r--r-- | src/commentscan.l | 29 | ||||
-rw-r--r-- | src/config.xml | 3 | ||||
-rw-r--r-- | src/context.cpp | 1 | ||||
-rw-r--r-- | src/declinfo.l | 5 | ||||
-rw-r--r-- | src/defargs.l | 22 | ||||
-rw-r--r-- | src/docsets.cpp | 1 | ||||
-rw-r--r-- | src/doctokenizer.l | 7 | ||||
-rw-r--r-- | src/doxygen.cpp | 4 | ||||
-rw-r--r-- | src/fortrancode.l | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | src/fortranscanner.l | 3 | ||||
-rw-r--r-- | src/lexcode.h | 57 | ||||
-rw-r--r-- | src/lexcode.l | 1240 | ||||
-rw-r--r-- | src/lexscanner.h | 43 | ||||
-rw-r--r-- | src/lexscanner.l | 955 | ||||
-rw-r--r-- | src/memberdef.cpp | 11 | ||||
-rw-r--r-- | src/pre.l | 337 | ||||
-rw-r--r-- | src/pycode.l | 2 | ||||
-rw-r--r-- | src/scanner.l | 185 | ||||
-rw-r--r-- | src/sqlcode.l | 2 | ||||
-rw-r--r-- | src/types.h | 21 | ||||
-rw-r--r-- | src/util.cpp | 6 |
25 files changed, 2781 insertions, 344 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4488067..7b421f6 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 @@ -46,6 +46,7 @@ class CCodeParser : public CodeParserInterface bool collectXRefs=TRUE ); void resetCodeParserState(); + void setStartCodeLine(const bool inp); private: struct Private; std::unique_ptr<Private> p; @@ -97,6 +97,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 @@ -255,6 +260,7 @@ static std::mutex g_countFlowKeywordsMutex; %} B [ \t] +Bopt {B}* BN [ \t\n\r] ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* SEP ("::"|"\\") @@ -278,6 +284,8 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"(" RAWEND ")"[^ \t\(\)\\]{0,16}\" + /* no comment start / end signs inside square brackets */ +NCOMM [^/\*] //- start: NUMBER ------------------------------------------------------------------------- // Note same defines in commentcnv.l: keep in sync DECIMAL_INTEGER [1-9][0-9']*[0-9]?[uU]?[lL]?[lL]? @@ -306,6 +314,18 @@ FLOAT_NUMBER {FLOAT_DECIMAL}|{FLOAT_HEXADECIMAL} NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} //- end: NUMBER --------------------------------------------------------------------------- + // C start comment +CCS "/\*" + // C end comment +CCE "*\/" + // Cpp comment +CPPC "/\/" + + // ENDIDopt +ENDIDopt ("::"{ID})* + // Optional end qualifiers +ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"sealed"|"override"))* + %option noyywrap %x SkipString @@ -534,7 +554,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <SkipCPP>\\[\r]?\n { codifyLines(yyscanner,yytext); } -<SkipCPP>"//"/[^/!] { +<SkipCPP>{CPPC}/[^/!] { REJECT; } <Body,FuncCall>"{" { @@ -738,7 +758,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN( Bases ); } <PackageName>[ \t]*";" | -<Bases>^{B}*/"@"{ID} | // Objective-C interface +<Bases>^{Bopt}/"@"{ID} | // Objective-C interface <Bases,ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*"{"{B}* { yyextra->theVarContext.pushScope(); yyextra->code->codify(yytext); @@ -858,7 +878,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} } -<Body>{SCOPEPREFIX}?"operator"{B}*"()"{B}*/"(" { +<Body>{SCOPEPREFIX}?"operator"{B}*"()"{Bopt}/"(" { addType(yyscanner); generateFunctionLink(yyscanner,*yyextra->code,yytext); yyextra->bracketCount=0; @@ -1089,7 +1109,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} generatePHPVariableLink(yyscanner,*yyextra->code,yytext); yyextra->name+=yytext+7; } -<Body,TemplCast>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>\(]*">"("::"{ID})*/{B}* { // A<T> *pt; +<Body,TemplCast>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>\(]*">"{ENDIDopt}/{B}* { // A<T> *pt; if (isCastKeyword(yytext) && YY_START==Body) { REJECT; @@ -1167,7 +1187,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <SkipStringS>[^\'\\\r\n]* { yyextra->code->codify(yytext); } -<SkipString,SkipStringS>"//"|"/*" { +<SkipString,SkipStringS>{CPPC}|{CCS} { yyextra->code->codify(yytext); } <SkipString>@?\" { @@ -1412,21 +1432,21 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} } DBG_CTX((stderr,"close\n")); } -<ObjCCall,ObjCMName>"//".* { +<ObjCCall,ObjCMName>{CPPC}.* { yyextra->currentCtx->format+=escapeComment(yyscanner,yytext); } -<ObjCCall,ObjCMName>"/*" { +<ObjCCall,ObjCMName>{CCS} { yyextra->lastObjCCallContext = YY_START; yyextra->currentCtx->comment=yytext; BEGIN(ObjCCallComment); } -<ObjCCallComment>"*/" { +<ObjCCallComment>{CCE} { yyextra->currentCtx->comment+=yytext; yyextra->currentCtx->format+=escapeComment(yyscanner,yyextra->currentCtx->comment); BEGIN(yyextra->lastObjCCallContext); } <ObjCCallComment>[^*\n]+ { yyextra->currentCtx->comment+=yytext; } -<ObjCCallComment>"//"|"/*" { yyextra->currentCtx->comment+=yytext; } +<ObjCCallComment>{CPPC}|{CCS} { yyextra->currentCtx->comment+=yytext; } <ObjCCallComment>\n { yyextra->currentCtx->comment+=*yytext; } <ObjCCallComment>. { yyextra->currentCtx->comment+=*yytext; } <ObjCCall>{ID} { @@ -1667,7 +1687,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN( SkipInits ); } } -<CallEnd>("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"sealed"|"override"))*/{BN}*(";"|"="|"throw"{BN}*"(") { +<CallEnd>{ENDQopt}/{BN}*(";"|"="|"throw"{BN}*"(") { startFontClass(yyscanner,"keyword"); codifyLines(yyscanner,yytext); endFontClass(yyscanner); @@ -1847,18 +1867,18 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->memCallContext = YY_START; BEGIN( MemberCall ); } -<SkipComment>"/*"("!"?)"*/" { +<SkipComment>{CCS}("!"?){CCE} { yyextra->code->codify(yytext); endFontClass(yyscanner); BEGIN( yyextra->lastCContext ) ; } -<SkipComment>"//"|"/*" { +<SkipComment>{CPPC}|{CCS} { yyextra->code->codify(yytext); } -<SkipComment>[^*/\n]+ { +<SkipComment>[^*\/\n]+ { yyextra->code->codify(yytext); } -<SkipComment>[ \t]*"*/" { +<SkipComment>[ \t]*{CCE} { yyextra->code->codify(yytext); endFontClass(yyscanner); if (yyextra->lastCContext==SkipCPP) @@ -1882,10 +1902,10 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <SkipCxxComment>. { yyextra->code->codify(yytext); } -<RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)?{B}*"/*"[*!]/[^/*] { +<RemoveSpecialCComment>{CCE}{B}*\n({B}*\n)*({B}*(({CPPC}"@"[{}])|({CCS}"@"[{}]{CCE})){B}*\n)?{B}*{CCS}[*!]/{NCOMM} { yyextra->yyLineNr+=QCString(yytext).contains('\n'); } -<RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)? { +<RemoveSpecialCComment>{CCE}{B}*\n({B}*\n)*({B}*(({CPPC}"@"[{}])|({CCS}"@"[{}]{CCE})){B}*\n)? { if (yyextra->lastSpecialCContext==SkipCxxComment) { // force end of C++ comment here yyextra->yyLineNr+=QCString(yytext).contains('\n'); @@ -1908,11 +1928,11 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN(yyextra->lastSpecialCContext); } } -<RemoveSpecialCComment>"*/" { +<RemoveSpecialCComment>{CCE} { BEGIN(yyextra->lastSpecialCContext); } <RemoveSpecialCComment>[^*\n]+ -<RemoveSpecialCComment>"//"|"/*" +<RemoveSpecialCComment>{CPPC}|{CCS} <RemoveSpecialCComment>\n { yyextra->yyLineNr++; } <RemoveSpecialCComment>. <MemberCall>[^a-z_A-Z0-9(\n] { @@ -1921,7 +1941,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->name.resize(0); BEGIN(yyextra->memCallContext); } -<*>\n({B}*"//"[!/][^\n]*\n)+ { // remove special one-line comment +<*>\n({B}*{CPPC}[!/][^\n]*\n)+ { // remove special one-line comment if (YY_START==SkipCPP) REJECT; if (Config_getBool(STRIP_CODE_COMMENTS)) { @@ -1945,7 +1965,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN( yyextra->lastSkipCppContext ) ; unput('\n'); } -<*>\n{B}*"//@"[{}].*\n { // remove one-line group marker +<*>\n{B}*{CPPC}"@"[{}].*\n { // remove one-line group marker if (Config_getBool(STRIP_CODE_COMMENTS)) { yyextra->yyLineNr+=2; @@ -1963,7 +1983,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN( yyextra->lastCContext ) ; } } -<*>\n{B}*"/*@"[{}] { // remove one-line group marker +<*>\n{B}*{CCS}"@"[{}] { // remove one-line group marker if (Config_getBool(STRIP_CODE_COMMENTS)) { if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; @@ -1982,7 +2002,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN(SkipComment); } } -<*>^{B}*"//@"[{}].*\n { // remove one-line group marker +<*>^{B}*{CPPC}"@"[{}].*\n { // remove one-line group marker if (Config_getBool(STRIP_CODE_COMMENTS)) { yyextra->yyLineNr++; @@ -1995,7 +2015,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} endFontClass(yyscanner); } } -<*>^{B}*"/*@"[{}] { // remove multi-line group marker +<*>^{B}*{CCS}"@"[{}] { // remove multi-line group marker if (Config_getBool(STRIP_CODE_COMMENTS)) { if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; @@ -2013,7 +2033,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN(SkipComment); } } -<*>^{B}*"//"[!/][^\n]* { // remove special one-line comment +<*>^{B}*{CPPC}[!/][^\n]* { // remove special one-line comment if (!Config_getBool(STRIP_CODE_COMMENTS)) { startFontClass(yyscanner,"comment"); @@ -2021,7 +2041,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} endFontClass(yyscanner); } } -<*>"//"[!/][^\n]* { // strip special one-line comment +<*>{CPPC}[!/][^\n]* { // strip special one-line comment if (YY_START==SkipComment || YY_START==SkipString) REJECT; if (!Config_getBool(STRIP_CODE_COMMENTS)) { @@ -2030,7 +2050,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} endFontClass(yyscanner); } } -<*>\n{B}*"/*"[!*]/[^/*] { +<*>\n{B}*{CCS}[!*]/{NCOMM} { if (Config_getBool(STRIP_CODE_COMMENTS)) { if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; @@ -2049,7 +2069,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN(SkipComment); } } -<*>^{B}*"/**"[*]+/[^/] { // special C "banner" comment block at a new line +<*>^{B}*{CCS}"*"[*]+/[^/] { // special C "banner" comment block at a new line if (Config_getBool(JAVADOC_BANNER) && Config_getBool(STRIP_CODE_COMMENTS)) { if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; @@ -2067,7 +2087,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN(SkipComment); } } -<*>^{B}*"/*"[!*]/[^/*] { // special C comment block at a new line +<*>^{B}*{CCS}[!*]/{NCOMM} { // special C comment block at a new line if (Config_getBool(STRIP_CODE_COMMENTS)) { if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; @@ -2085,7 +2105,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN(SkipComment); } } -<*>"/*"[!*]/[^/*] { // special C comment block half way a line +<*>{CCS}[!*]/{NCOMM} { // special C comment block half way a line if (YY_START==SkipString) REJECT; if (Config_getBool(STRIP_CODE_COMMENTS)) { @@ -2104,7 +2124,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN(SkipComment); } } -<*>"/*"("!"?)"*/" { +<*>{CCS}("!"?){CCE} { if (YY_START==SkipString) REJECT; if (!Config_getBool(STRIP_CODE_COMMENTS)) { @@ -2116,7 +2136,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <SkipComment>[^\*\n]+ { yyextra->code->codify(yytext); } -<*>"/*" { +<*>{CCS} { startFontClass(yyscanner,"comment"); yyextra->code->codify(yytext); // check is to prevent getting stuck in skipping C++ comments @@ -2132,7 +2152,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->lastVerbStringContext=YY_START; BEGIN(SkipVerbString); } -<*>"//" { +<*>{CPPC} { startFontClass(yyscanner,"comment"); yyextra->code->codify(yytext); yyextra->lastCContext = YY_START ; @@ -3785,6 +3805,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, @@ -3859,7 +3885,7 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const } yyextra->includeCodeFragment = inlineFragment; DBG_CTX((stderr,"** 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/commentcnv.l b/src/commentcnv.l index 7a3cda5..d3b5362 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -170,6 +170,23 @@ FLOAT_NUMBER {FLOAT_DECIMAL}|{FLOAT_HEXADECIMAL} NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} //- end: NUMBER --------------------------------------------------------------------------- + // C start comment +CCS "/\*" + // C end comment +CCE "*\/" + // Cpp comment +CPPC "/\/" + + // Optional any character +ANYopt .* + + // Optional white space +WSopt [ \t\r]* + // readline non special +RLopt [^\\@\n\*\/]* + // Optional slash +SLASHopt [/]* + %% <Scan>{NUMBER} { //Note similar code in code.l @@ -276,8 +293,8 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <Scan>\n { /* new line */ copyToOutput(yyscanner,yytext,(int)yyleng); } -<Scan>"//!"/.*\n[ \t]*"//"[\/!][^\/] | /* start C++ style special comment block */ -<Scan>("///"[/]*)/[^/].*\n[ \t]*"//"[\/!][^\/] { /* start C++ style special comment block */ +<Scan>{CPPC}"!"/.*\n[ \t]*{CPPC}[\/!][^\/] | /* start C++ style special comment block */ +<Scan>({CPPC}"/"[/]*)/[^/].*\n[ \t]*{CPPC}[\/!][^\/] { /* start C++ style special comment block */ if (yyextra->mlBrief) { REJECT; // bail out if we do not need to convert @@ -298,7 +315,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN(ReadLine); } } -<Scan>"//##Documentation".*/\n { /* Start of Rational Rose ANSI C++ comment block */ +<Scan>{CPPC}"##Documentation"{ANYopt}/\n { /* Start of Rational Rose ANSI C++ comment block */ if (yyextra->mlBrief) REJECT; int i=17; //=strlen("//##Documentation"); yyextra->blockHeadCol=yyextra->col; @@ -307,22 +324,22 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->inRoseComment=TRUE; BEGIN(SComment); } -<Scan>"//"[!\/]/.*\n[ \t]*"//"[|\/][ \t]*[@\\]"}" { // next line contains an end marker, see bug 752712 +<Scan>{CPPC}[!\/]/.*\n[ \t]*{CPPC}[|\/][ \t]*[@\\]"}" { // next line contains an end marker, see bug 752712 yyextra->inSpecialComment=yytext[2]=='/' || yytext[2]=='!'; copyToOutput(yyscanner,yytext,(int)yyleng); yyextra->readLineCtx=YY_START; BEGIN(ReadLine); } -<Scan>"//"/.*\n { /* one line C++ comment */ +<Scan>{CPPC}/.*\n { /* one line C++ comment */ yyextra->inSpecialComment=yytext[2]=='/' || yytext[2]=='!'; copyToOutput(yyscanner,yytext,(int)yyleng); yyextra->readLineCtx=YY_START; BEGIN(ReadLine); } -<Scan>"/**/" { /* avoid matching next rule for empty C comment, see bug 711723 */ +<Scan>{CCS}{CCE} { /* avoid matching next rule for empty C comment, see bug 711723 */ copyToOutput(yyscanner,yytext,(int)yyleng); } -<Scan>"/*"[*!]? { /* start of a C comment */ +<Scan>{CCS}[*!]? { /* start of a C comment */ if (yyextra->lang==SrcLangExt_Python) { REJECT; @@ -443,8 +460,14 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->lastCommentContext = YY_START; BEGIN(Verbatim); } +<Scan>"\\\"" { /* escaped double quote */ + copyToOutput(yyscanner,yytext,(int)yyleng); + } +<Scan>"\\\\" { /* escaped backslash */ + copyToOutput(yyscanner,yytext,(int)yyleng); + } <Scan>. { /* any other character */ - copyToOutput(yyscanner,yytext,(int)yyleng); + copyToOutput(yyscanner,yytext,(int)yyleng); } <Verbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}") { /* end of verbatim block */ copyToOutput(yyscanner,yytext,(int)yyleng); @@ -501,7 +524,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN(yyextra->lastCommentContext); } } -<VerbatimCode>^[ \t]*"//"[\!\/]? { /* skip leading comments */ +<VerbatimCode>^[ \t]*{CPPC}[\!\/]? { /* skip leading comments */ if (!yyextra->inSpecialComment) { copyToOutput(yyscanner,yytext,(int)yyleng); @@ -530,7 +553,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <Verbatim,VerbatimCode>\n { /* new line in verbatim block */ copyToOutput(yyscanner,yytext,(int)yyleng); } -<Verbatim>^[ \t]*"//"[/!] { +<Verbatim>^[ \t]*{CPPC}[/!] { if (yyextra->blockName=="dot" || yyextra->blockName=="msc" || yyextra->blockName=="uml" || yyextra->blockName.at(0)=='f') { // see bug 487871, strip /// from dot images and formulas. @@ -596,7 +619,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <CComment>[^ `~<\\!@*\n{\"\/]* { /* anything that is not a '*' or command */ copyToOutput(yyscanner,yytext,(int)yyleng); } -<CComment>"*"+[^*/\\@\n{\"]* { /* stars without slashes */ +<CComment>"*"+[^*\/\\@\n{\"]* { /* stars without slashes */ copyToOutput(yyscanner,yytext,(int)yyleng); } <CComment>"\"\"\"" { /* end of Python docstring */ @@ -728,18 +751,18 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <CComment>. { copyToOutput(yyscanner,yytext,(int)yyleng); } -<SComment>^[ \t]*"///"[\/]*/\n { +<SComment>^[ \t]*{CPPC}"/"{SLASHopt}/\n { replaceComment(yyscanner,0); } -<SComment>\n[ \t]*"///"[\/]*/\n { +<SComment>\n[ \t]*{CPPC}"/"{SLASHopt}/\n { replaceComment(yyscanner,1); } -<SComment>^[ \t]*"///"[^\/\n]/.*\n { +<SComment>^[ \t]*{CPPC}"/"[^\/\n]/.*\n { replaceComment(yyscanner,0); yyextra->readLineCtx=YY_START; BEGIN(ReadLine); } -<SComment>\n[ \t]*"//"[\/!]("<")?[ \t]*[\\@]"}".*\n { +<SComment>\n[ \t]*{CPPC}[\/!]("<")?[ \t]*[\\@]"}".*\n { /* See Bug 752712: end the multiline comment when finding a @} or \} command */ copyToOutput(yyscanner," */",3); copyToOutput(yyscanner,yytext,(int)yyleng); @@ -747,26 +770,26 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->inRoseComment=FALSE; BEGIN(Scan); } -<SComment>\n[ \t]*"///"[^\/\n]/.*\n { +<SComment>\n[ \t]*{CPPC}"/"[^\/\n]/.*\n { replaceComment(yyscanner,1); yyextra->readLineCtx=YY_START; BEGIN(ReadLine); } -<SComment>^[ \t]*"//!" | // just //! -<SComment>^[ \t]*"//!<"/.*\n | // or //!< something -<SComment>^[ \t]*"//!"[^<]/.*\n { // or //!something +<SComment>^[ \t]*{CPPC}"!" | // just //! +<SComment>^[ \t]*{CPPC}"!<"/.*\n | // or //!< something +<SComment>^[ \t]*{CPPC}"!"[^<]/.*\n { // or //!something replaceComment(yyscanner,0); yyextra->readLineCtx=YY_START; BEGIN(ReadLine); } -<SComment>\n[ \t]*"//!" | -<SComment>\n[ \t]*"//!<"/.*\n | -<SComment>\n[ \t]*"//!"[^<\n]/.*\n { +<SComment>\n[ \t]*{CPPC}"!" | +<SComment>\n[ \t]*{CPPC}"!<"/.*\n | +<SComment>\n[ \t]*{CPPC}"!"[^<\n]/.*\n { replaceComment(yyscanner,1); yyextra->readLineCtx=YY_START; BEGIN(ReadLine); } -<SComment>^[ \t]*"//##"/.*\n { +<SComment>^[ \t]*{CPPC}"##"/.*\n { if (!yyextra->inRoseComment) { REJECT; @@ -778,7 +801,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN(ReadLine); } } -<SComment>\n[ \t]*"//##"/.*\n { +<SComment>\n[ \t]*{CPPC}"##"/.*\n { if (!yyextra->inRoseComment) { REJECT; @@ -797,19 +820,19 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->inRoseComment=FALSE; BEGIN(Scan); } -<ReadLine>"/**" { +<ReadLine>{CCS}"*" { copyToOutput(yyscanner,"/‍**",8); } -<ReadLine>"*/" { +<ReadLine>{CCE} { copyToOutput(yyscanner,"*‍/",7); } <ReadLine>"*" { copyToOutput(yyscanner,yytext,(int)yyleng); } -<ReadLine>[^\\@\n\*/]* { +<ReadLine>{RLopt} { copyToOutput(yyscanner,yytext,(int)yyleng); } -<ReadLine>[^\\@\n\*/]*/\n { +<ReadLine>{RLopt}/\n { copyToOutput(yyscanner,yytext,(int)yyleng); BEGIN(yyextra->readLineCtx); } @@ -843,7 +866,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <CondLine>[!()&| \ta-z_A-Z0-9.\-]+ { handleCondSectionId(yyscanner,yytext); } -<CComment,ReadLine>[\\@]"cond"[ \t\r]*/\n { +<CComment,ReadLine>[\\@]"cond"{WSopt}/\n { yyextra->condCtx=YY_START; handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally } @@ -861,9 +884,9 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->lastEscaped=0; BEGIN( ReadAliasArgs ); } -<ReadAliasArgs>^[ \t]*"//"[/!]/[^\n]+ { // skip leading special comments (see bug 618079) +<ReadAliasArgs>^[ \t]*{CPPC}[/!]/[^\n]+ { // skip leading special comments (see bug 618079) } -<ReadAliasArgs>"*/" { // oops, end of comment in the middle of an alias? +<ReadAliasArgs>{CCE} { // oops, end of comment in the middle of an alias? if (yyextra->lang==SrcLangExt_Python) { REJECT; diff --git a/src/commentscan.l b/src/commentscan.l index faaa1fc..c17d9f6 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -469,7 +469,8 @@ DETAILEDHTMLOPT {CODE} BN [ \t\n\r] BL [ \t\r]*"\n" B [ \t] -BS ^(({B}*"//")?)(({B}*"*"+)?){B}* +Bopt {B}* +BS ^(({B}*"/""/")?)(({B}*"*"+)?){B}* ATTR ({B}+[^>\n]*)? DOCNL "\n"|"\\ilinebr" LC "\\"{B}*"\n" @@ -488,6 +489,18 @@ TMPLSPEC "<"{BN}*[^>]+{BN}*">" MAILADDR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ RCSTAG "$"{ID}":"[^\n$]+"$" + // C start comment +CCS "/\*" + // C end comment +CCE "*\/" + // Cpp comment +CPPC "/\/" + + // end of section title with asterisk +STAopt [^\n@\\*]* + // end of section title without asterisk +STopt [^\n@\\]* + %option noyywrap /* comment parsing states. */ @@ -541,7 +554,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" /* What can happen in while parsing a comment block: * commands (e.g. @page, or \page) * escaped commands (e.g. @@page or \\page). - * formulas (e.g. \f$ \f[ \f{..) + * formulas (e.g. \f$...\f$ \f[...\f] \f{...\f}) * directories (e.g. \doxygen\src\) * autolist end. (e.g. a dot on an otherwise empty line) * newlines. @@ -768,7 +781,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <Comment>[a-z_A-Z]+ { // normal word addOutput(yyscanner,yytext); } -<Comment>^{B}*"."{B}*/\n { // explicit end autolist: e.g " ." +<Comment>^{B}*"."{Bopt}/\n { // explicit end autolist: e.g " ." addOutput(yyscanner,yytext); } <Comment>^{B}*[1-9][0-9]*"."{B}+ | @@ -795,7 +808,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" } addOutput(yyscanner,yytext); } -<Comment>^{B}*([\-:|]{B}*)*("--"|"---")({B}*[\-:|])*{B}*/\n { // horizontal line (dashed) +<Comment>^{B}*([\-:|]{B}*)*("--"|"---")({B}*[\-:|])*{Bopt}/\n { // horizontal line (dashed) addOutput(yyscanner,yytext); } <Comment>{CMD}"---" { // escaped mdash @@ -1342,12 +1355,12 @@ RCSTAG "$"{ID}":"[^\n$]+"$" ); BEGIN(Comment); } -<SectionTitle>[^\n@\\*]*/"\n" { // end of section title +<SectionTitle>{STAopt}/"\n" { // end of section title addSection(yyscanner); addOutput(yyscanner,yytext); BEGIN( Comment ); } -<SectionTitle>[^\n@\\]*/"\\ilinebr" { // end of section title +<SectionTitle>{STopt}/"\\ilinebr" { // end of section title addSection(yyscanner); addOutput(yyscanner,yytext); BEGIN( Comment ); @@ -1449,11 +1462,11 @@ RCSTAG "$"{ID}":"[^\n$]+"$" if (*yytext=='\n') yyextra->lineNr++; addOutput(yyscanner,'\n'); } -<FormatBlock>"/*" { // start of a C-comment +<FormatBlock>{CCS} { // start of a C-comment if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim")) yyextra->commentCount++; addOutput(yyscanner,yytext); } -<FormatBlock>"*/" { // end of a C-comment +<FormatBlock>{CCE} { // end of a C-comment addOutput(yyscanner,yytext); if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim")) { diff --git a/src/config.xml b/src/config.xml index 1474698..e9b8323 100644 --- a/src/config.xml +++ b/src/config.xml @@ -647,7 +647,7 @@ Go to the <a href="commands.html">next</a> 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 <code>ext=language</code>, 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 @@ -1445,6 +1445,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn" <value name='*.hxx'/> <value name='*.hpp'/> <value name='*.h++'/> + <value name='*.l'/> <value name='*.cs'/> <value name='*.d'/> <value name='*.php'/> diff --git a/src/context.cpp b/src/context.cpp index 8bdc23c..46249f5 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/declinfo.l b/src/declinfo.l index 014ef75..9ed7738 100644 --- a/src/declinfo.l +++ b/src/declinfo.l @@ -83,6 +83,7 @@ static yy_size_t yyread(char *buf,yy_size_t max_size, yyscan_t yyscanner); %} B [ \t] +Bopt {B}* ID "$"?([a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+) %x Start @@ -188,11 +189,11 @@ ID "$"?([a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+) <Template>. { yyextra->name+=*yytext; } -<Operator>{B}*"("{B}*")"{B}*"<>"{B}*/"(" { +<Operator>{B}*"("{B}*")"{B}*"<>"{Bopt}/"(" { yyextra->name+="() <>"; BEGIN(ReadArgs); } -<Operator>{B}*"("{B}*")"{B}*/"(" { +<Operator>{B}*"("{B}*")"{Bopt}/"(" { yyextra->name+="()"; BEGIN(ReadArgs); } diff --git a/src/defargs.l b/src/defargs.l index 6846544..18e9505 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" * "<class T,class N>" * "(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 @@ -114,10 +114,18 @@ static bool nameIsActuallyPartOfType(QCString &name); %} B [ \t] +Bopt {B}* ID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"(" RAWEND ")"[^ \t\(\)\\]{0,16}\" + // C start comment +CCS "/\*" + // C end comment +CCE "*\/" + // Cpp comment +CPPC "/\/" + %option noyywrap %x Start @@ -168,7 +176,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" yyextra->curArgDefValue+=*yytext; BEGIN( CopyArgString ); } -<ReadFuncArgType>"("([^:)]+{B}*"::")*{B}*[&*\^]+{B}*/{ID} { +<ReadFuncArgType>"("([^:)]+{B}*"::")*{B}*[&*\^]+{Bopt}/{ID} { // function pointer as argument yyextra->curArgTypeName+=yytext; //yyextra->curArgTypeName=yyextra->curArgTypeName.simplifyWhiteSpace(); @@ -336,7 +344,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" <ReadFuncArgType>"=" { BEGIN( ReadFuncArgDef ); } -<ReadFuncArgType,ReadFuncArgDef>[,)>]{B}*("/*"[*!]|"//"[/!])"<" { +<ReadFuncArgType,ReadFuncArgDef>[,)>]{B}*({CCS}[*!]|{CPPC}[/!])"<" { yyextra->lastDocContext=YY_START; yyextra->lastDocChar=*yytext; QCString text=yytext; @@ -546,7 +554,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" <ReadDocLine>[^\n]+ { yyextra->curArgDocs+=yytext; } -<ReadDocBlock>"*/" { +<ReadDocBlock>{CCE} { if (yyextra->lastDocChar!=0) unput(yyextra->lastDocChar); BEGIN(yyextra->lastDocContext); @@ -562,7 +570,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" <ReadDocBlock>. { yyextra->curArgDocs+=*yytext; } -<*>("/*"[*!]|"//"[/!])("<"?) { +<*>({CCS}[*!]|{CPPC}[/!])("<"?) { yyextra->lastDocContext=YY_START; yyextra->lastDocChar=0; if (yytext[1]=='/') @@ -763,8 +771,8 @@ static bool nameIsActuallyPartOfType(QCString &name) } /*! Converts an argument string into an ArgumentList. + * \param[in] lang langage of the current argument list * \param[in] argsString the list of Arguments. - * \param[out] al a reference to resulting argument list pointer. * \param[out] extraTypeChars point to string to which trailing characters * for complex types are written to */ diff --git a/src/docsets.cpp b/src/docsets.cpp index 2911025..7cb5d31 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/doctokenizer.l b/src/doctokenizer.l index 9bafcab..a717d69 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -366,6 +366,7 @@ CMD ("\\"|"@") WS [ \t\r\n] NONWS [^ \t\r\n] BLANK [ \t\r] +BLANKopt {BLANK}* ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* LABELID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]* PHPTYPE [\\:a-z_A-Z0-9\x80-\xFF\-]+ @@ -375,7 +376,7 @@ CITEID {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*|"\""{CITESCHAR}{C MAILADDR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ MAILWS [\t a-z_A-Z0-9+-] MAILADDR2 {MAILWS}+{BLANK}+("at"|"AT"|"_at_"|"_AT_"){BLANK}+{MAILWS}+("dot"|"DOT"|"_dot_"|"_DOT_"){BLANK}+{MAILWS}+ -OPTSTARS ("//"{BLANK}*)?"*"*{BLANK}* +OPTSTARS ("/""/"{BLANK}*)?"*"*{BLANK}* LISTITEM {BLANK}*[-]("#")?{WS} MLISTITEM {BLANK}*[+*]{WS} OLISTITEM {BLANK}*[1-9][0-9]*"."{BLANK} @@ -970,11 +971,11 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio g_token->sectionId = QCString(yytext).stripWhiteSpace(); return RetVal_OK; } -<St_PlantUMLOpt>{BLANK}*{FILEMASK}{BLANK}*/\n { // case 4: plain file name specified without title or attributes +<St_PlantUMLOpt>{BLANK}*{FILEMASK}{BLANKopt}/\n { // case 4: plain file name specified without title or attributes g_token->sectionId = QCString(yytext).stripWhiteSpace(); return RetVal_OK; } -<St_PlantUMLOpt>{BLANK}*{FILEMASK}{BLANK}*/"\\ilinebr" { // case 5: plain file name specified without title or attributes +<St_PlantUMLOpt>{BLANK}*{FILEMASK}{BLANKopt}/"\\ilinebr" { // case 5: plain file name specified without title or attributes g_token->sectionId = QCString(yytext).stripWhiteSpace(); return RetVal_OK; } diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 03313ea..70153ab 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" @@ -10091,6 +10093,8 @@ void initDoxygen() make_parser_factory<SQLCodeParser>()); Doxygen::parserManager->registerParser("md", make_parser_factory<MarkdownOutlineParser>(), make_parser_factory<FileCodeParser>()); + Doxygen::parserManager->registerParser("lex", make_parser_factory<LexOutlineParser>(), + make_parser_factory<LexCodeParser>()); // register any additional parsers here... diff --git a/src/fortrancode.l b/src/fortrancode.l index d2febb9..fbc1a64 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -321,7 +321,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") codifyLines(yyscanner,yytext); endFontClass(yyscanner); } -<Start>^{BS}"namelist"/[//] { // Namelist specification +<Start>^{BS}"namelist"/[/] { // Namelist specification startFontClass(yyscanner,"keywordtype"); codifyLines(yyscanner,yytext); endFontClass(yyscanner); @@ -1067,7 +1067,7 @@ static bool getFortranNamespaceDefs(const QCString &mname, @param tname the name of the type @param moduleName name of enclosing module or null, if global entry @param cd the entry, if found or null - @param usedict dictionary of data of USE-statement + @param useMap map of data of USE-statement @returns true, if type is found */ static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName, @@ -1105,9 +1105,10 @@ static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName /** searches for definition of function memberName + @param yyscanner the scanner data to be used @param memberName the name of the function/variable @param moduleName name of enclosing module or null, if global entry - @param usedict array of data of USE-statement + @param useMap map of data of USE-statement @returns MemberDef pointer, if found, or nullptr otherwise */ static MemberDef *getFortranDefs(yyscan_t yyscanner,const QCString &memberName, const QCString &moduleName, diff --git a/src/fortranscanner.l b/src/fortranscanner.l index e43e0f4..cf8a0bb 100644..100755 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -1795,7 +1795,8 @@ static void copyEntry(std::shared_ptr<Entry> dest, const std::shared_ptr<Entry> /** fill empty interface module procedures with info from corresponding module subprogs - @TODO: handle procedures in used modules + + TODO: handle procedures in used modules */ void resolveModuleProcedures(yyscan_t yyscanner,Entry *current_root) { 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<Private> p; +}; + + +#endif diff --git a/src/lexcode.l b/src/lexcode.l new file mode 100644 index 0000000..a118703 --- /dev/null +++ b/src/lexcode.l @@ -0,0 +1,1240 @@ +/****************************************************************************** + * + * 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 <stdint.h> +} + +%{ + +#include <stdio.h> + +#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] +Bopt {B}* +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}"'")) + + /* no comment start / end signs inside square brackets */ +NCOMM [^/\*] + // C start comment +CCS "/\*" + // C end comment +CCE "*\/" + // Cpp comment +CPPC "/\/" + // doxygen start comment +DCOMM ("/\*!"|"/\**"|"/\/!"|"/\/\/") + + // Optional any character +ANYopt .* + // Optional all but newline +NONLopt [^\n]* + +%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 +<DefSection>^{TopStart} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->lastContext = YY_START; + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN (TopSection); + } +<DefSection>^{LiteralStart} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->lastContext = YY_START; + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN (LiteralSection); + } +<TopSection>^{TopEnd} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + BEGIN( yyextra->lastContext ) ; + } +<TopSection>.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<LiteralSection>^{LiteralEnd} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + BEGIN( yyextra->lastContext ) ; + } +<LiteralSection>.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<DefSection>{CPPC}.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<DefSection>^{ws}*{CCS} { + yyextra->CCodeBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(COMMENT); + } +<COMMENT>{CCE}{ws}*{nl} { + yyextra->CCodeBuffer+=yytext; + yyextra->yyLineNr++; + handleCCode(yyscanner); + BEGIN(yyextra->lastContext); + } +<COMMENT>{CCE} { + yyextra->CCodeBuffer+=yytext; + handleCCode(yyscanner); + BEGIN(yyextra->lastContext); + } +<COMMENT>[^*\n]+ { + yyextra->CCodeBuffer += yytext; + } +<COMMENT>{CPPC}|{CCS} { + yyextra->CCodeBuffer += yytext; + } +<COMMENT>{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<COMMENT>. { + yyextra->CCodeBuffer += yytext; + } +<DefSection>^{nl} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + } +<DefSection>^{ws}.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<DefSection>^{RulesStart} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN (RulesSectionInit); + } +<DefSection>^{nws} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + BEGIN(DefSectionLine); + } +<DefSectionLine>.*{nl} { + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN(DefSection); + } +<RulesSectionInit,RulesPattern>^{RulesEnd} { + handleCCode(yyscanner); + codifyLines(yyscanner,yytext); + yyextra->startCCodeLine=yyextra->yyLineNr; + BEGIN (UserSection); + } +<RulesSectionInit>^{nws} { + handleCCode(yyscanner); + unput(*yytext); + BEGIN(RulesPattern); + } +<RulesSectionInit>{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<RulesSectionInit>^{ws}.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<RulesPattern>"<<EOF>>" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{EscapeRulesChar} { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{RulesSharp} { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{RulesCurly} { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{StartDouble} { + yyextra->rulesPatternBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(RulesDouble); + } +<RulesDouble,RulesRoundDouble>"\\\\" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesDouble,RulesRoundDouble>"\\\"" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesDouble>"\"" { + yyextra->rulesPatternBuffer += yytext; + BEGIN( yyextra->lastContext ) ; + } +<RulesRoundDouble>"\"" { + yyextra->rulesPatternBuffer += yytext; + BEGIN(RulesRound) ; + } +<RulesDouble,RulesRoundDouble>. { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{StartSquare} { + yyextra->squareCount++; + yyextra->rulesPatternBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(RulesSquare); + } +<RulesSquare,RulesRoundSquare>"\\[" | +<RulesSquare,RulesRoundSquare>"\\]" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesSquare,RulesRoundSquare>"[" { + yyextra->squareCount++; + yyextra->rulesPatternBuffer += yytext; + } +<RulesSquare>"]" { + yyextra->squareCount--; + yyextra->rulesPatternBuffer += yytext; + if (!yyextra->squareCount) BEGIN(RulesPattern) ; + } +<RulesRoundSquare>"]" { + yyextra->squareCount--; + yyextra->rulesPatternBuffer += yytext; + if (!yyextra->squareCount) BEGIN(RulesRound) ; + } +<RulesSquare,RulesRoundSquare>"\\\\" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesSquare,RulesRoundSquare>. { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{StartRound} { + yyextra->roundCount++; + yyextra->rulesPatternBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(RulesRound); + } +<RulesRound>{RulesCurly} { + yyextra->rulesPatternBuffer += yytext; + } +<RulesRound>{StartSquare} { + yyextra->squareCount++; + yyextra->rulesPatternBuffer += yytext; + BEGIN(RulesRoundSquare); + } +<RulesRound>{StartDouble} { + yyextra->rulesPatternBuffer += yytext; + BEGIN(RulesRoundDouble); + } +<RulesRound>"\\(" | +<RulesRound>"\\)" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesRound>"(" { + yyextra->roundCount++; + yyextra->rulesPatternBuffer += yytext; + } +<RulesRound>")" { + yyextra->roundCount--; + yyextra->rulesPatternBuffer += yytext; + if (!yyextra->roundCount) BEGIN( yyextra->lastContext ) ; + } +<RulesRound>. { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{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); + } +<RulesPattern>^{ws}*{nl} { + codifyLines(yyscanner,"\n"); + } +<RulesPattern>^{ws}+ { + codifyLines(yyscanner,yytext); + } +<RulesPattern>({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); + } +<RulesPattern>"\\\\" { + yyextra->rulesPatternBuffer += yytext; + } +<RulesPattern>{CCS} { + 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); + } +<RulesPattern>. { + yyextra->rulesPatternBuffer += yytext; + } +<SkipCurly>{B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */ + yyextra->CCodeBuffer += yytext; + yyextra->lastPreLineCtrlContext = YY_START; + BEGIN( PreLineCtrl ); + } +<PreLineCtrl>"\""[^\n\"]*"\"" { + yyextra->CCodeBuffer += yytext; + } +<PreLineCtrl>. { + yyextra->CCodeBuffer += yytext; + } +<PreLineCtrl>\n { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + BEGIN( yyextra->lastPreLineCtrlContext ); + } +<SkipCurly>"{" { + yyextra->CCodeBuffer += yytext; + ++yyextra->curlyCount ; + } +<SkipCurly>"}"/{BN}*{DCOMM}"<!--" | /* see bug710917 */ +<SkipCurly>"}" { + yyextra->CCodeBuffer += yytext; + lineCount(yyscanner); + if( yyextra->curlyCount ) + { + --yyextra->curlyCount ; + } + } +<SkipCurly>"}"{BN}*{DCOMM}"<" { + yyextra->CCodeBuffer += yytext; + lineCount(yyscanner); + if ( yyextra->curlyCount ) + { + --yyextra->curlyCount ; + } + else + { + yyextra->docBlockContext = SkipCurlyEndDoc; + if (yytext[yyleng-3]=='/') + { + BEGIN( DocLine ); + } + else + { + BEGIN( DocBlock ); + } + } + } +<SkipCurly>\" { + yyextra->CCodeBuffer += yytext; + yyextra->lastStringContext=SkipCurly; + BEGIN( SkipString ); + } +<SkipCurly>^{B}*"#" { + yyextra->CCodeBuffer += yytext; + yyextra->lastPreLineCtrlContext = YY_START; + BEGIN( PreLineCtrl ); + } +<SkipCurly>{B}*{RAWBEGIN} { + QCString raw=QCString(yytext).stripWhiteSpace(); + yyextra->delimiter = raw.data()+2; + yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1); + yyextra->lastRawStringContext = YY_START; + yyextra->CCodeBuffer += yytext; + BEGIN(RawString); + } +<SkipCurly>[^\n#"'@\\/{}<]+ { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>{CCS} { + yyextra->CCodeBuffer += yytext; + yyextra->lastCContext = YY_START; + BEGIN(SkipComment); + } +<SkipCurly>{CPPC} { + yyextra->CCodeBuffer += yytext; + yyextra->lastCContext = YY_START; + BEGIN(SkipCxxComment); + } +<SkipCurly>{CHARLIT} { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>\' { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>. { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>({CPPC}{B}*)?{CCS}"!" { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocBlock ); + } +<SkipCurly>{CCS}"*"[*]+{BL} { + bool javadocBanner = Config_getBool(JAVADOC_BANNER); + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + if( javadocBanner ) + { + yyextra->docBlockContext = YY_START; + BEGIN( DocBlock ); + } + else + { + BEGIN( Comment ) ; + } + } +<SkipCurly>({CPPC}{B}*)?{CCS}"*"/{NCOMM} { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocBlock ); + } +<SkipCurly>{CPPC}"!" { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocLine ); + } +<SkipCurly>{CPPC}"/"/[^/] { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocLine ); + } + +<SkipCurly>\n { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + if (yyextra->curlyCount<=0) + { + handleCCode(yyscanner); + BEGIN(RulesPattern); + } + } +<SkipString>\\. { + yyextra->CCodeBuffer += yytext; + } +<SkipString>\" { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastStringContext ); + } +<SkipString>{CCS}|{CCE}|{CPPC} { + yyextra->CCodeBuffer += yytext; + } +<SkipString>\n { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<SkipString>. { + yyextra->CCodeBuffer += yytext; + } +<SkipCxxComment>.*"\\\n" { // line continuation + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<SkipCxxComment>{ANYopt}/\n { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastCContext ) ; + } +<Comment>{BN}+ { + yyextra->CCodeBuffer += yytext ; + lineCount(yyscanner); + } +<Comment>{CCS} { yyextra->CCodeBuffer += yytext ; } +<Comment>{CPPC} { yyextra->CCodeBuffer += yytext ; } +<Comment>{CMD}("code"|"verbatim") { + yyextra->insideCode=TRUE; + yyextra->CCodeBuffer += yytext ; + } +<Comment>{CMD}("endcode"|"endverbatim") { + yyextra->insideCode=FALSE; + yyextra->CCodeBuffer += yytext ; + } +<Comment>[^ \.\t\r\n\/\*]+ { yyextra->CCodeBuffer += yytext ; } +<Comment>{CCE} { + yyextra->CCodeBuffer += yytext ; + if (!yyextra->insideCode) BEGIN( yyextra->lastContext ) ; + } +<Comment>. { yyextra->CCodeBuffer += *yytext ; } + +<SkipComment>{CPPC}|{CCS} { + yyextra->CCodeBuffer += yytext; + } +<SkipComment>[^\*\n]+ { + yyextra->CCodeBuffer += yytext; + } +<SkipComment>\n { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } +<SkipComment>{B}*{CCE} { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastCContext ); + } +<SkipComment>"*" { + yyextra->CCodeBuffer += yytext; + } +<RawString>{RAWEND} { + yyextra->CCodeBuffer += yytext; + QCString delimiter = yytext+1; + delimiter=delimiter.left(delimiter.length()-1); + if (delimiter==yyextra->delimiter) + { + BEGIN(yyextra->lastRawStringContext); + } + } +<RawString>[^)\n]+ { + yyextra->CCodeBuffer += yytext; + } +<RawString>. { + yyextra->CCodeBuffer += yytext; + } +<RawString>\n { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } + + + /* ---- Single line comments ------ */ +<DocLine>[^\n]*"\n"[ \t]*{CPPC}[/!][<]? { // continuation of multiline C++-style comment + yyextra->CCodeBuffer += yytext; + lineCount(yyscanner); + } +<DocLine>{B}*{CPPC}"/"[/]+{Bopt}/"\n" { // ignore marker line (see bug700345) + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->docBlockContext ); + } +<DocLine>{NONLopt}/"\n"{B}*{CPPC}[!/]{B}*{CMD}"}" { // next line is an end group marker, see bug 752712 + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->docBlockContext ); + } +<DocLine>{NONLopt}/"\n" { // whole line + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->docBlockContext ); + } + + /* ---- Comments blocks ------ */ + +<DocBlock>"*"*{CCE} { // end of comment block + yyextra->CCodeBuffer += yytext; + BEGIN(yyextra->docBlockContext); + } +<DocBlock>^{B}*"*"+/[^/] { + yyextra->CCodeBuffer += yytext; + } +<DocBlock>^{B}*({CPPC})?{B}*"*"+/[^/a-z_A-Z0-9*] { // start of a comment line + yyextra->CCodeBuffer += yytext; + } +<DocBlock>^{B}*({CPPC}){B}* { // strip embedded C++ comments if at the start of a line + yyextra->CCodeBuffer += yytext; + } +<DocBlock>{CPPC} { // slashes in the middle of a comment block + yyextra->CCodeBuffer += yytext; + } +<DocBlock>{CCS} { // start of a new comment in the + // middle of a comment block + yyextra->CCodeBuffer += yytext; + } +<DocBlock>({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command + yyextra->CCodeBuffer += yytext; + } +<DocBlock>{CMD}("f$"|"f["|"f{") { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockName=&yytext[1]; + if (yyextra->docBlockName.at(1)=='{') + { + yyextra->docBlockName.at(1)='}'; + } + yyextra->fencedSize=0; + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>{B}*"<"{PRE}">" { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockName="<pre>"; + yyextra->fencedSize=0; + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) + yyextra->CCodeBuffer += yytext; + yyextra->docBlockName=&yytext[1]; + yyextra->fencedSize=0; + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + yyextra->docBlockName="~~~"; + yyextra->fencedSize=pat.stripWhiteSpace().length(); + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + yyextra->docBlockName="```"; + yyextra->fencedSize=pat.stripWhiteSpace().length(); + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>{B}*"<code>" { + REJECT; + } +<DocBlock>[^@*~\/\\\n]+ { // any character that isn't special + yyextra->CCodeBuffer += yytext; + } +<DocBlock>\n { // newline + yyextra->CCodeBuffer += yytext; + lineCount(yyscanner); + } +<DocBlock>. { // command block + yyextra->CCodeBuffer += yytext; + } + /* ---- Copy verbatim sections ------ */ + +<DocCopyBlock>"</"{PRE}">" { // end of a <pre> block + yyextra->CCodeBuffer += yytext; + if (yyextra->docBlockName=="<pre>") + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>"</"{CODE}">" { // end of a <code> block + yyextra->CCodeBuffer += yytext; + if (yyextra->docBlockName=="<code>") + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>[\\@]("f$"|"f]"|"f}") { + yyextra->CCodeBuffer += yytext; + BEGIN(DocBlock); + } +<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block + yyextra->CCodeBuffer += yytext; + if (&yytext[4]==yyextra->docBlockName) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line + yyextra->CCodeBuffer += yytext; + if (yyextra->docBlockName=="verbatim") + { + REJECT; + } + else if (yyextra->docBlockName=="code") + { + REJECT; + } + else + { + yyextra->CCodeBuffer += yytext; + } + } +<DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s + if (yyextra->docBlockName=="code") + { + yyextra->CCodeBuffer += yytext; + } + else + { + REJECT; + } + } +<DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516) + if (yyextra->docBlockName=="code") + { + yyextra->CCodeBuffer += yytext; + } + else + { + REJECT; + } + } +<DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one * + if (yyextra->docBlockName=="code") + { + if (yyextra->nestedComment) // keep * it is part of the code + { + yyextra->CCodeBuffer += yytext; + } + else // remove * it is part of the comment block + { + yyextra->CCodeBuffer += yytext; + } + } + else + { + REJECT; + } + } +<DocCopyBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + if (yyextra->fencedSize==pat.stripWhiteSpace().length()) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + if (yyextra->fencedSize==pat.stripWhiteSpace().length()) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>[^\<@/\*\]~\$\\\n]+ { // any character that is not special + yyextra->CCodeBuffer += yytext; + } +<DocCopyBlock>{CCS}|{CCE}|{CPPC} { + if (yytext[1]=='*') + { + yyextra->nestedComment=TRUE; + } + else if (yytext[0]=='*') + { + yyextra->nestedComment=FALSE; + } + yyextra->CCodeBuffer += yytext; + } +<DocCopyBlock>\n { // newline + yyextra->CCodeBuffer += yytext; + lineCount(yyscanner); + } +<DocCopyBlock>. { // any other character + yyextra->CCodeBuffer += yytext; + } +<SkipCurlyEndDoc>"}"{BN}*{DCOMM}"<" { // desc is followed by another one + yyextra->docBlockContext = SkipCurlyEndDoc; + yyextra->CCodeBuffer += yytext; + if (yytext[yyleng-3]=='/') + { + BEGIN( DocLine ); + } + else + { + BEGIN( DocBlock ); + } + } +<SkipCurlyEndDoc>"}" { + yyextra->CCodeBuffer += yytext; + BEGIN(SkipCurly); + } + +<UserSection>.*{nl} { + yyextra->CCodeBuffer += yytext; + yyextra->yyLineNr++; + } + /* +<*>. { fprintf(stderr,"Lex code scanner Def rule for %s: #%s#\n",stateToString(YY_START),yytext);} + */ +<*><<EOF>> { + handleCCode(yyscanner); + yyterminate(); + } +%% + +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (Doxygen::searchIndex) + { + if (yyextra->searchCtx) + { + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false); + } + else + { + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,true); + } + } +} + +/*! start a new line of code, inserting a line number if yyextra->sourceFileDef + * is true. If a definition starts at the current line, then the line + * number is linked to the documentation of that definition. + */ +static void startCodeLine(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->sourceFileDef && yyextra->lineNumbers) + { + const Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + + if (!yyextra->includeCodeFragment && d) + { + yyextra->currentDefinition = d; + yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr); + yyextra->classScope = d->name().copy(); + QCString lineAnchor; + lineAnchor.sprintf("l%05d",yyextra->yyLineNr); + if (yyextra->currentMemberDef) + { + yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), + yyextra->currentMemberDef->getOutputFileBase(), + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); + } + else + { + yyextra->code->writeLineNumber(d->getReference(), + d->getOutputFileBase(), + 0,yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); + } + } + else + { + yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); + } + } + + yyextra->code->startCodeLine(yyextra->sourceFileDef && yyextra->lineNumbers); + + if (yyextra->currentFontClass) + { + yyextra->code->startFontClass(yyextra->currentFontClass); + } +} + +static void endFontClass(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->currentFontClass) + { + yyextra->code->endFontClass(); + yyextra->currentFontClass=0; + } +} + +static void endCodeLine(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + endFontClass(yyscanner); + yyextra->code->endCodeLine(); +} + +static void nextCodeLine(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *fc = yyextra->currentFontClass; + endCodeLine(yyscanner); + if (yyextra->yyLineNr<yyextra->inputLines) + { + yyextra->currentFontClass = fc; + startCodeLine(yyscanner); + } +} + +static void codifyLines(yyscan_t yyscanner,const char *text) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p=text,*sp=p; + char c; + bool done=false; + while (!done) + { + sp=p; + while ((c=*p++) && c!='\n') { } + if (c=='\n') + { + yyextra->yyLineNr++; + int l = (int)(p-sp-1); + char *tmp = (char*)malloc(l+1); + memcpy(tmp,sp,l); + tmp[l]='\0'; + yyextra->code->codify(tmp); + if (p) + { + nextCodeLine(yyscanner); + } + else + { + endCodeLine(yyscanner); + done=true; + } + free(tmp); + } + else + { + yyextra->code->codify(sp); + done=true; + } + } + yyextra->startCCodeLine = yyextra->yyLineNr; +} + +static void startFontClass(yyscan_t yyscanner,const char *s) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + endFontClass(yyscanner); + if (!yyextra->currentFontClass || !s || strcmp(yyextra->currentFontClass,s)) + { + endFontClass(yyscanner); + yyextra->code->startFontClass(s); + yyextra->currentFontClass=s; + } +} + +/*! counts the number of lines in the input */ +static int countLines(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p=yyextra->inputString; + char c; + int count=1; + while ((c=*p)) + { + p++ ; + if (c=='\n') count++; + } + if (p>yyextra->inputString && *(p-1)!='\n') + { // last line does not end with a \n, so we add an extra + // line and explicitly terminate the line after parsing. + count++, + yyextra->needsTermination=true; + } + return count; +} + +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; + yy_size_t c=0; + while( c < max_size && *s ) + { + *buf++ = *s++; + c++; + } + yyextra->inputPosition += c; + return c; +} + +static void lineCount(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p; + for (p = yytext ; *p ; ++p ) + { + if (*p=='\n') + { + yyextra->yyLineNr++; + } + } +} + +static void handleCCode(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->CCodeBuffer.isEmpty()) return; + + yyextra->ccodeParser.setStartCodeLine(false); + yyextra->ccodeParser.parseCode(*yyextra->code, + yyextra->classScope, + yyextra->CCodeBuffer, + SrcLangExt_Cpp, + yyextra->exampleBlock, + yyextra->exampleName, + yyextra->sourceFileDef, + yyextra->startCCodeLine, + -1, /* endLine will be calculated in called routine */ + yyextra->includeCodeFragment, + yyextra->currentMemberDef, + yyextra->lineNumbers, + yyextra->searchCtx, + yyextra->collectXRefs + ); + yyextra->CCodeBuffer.resize(0); + yyextra->ccodeParser.setStartCodeLine(true); + yyextra->yyLineNr--; + codifyLines(yyscanner,"\n"); + return; +} + +// public interface ----------------------------------------------------------- + +struct LexCodeParser::Private +{ + yyscan_t yyscanner; + lexcodeYY_state state; +}; + +LexCodeParser::LexCodeParser() : p(std::make_unique<Private>()) +{ + lexcodeYYlex_init_extra(&p->state, &p->yyscanner); +#ifdef FLEX_DEBUG + lexcodeYYset_debug(1,p->yyscanner); +#endif + resetCodeParserState(); +} + +LexCodeParser::~LexCodeParser() +{ + lexcodeYYlex_destroy(p->yyscanner); +} + +void LexCodeParser::resetCodeParserState() +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; +} + +void LexCodeParser::parseCode(CodeOutputInterface &codeOutIntf, + const char *scopeName, + const QCString &input, + SrcLangExt, + bool isExampleBlock, + const char *exampleName, + FileDef *fileDef, + int startLine, + int endLine, + bool inlineFragment, + const MemberDef *memberDef, + bool showLineNumbers, + const Definition *searchCtx, + bool collectXRefs + ) +{ + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + + if (input.isEmpty()) return; + + printlex(yy_flex_debug, true, __FILE__, fileDef ? fileDef->fileName().data(): NULL); + + yyextra->code = &codeOutIntf; + yyextra->inputString = input; + yyextra->inputPosition = 0; + yyextra->currentFontClass = 0; + yyextra->needsTermination = false; + + yyextra->classScope=scopeName; + yyextra->currentMemberDef=memberDef; + yyextra->searchCtx=searchCtx; + yyextra->collectXRefs=collectXRefs; + + if (startLine!=-1) + yyextra->yyLineNr = startLine; + else + yyextra->yyLineNr = 1; + + if (endLine!=-1) + yyextra->inputLines = endLine+1; + else + yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1; + + yyextra->startCCodeLine = yyextra->yyLineNr; + yyextra->exampleBlock = isExampleBlock; + yyextra->exampleName = exampleName; + yyextra->sourceFileDef = fileDef; + yyextra->lineNumbers = fileDef!=0 && showLineNumbers; + + bool cleanupSourceDef = false; + + if (isExampleBlock && fileDef==0) + { + // create a dummy filedef for the example + yyextra->sourceFileDef = createFileDef("",(exampleName?exampleName:"generated")); + cleanupSourceDef = true; + } + + if (yyextra->sourceFileDef) + { + setCurrentDoc(yyscanner,"l00001"); + } + + yyextra->includeCodeFragment = inlineFragment; + // Starts line 1 on the output + startCodeLine(yyscanner); + + lexcodeYYrestart( 0, yyscanner ); + BEGIN( DefSection ); + lexcodeYYlex(yyscanner); + + if (yyextra->needsTermination) + { + endCodeLine(yyscanner); + } + if (cleanupSourceDef) + { + // delete the temporary file definition used for this example + delete yyextra->sourceFileDef; + yyextra->sourceFileDef=0; + } + + printlex(yy_flex_debug, false, __FILE__, fileDef ? fileDef->fileName().data(): NULL); +} + +//--------------------------------------------------------------------------------- + +#if USE_STATE2STRING +#include "lexcode.l.h" +#endif diff --git a/src/lexscanner.h b/src/lexscanner.h new file mode 100644 index 0000000..8734c59 --- /dev/null +++ b/src/lexscanner.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * + * + * + * 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 SCANNER_LEX_H +#define SCANNER_LEX_H + +#include "parserintf.h" + +/** \brief Lex language parser using state-based lexical scanning. + * + * This is the Lex language parser for doxygen. + */ +class LexOutlineParser : public OutlineParserInterface +{ + public: + LexOutlineParser(); + ~LexOutlineParser(); + void parseInput(const char *fileName, + const char *fileBuf, + const std::shared_ptr<Entry> &root, + ClangTUParser *clangParser); + bool needsPreprocessing(const QCString &extension) const { return TRUE; }; + void parsePrototype(const char *text){} + + private: + struct Private; + std::unique_ptr<Private> p; +}; +#endif diff --git a/src/lexscanner.l b/src/lexscanner.l new file mode 100644 index 0000000..47d3443 --- /dev/null +++ b/src/lexscanner.l @@ -0,0 +1,955 @@ +/***************************************************************************** + * + * + * + * 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="lexscannerYY" +%option reentrant +%option extra-type="struct lexscannerYY_state *" +%option noyywrap + +%top{ +#include <stdint.h> +} + +%{ + +/* + * includes + */ + +#include <algorithm> +#include <vector> +#include <utility> + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <ctype.h> + +#include "config.h" +#include "lexscanner.h" +#include "entry.h" +#include "message.h" +#include "util.h" +#include "scanner.h" + +#define YY_NO_INPUT 1 +#define YY_NO_UNISTD_H 1 + +#define USE_STATE2STRING 0 + +#define repeatChar(chr, cnt) std::string(cnt, chr).c_str() + +struct lexscannerYY_state +{ + COutlineParser cOutlineParser; + const char * inputString = 0; + int inputPosition = 0; + + int lastContext = 0; + int lastCContext = 0; + int lastStringContext = 0; + int docBlockContext = 0; + int lastPreLineCtrlContext = 0; + int lastRawStringContext = 0; + int curlyCount = 0; + + bool insideCode = FALSE; + QCString delimiter; + QCString docBlockName; + uint fencedSize = 0; + bool nestedComment = false; + + QCString prefix = "yy"; + QCString CCodeBuffer; + int roundCount = 0; + int squareCount = 0; + + QCString yyFileName; + ClangTUParser *clangParser = 0; + + std::shared_ptr<Entry> current; + std::shared_ptr<Entry> current_root; + SrcLangExt language; +}; + +#if USE_STATE2STRING +static const char *stateToString(int state); +#endif +//----------------------------------------------------------------------------- + +// forward declarations for statefull functions +static void handleCCode(yyscan_t yyscanner); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); + +/* ----------------------------------------------------------------- */ +#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} +OptPrefix "%option"{ws}+"prefix"{ws}*"="{ws}* +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] +Bopt {B}* +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}"'")) + + /* no comment start / end signs inside square brackets */ +NCOMM [^/\*] + // C start comment +CCS "/\*" + // C end comment +CCE "*\/" + // Cpp comment +CPPC "/\/" + // doxygen start comment +DCOMM ("/\*!"|"/\**"|"/\/!"|"/\/\/") + + // Optional any character +ANYopt .* + // Optional all but newline +NONLopt [^\n]* + +%x DefSection +%x OptPrefix +%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 +<DefSection>{OptPrefix} { + BEGIN (OptPrefix); + } +<OptPrefix>"\""[^\"]*"\"" { + yyextra->prefix = yytext; + yyextra->prefix = yyextra->prefix.mid(1,yyleng-2); + } +<OptPrefix>{nl} { + yyextra->CCodeBuffer += yytext; + BEGIN (DefSection); + } +<DefSection>^{RulesStart} { + yyextra->CCodeBuffer += "int " + yyextra->prefix + "lex (yyscan_t yyscanner) {\n"; + BEGIN (RulesSectionInit); + } +<DefSection>^{TopStart} { + yyextra->CCodeBuffer += "\n"; + yyextra->lastContext = YY_START; + BEGIN (TopSection); + } +<DefSection>^{LiteralStart} { + yyextra->CCodeBuffer += "\n"; + yyextra->lastContext = YY_START; + BEGIN (LiteralSection); + } +<TopSection>^{TopEnd} { + yyextra->CCodeBuffer += "\n"; + BEGIN( yyextra->lastContext ) ; + } +<TopSection>.*{nl} { + yyextra->CCodeBuffer += yytext; + } +<LiteralSection>^{LiteralEnd} { + yyextra->CCodeBuffer += "\n"; + BEGIN( yyextra->lastContext ) ; + } +<LiteralSection>.*{nl} { + yyextra->CCodeBuffer += yytext; + } +<DefSection>^{nws} { + BEGIN(DefSectionLine); + } +<DefSection>{CPPC}.*{nl} { + yyextra->CCodeBuffer += yytext; + } +<DefSection>^{ws}*{CCS} { + yyextra->CCodeBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(COMMENT); + } +<COMMENT>{CCE}{ws}*{nl} { + yyextra->CCodeBuffer+=yytext; + BEGIN(yyextra->lastContext); + } +<COMMENT>{CCE} { + yyextra->CCodeBuffer+=yytext; + BEGIN(yyextra->lastContext); + } +<COMMENT>[^*\n]+ { + yyextra->CCodeBuffer += yytext; + } +<COMMENT>{CPPC}|{CCS} { + yyextra->CCodeBuffer += yytext; + } +<COMMENT>{nl} { + yyextra->CCodeBuffer += yytext; + } +<COMMENT>. { + yyextra->CCodeBuffer += yytext; + } +<DefSection>^{nl} { + yyextra->CCodeBuffer += "\n"; + } +<DefSection>^{ws}.*{nl} { + yyextra->CCodeBuffer += yytext; + } +<DefSectionLine>.*{nl} { + yyextra->CCodeBuffer += "\n"; + BEGIN(DefSection); + } +<RulesSectionInit,RulesPattern>^{RulesEnd} { + yyextra->CCodeBuffer += "}\n"; + BEGIN (UserSection); + } +<RulesSectionInit>^{nws} { + unput(*yytext); + BEGIN(RulesPattern); + } +<RulesSectionInit>^{ws}.*{nl} { + yyextra->CCodeBuffer += yytext; + } +<RulesSectionInit>^{nl} { + yyextra->CCodeBuffer += yytext; + } +<RulesPattern>"<<EOF>>" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{EscapeRulesChar} { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{RulesSharp} { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{RulesCurly} { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{StartDouble} { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + yyextra->lastContext = YY_START; + BEGIN(RulesDouble); + } +<RulesDouble,RulesRoundDouble>"\\\\" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesDouble,RulesRoundDouble>"\\\"" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesDouble>"\"" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + BEGIN( yyextra->lastContext ) ; + } +<RulesRoundDouble>"\"" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + BEGIN(RulesRound) ; + } +<RulesDouble,RulesRoundDouble>. { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{StartSquare} { + yyextra->squareCount++; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + yyextra->lastContext = YY_START; + BEGIN(RulesSquare); + } +<RulesSquare,RulesRoundSquare>"\\[" | +<RulesSquare,RulesRoundSquare>"\\]" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesSquare,RulesRoundSquare>"[" { + yyextra->squareCount++; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesSquare>"]" { + yyextra->squareCount--; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + if (!yyextra->squareCount) BEGIN(RulesPattern); + } +<RulesRoundSquare>"]" { + yyextra->squareCount--; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + if (!yyextra->squareCount) BEGIN(RulesRound) ; + } +<RulesSquare,RulesRoundSquare>"\\\\" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesSquare,RulesRoundSquare>. { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{StartRound} { + yyextra->roundCount++; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + yyextra->lastContext = YY_START; + BEGIN(RulesRound); + } +<RulesRound>{RulesCurly} { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesRound>{StartSquare} { + yyextra->squareCount++; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + BEGIN(RulesRoundSquare); + } +<RulesRound>{StartDouble} { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + BEGIN(RulesRoundDouble); + } +<RulesRound>"\\(" | +<RulesRound>"\\)" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesRound>"(" { + yyextra->roundCount++; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesRound>")" { + yyextra->roundCount--; + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + if (!yyextra->roundCount) BEGIN( yyextra->lastContext ) ; + } +<RulesRound>. { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{ws}+"|" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + yyextra->curlyCount = 0; + BEGIN(SkipCurly); + } +<RulesPattern>^{ws}*{nl} { + yyextra->CCodeBuffer += "\n"; + } +<RulesPattern>^{ws}+ { + } + +<RulesPattern>({ws}|{nl}) { + unput(*yytext); + yyextra->curlyCount = 0; + BEGIN(SkipCurly); + } +<RulesPattern>"\\\\" { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<RulesPattern>{CCS} { + yyextra->CCodeBuffer += yytext; + yyextra->lastContext = YY_START; + BEGIN(COMMENT); + } +<RulesPattern>. { + yyextra->CCodeBuffer += repeatChar(' ', yyleng); + } +<SkipCurly>{B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */ + yyextra->CCodeBuffer += yytext; + yyextra->lastPreLineCtrlContext = YY_START; + BEGIN( PreLineCtrl ); + } +<PreLineCtrl>"\""[^\n\"]*"\"" { + yyextra->CCodeBuffer += yytext; + } +<PreLineCtrl>. { + yyextra->CCodeBuffer += yytext; + } +<PreLineCtrl>\n { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastPreLineCtrlContext ); + } +<SkipCurly>"{" { + yyextra->CCodeBuffer += yytext; + ++yyextra->curlyCount ; + } +<SkipCurly>"}"/{BN}*{DCOMM}"<!--" | /* see bug710917 */ +<SkipCurly>"}" { + yyextra->CCodeBuffer += yytext; + if( yyextra->curlyCount ) + { + --yyextra->curlyCount ; + } + } +<SkipCurly>"}"{BN}*{DCOMM}"<" { + yyextra->CCodeBuffer += yytext; + if ( yyextra->curlyCount ) + { + --yyextra->curlyCount ; + } + else + { + yyextra->docBlockContext = SkipCurlyEndDoc; + if (yytext[yyleng-3]=='/') + { + BEGIN( DocLine ); + } + else + { + BEGIN( DocBlock ); + } + } + } +<SkipCurly>\" { + yyextra->CCodeBuffer += yytext; + yyextra->lastStringContext=SkipCurly; + BEGIN( SkipString ); + } +<SkipCurly>^{B}*"#" { + yyextra->CCodeBuffer += yytext; + yyextra->lastPreLineCtrlContext = YY_START; + BEGIN( PreLineCtrl ); + } +<SkipCurly>{B}*{RAWBEGIN} { + QCString raw=QCString(yytext).stripWhiteSpace(); + yyextra->delimiter = raw.data()+2; + yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1); + yyextra->lastRawStringContext = YY_START; + yyextra->CCodeBuffer += yytext; + BEGIN(RawString); + } +<SkipCurly>[^\n#"'@\\/{}<]+ { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>{CCS} { + yyextra->CCodeBuffer += yytext; + yyextra->lastCContext = YY_START; + BEGIN(SkipComment); + } +<SkipCurly>{CPPC} { + yyextra->CCodeBuffer += yytext; + yyextra->lastCContext = YY_START; + BEGIN(SkipCxxComment); + } +<SkipCurly>{CHARLIT} { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>\' { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>. { + yyextra->CCodeBuffer += yytext; + } +<SkipCurly>({CPPC}{B}*)?{CCS}"!" { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocBlock ); + } +<SkipCurly>{CCS}"*"[*]+{BL} { + bool javadocBanner = Config_getBool(JAVADOC_BANNER); + yyextra->CCodeBuffer += yytext; + if( javadocBanner ) + { + yyextra->docBlockContext = YY_START; + BEGIN( DocBlock ); + } + else + { + BEGIN( Comment ) ; + } + } +<SkipCurly>({CPPC}{B}*)?{CCS}"*"/{NCOMM} { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocBlock ); + } +<SkipCurly>{CPPC}"!" { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocLine ); + } +<SkipCurly>{CPPC}"/"/[^/] { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockContext = YY_START; + BEGIN( DocLine ); + } + +<SkipCurly>\n { + yyextra->CCodeBuffer += yytext; + if (yyextra->curlyCount<=0) + { + BEGIN(RulesPattern); + } + } +<SkipString>\\. { + yyextra->CCodeBuffer += yytext; + } +<SkipString>\" { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastStringContext ); + } +<SkipString>{CCS}|{CCE}|{CPPC} { + yyextra->CCodeBuffer += yytext; + } +<SkipString>\n { + yyextra->CCodeBuffer += yytext; + } +<SkipString>. { + yyextra->CCodeBuffer += yytext; + } +<SkipCxxComment>.*"\\\n" { // line continuation + yyextra->CCodeBuffer += yytext; + } +<SkipCxxComment>{ANYopt}/\n { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastCContext ) ; + } +<Comment>{BN}+ { + yyextra->CCodeBuffer += yytext ; + } +<Comment>{CCS} { yyextra->CCodeBuffer += yytext ; } +<Comment>{CPPC} { yyextra->CCodeBuffer += yytext ; } +<Comment>{CMD}("code"|"verbatim") { + yyextra->insideCode=TRUE; + yyextra->CCodeBuffer += yytext ; + } +<Comment>{CMD}("endcode"|"endverbatim") { + yyextra->insideCode=FALSE; + yyextra->CCodeBuffer += yytext ; + } +<Comment>[^ \.\t\r\n\/\*]+ { yyextra->CCodeBuffer += yytext ; } +<Comment>{CCE} { yyextra->CCodeBuffer += yytext ; + if (!yyextra->insideCode) BEGIN( yyextra->lastContext ) ; + } +<Comment>. { yyextra->CCodeBuffer += *yytext ; } + +<SkipComment>{CPPC}|{CCS} { + yyextra->CCodeBuffer += yytext; + } +<SkipComment>[^\*\n]+ { + yyextra->CCodeBuffer += yytext; + } +<SkipComment>\n { + yyextra->CCodeBuffer += yytext; + } +<SkipComment>{B}*{CCE} { + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->lastCContext ); + } +<SkipComment>"*" { + yyextra->CCodeBuffer += yytext; + } +<RawString>{RAWEND} { + yyextra->CCodeBuffer += yytext; + QCString delimiter = yytext+1; + delimiter=delimiter.left(delimiter.length()-1); + if (delimiter==yyextra->delimiter) + { + BEGIN(yyextra->lastRawStringContext); + } + } +<RawString>[^)\n]+ { + yyextra->CCodeBuffer += yytext; + } +<RawString>. { + yyextra->CCodeBuffer += yytext; + } +<RawString>\n { + yyextra->CCodeBuffer += yytext; + } + + + /* ---- Single line comments ------ */ +<DocLine>[^\n]*"\n"[ \t]*{CPPC}[/!][<]? { // continuation of multiline C++-style comment + yyextra->CCodeBuffer += yytext; + } +<DocLine>{B}*{CPPC}"/"[/]+{Bopt}/"\n" { // ignore marker line (see bug700345) + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->docBlockContext ); + } +<DocLine>{NONLopt}/"\n"{B}*{CPPC}[!/]{B}*{CMD}"}" { // next line is an end group marker, see bug 752712 + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->docBlockContext ); + } +<DocLine>{NONLopt}/"\n" { // whole line + yyextra->CCodeBuffer += yytext; + BEGIN( yyextra->docBlockContext ); + } + + /* ---- Comments blocks ------ */ + +<DocBlock>"*"*{CCE} { // end of comment block + yyextra->CCodeBuffer += yytext; + BEGIN(yyextra->docBlockContext); + } +<DocBlock>^{B}*"*"+/[^/] { + yyextra->CCodeBuffer += yytext; + } +<DocBlock>^{B}*({CPPC})?{B}*"*"+/[^/a-z_A-Z0-9*] { // start of a comment line + yyextra->CCodeBuffer += yytext; + } +<DocBlock>^{B}*({CPPC}){B}* { // strip embedded C++ comments if at the start of a line + yyextra->CCodeBuffer += yytext; + } +<DocBlock>{CPPC} { // slashes in the middle of a comment block + yyextra->CCodeBuffer += yytext; + } +<DocBlock>{CCS} { // start of a new comment in the + // middle of a comment block + yyextra->CCodeBuffer += yytext; + } +<DocBlock>({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command + yyextra->CCodeBuffer += yytext; + } +<DocBlock>{CMD}("f$"|"f["|"f{") { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockName=&yytext[1]; + if (yyextra->docBlockName.at(1)=='{') + { + yyextra->docBlockName.at(1)='}'; + } + yyextra->fencedSize=0; + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>{B}*"<"{PRE}">" { + yyextra->CCodeBuffer += yytext; + yyextra->docBlockName="<pre>"; + yyextra->fencedSize=0; + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) + yyextra->CCodeBuffer += yytext; + yyextra->docBlockName=&yytext[1]; + yyextra->fencedSize=0; + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + yyextra->docBlockName="~~~"; + yyextra->fencedSize=pat.stripWhiteSpace().length(); + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + yyextra->docBlockName="```"; + yyextra->fencedSize=pat.stripWhiteSpace().length(); + yyextra->nestedComment=FALSE; + BEGIN(DocCopyBlock); + } +<DocBlock>{B}*"<code>" { + REJECT; + } +<DocBlock>[^@*~\/\\\n]+ { // any character that isn't special + yyextra->CCodeBuffer += yytext; + } +<DocBlock>\n { // newline + yyextra->CCodeBuffer += yytext; + } +<DocBlock>. { // command block + yyextra->CCodeBuffer += yytext; + } + /* ---- Copy verbatim sections ------ */ + +<DocCopyBlock>"</"{PRE}">" { // end of a <pre> block + yyextra->CCodeBuffer += yytext; + if (yyextra->docBlockName=="<pre>") + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>"</"{CODE}">" { // end of a <code> block + yyextra->CCodeBuffer += yytext; + if (yyextra->docBlockName=="<code>") + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>[\\@]("f$"|"f]"|"f}") { + yyextra->CCodeBuffer += yytext; + BEGIN(DocBlock); + } +<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block + yyextra->CCodeBuffer += yytext; + if (&yytext[4]==yyextra->docBlockName) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line + yyextra->CCodeBuffer += yytext; + if (yyextra->docBlockName=="verbatim") + { + REJECT; + } + else if (yyextra->docBlockName=="code") + { + REJECT; + } + else + { + yyextra->CCodeBuffer += yytext; + } + } +<DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s + if (yyextra->docBlockName=="code") + { + yyextra->CCodeBuffer += yytext; + } + else + { + REJECT; + } + } +<DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516) + if (yyextra->docBlockName=="code") + { + yyextra->CCodeBuffer += yytext; + } + else + { + REJECT; + } + } +<DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one * + if (yyextra->docBlockName=="code") + { + if (yyextra->nestedComment) // keep * it is part of the code + { + yyextra->CCodeBuffer += yytext; + } + else // remove * it is part of the comment block + { + yyextra->CCodeBuffer += yytext; + } + } + else + { + REJECT; + } + } +<DocCopyBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + if (yyextra->fencedSize==pat.stripWhiteSpace().length()) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* { + yyextra->CCodeBuffer += yytext; + QCString pat = substitute(yytext,"*"," "); + if (yyextra->fencedSize==pat.stripWhiteSpace().length()) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>[^\<@/\*\]~\$\\\n]+ { // any character that is not special + yyextra->CCodeBuffer += yytext; + } +<DocCopyBlock>{CCS}|{CCE}|{CPPC} { + if (yytext[1]=='*') + { + yyextra->nestedComment=TRUE; + } + else if (yytext[0]=='*') + { + yyextra->nestedComment=FALSE; + } + yyextra->CCodeBuffer += yytext; + } +<DocCopyBlock>\n { // newline + yyextra->CCodeBuffer += yytext; + } +<DocCopyBlock>. { // any other character + yyextra->CCodeBuffer += yytext; + } +<SkipCurlyEndDoc>"}"{BN}*{DCOMM}"<" { // desc is followed by another one + yyextra->docBlockContext = SkipCurlyEndDoc; + yyextra->CCodeBuffer += yytext; + if (yytext[yyleng-3]=='/') + { + BEGIN( DocLine ); + } + else + { + BEGIN( DocBlock ); + } + } +<SkipCurlyEndDoc>"}" { + yyextra->CCodeBuffer += yytext; + BEGIN(SkipCurly); + } + +<UserSection>.*{nl} { + yyextra->CCodeBuffer += yytext; + } + + /* +<*>. { fprintf(stderr,"Lex scanner Def rule for %s: #%s#\n",stateToString(YY_START),yytext);} + */ +<*><<EOF>> { + handleCCode(yyscanner); + yyterminate(); + } +%% + +//---------------------------------------------------------------------------- +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t c=0; + while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) + { + *buf = yyextra->inputString[yyextra->inputPosition++] ; + //printf("%d (%c)\n",*buf,*buf); + c++; buf++; + } + return c; +} + +//----------------------------------------------------------------------------- + +static void parseMain(yyscan_t yyscanner, + const char *fileName, + const char *fileBuf, + const std::shared_ptr<Entry> &rt, + ClangTUParser *clangParser) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + + yyextra->inputString = fileBuf; + yyextra->inputPosition = 0; + lexscannerYYrestart(0,yyscanner); + + yyextra->current_root = rt; + yyextra->yyFileName = fileName; + yyextra->clangParser = clangParser; + yyextra->language = getLanguageFromFileName(yyextra->yyFileName); + rt->lang = yyextra->language; + msg("Parsing file %s...\n",yyextra->yyFileName.data()); + + yyextra->current_root = rt; + yyextra->current = std::make_shared<Entry>(); + int sec=guessSection(yyextra->yyFileName); + if (sec) + { + yyextra->current->name = yyextra->yyFileName; + yyextra->current->section = sec; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + } + yyextra->current->reset(); + BEGIN( DefSection ); + + lexscannerYYlex(yyscanner); + + rt->program.resize(0); +} + +//---------------------------------------------------------------------------- + + +static void handleCCode(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + + if (yyextra->CCodeBuffer.isEmpty()) return; + yyextra->cOutlineParser.parseInput(yyextra->yyFileName, + yyextra->CCodeBuffer, + yyextra->current_root, + yyextra->clangParser); + // SrcLangExt_Cpp, + yyextra->CCodeBuffer.resize(0); + return; +} +//---------------------------------------------------------------------------- + +struct LexOutlineParser::Private +{ + yyscan_t yyscanner; + lexscannerYY_state state; +}; + +LexOutlineParser::LexOutlineParser() : p(std::make_unique<LexOutlineParser::Private>()) +{ + lexscannerYYlex_init_extra(&p->state,&p->yyscanner); +#ifdef FLEX_DEBUG + lexscannerYYset_debug(1,p->yyscanner); +#endif +} + +LexOutlineParser::~LexOutlineParser() +{ + lexscannerYYlex_destroy(p->yyscanner); +} + +void LexOutlineParser::parseInput(const char *fileName, + const char *fileBuf, + const std::shared_ptr<Entry> &root, + ClangTUParser *clangParser) +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + + printlex(yy_flex_debug, TRUE, __FILE__, fileName); + + ::parseMain(p->yyscanner,fileName,fileBuf,root,clangParser); + + printlex(yy_flex_debug, FALSE, __FILE__, fileName); +} + + +//---------------------------------------------------------------------------- + +#if USE_STATE2STRING +#include "lexscanner.l.h" +#endif diff --git a/src/memberdef.cpp b/src/memberdef.cpp index c357c43..dde9eae 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -3477,10 +3477,17 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, else ol.parseText(theTranslator->trInitialValue()); ol.endBold(); - auto intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); + QCString langCorrected = getDefFileExtension(); + SrcLangExt srcLangExt = getLanguageFromFileName(getDefFileExtension()); + if (srcLangExt == SrcLangExt_Lex) + { + langCorrected = ".doxygen_lex_c"; + srcLangExt = SrcLangExt_Cpp; + } + auto intf = Doxygen::parserManager->getCodeParser(langCorrected); intf->resetCodeParserState(); ol.startCodeFragment("DoxyCode"); - intf->parseCode(ol,scopeName,m_impl->initializer,lang,FALSE,0,const_cast<FileDef*>(getFileDef()), + intf->parseCode(ol,scopeName,m_impl->initializer,srcLangExt,FALSE,0,const_cast<FileDef*>(getFileDef()), -1,-1,TRUE,this,FALSE,this); ol.endCodeFragment("DoxyCode"); } @@ -111,8 +111,8 @@ struct PreIncludeInfo /** A dictionary of managed Define objects. */ typedef std::map< std::string, Define > DefineMap; -/** @brief Class that manages the defines available while - * preprocessing files. +/** @brief Class that manages the defines available while + * preprocessing files. */ class DefineManager { @@ -122,7 +122,7 @@ class DefineManager { public: /** Creates an empty container for defines */ - DefinesPerFile(DefineManager *parent) + DefinesPerFile(DefineManager *parent) : m_parent(parent) { } @@ -340,11 +340,23 @@ static Define * isDefined(yyscan_t yyscanner,const char *name); ID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* B [ \t] +Bopt {B}* BN [ \t\r\n] RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"(" RAWEND ")"[^ \t\(\)\\]{0,16}\" CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) + // C start comment +CCS "/\*" + // C end comment +CCE "*\/" + // Cpp comment +CPPC "/\/" + // optional characters after import +ENDIMPORTopt [^\\\n]* + // Optional white space +WSopt [ \t\r]* + %option noyywrap %x Start @@ -353,6 +365,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) %x SkipLine %x SkipString %x CopyLine +%x LexCopyLine %x CopyString %x CopyStringCs %x CopyStringFtn @@ -396,9 +409,14 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) unput(resolveTrigraph(yytext[2])); } <Start>^{B}*"#" { BEGIN(Command); yyextra->yyColNr+=(int)yyleng; yyextra->yyMLines=0;} -<Start>^{B}*/[^#] { +<Start>^("%top{"|"%{") { + if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Lex) REJECT + outputArray(yyscanner,yytext,(int)yyleng); + BEGIN(LexCopyLine); + } +<Start>^{Bopt}/[^#] { outputArray(yyscanner,yytext,(int)yyleng); - BEGIN(CopyLine); + BEGIN(CopyLine); } <Start>^{B}*[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]+{B}*"("[^\)\n]*")"/{BN}{1,10}*[:{] { // constructors? int i; @@ -439,46 +457,49 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(CopyLine); } } -<CopyLine>"extern"{BN}{0,80}"\"C\""*{BN}{0,80}"{" { +<CopyLine,LexCopyLine>"extern"{BN}{0,80}"\"C\""*{BN}{0,80}"{" { QCString text=yytext; yyextra->yyLineNr+=text.contains('\n'); outputArray(yyscanner,yytext,(int)yyleng); } -<CopyLine>{RAWBEGIN} { +<CopyLine,LexCopyLine>{RAWBEGIN} { yyextra->delimiter = yytext+2; yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1); outputArray(yyscanner,yytext,(int)yyleng); BEGIN(CopyRawString); } -<CopyLine>"{" { // count brackets inside the main file - if (yyextra->includeStack.empty()) +<CopyLine,LexCopyLine>"{" { // count brackets inside the main file + if (yyextra->includeStack.empty()) { yyextra->curlyCount++; } outputChar(yyscanner,*yytext); } -<CopyLine>"}" { // count brackets inside the main file - if (yyextra->includeStack.empty() && yyextra->curlyCount>0) +<LexCopyLine>^"%}" { + outputArray(yyscanner,yytext,(int)yyleng); + } +<CopyLine,LexCopyLine>"}" { // count brackets inside the main file + if (yyextra->includeStack.empty() && yyextra->curlyCount>0) { yyextra->curlyCount--; } outputChar(yyscanner,*yytext); } -<CopyLine>"'"\\[0-7]{1,3}"'" { +<CopyLine,LexCopyLine>"'"\\[0-7]{1,3}"'" { outputArray(yyscanner,yytext,(int)yyleng); } -<CopyLine>"'"\\."'" { +<CopyLine,LexCopyLine>"'"\\."'" { outputArray(yyscanner,yytext,(int)yyleng); } -<CopyLine>"'"."'" { +<CopyLine,LexCopyLine>"'"."'" { outputArray(yyscanner,yytext,(int)yyleng); } -<CopyLine>@\" { +<CopyLine,LexCopyLine>@\" { if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_CSharp) REJECT; outputArray(yyscanner,yytext,(int)yyleng); BEGIN( CopyStringCs ); } -<CopyLine>\" { +<CopyLine,LexCopyLine>\" { outputChar(yyscanner,*yytext); if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Fortran) { @@ -489,7 +510,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN( CopyStringFtnDouble ); } } -<CopyLine>\' { +<CopyLine,LexCopyLine>\' { if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Fortran) REJECT; outputChar(yyscanner,*yytext); BEGIN( CopyStringFtn ); @@ -542,7 +563,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <CopyRawString>. { outputChar(yyscanner,*yytext); } -<CopyLine>{ID}/{BN}{0,80}"(" { +<CopyLine,LexCopyLine>{ID}/{BN}{0,80}"(" { yyextra->expectGuard = FALSE; Define *def=0; //def=yyextra->globalDefineDict->find(yytext); @@ -579,9 +600,9 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputArray(yyscanner,yytext,(int)yyleng); } } -<CopyLine>{ID} { +<CopyLine,LexCopyLine>{ID} { Define *def=0; - if ((yyextra->includeStack.empty() || yyextra->curlyCount>0) && + if ((yyextra->includeStack.empty() || yyextra->curlyCount>0) && yyextra->macroExpansion && (def=isDefined(yyscanner,yytext)) && def->nargs==-1 && @@ -589,7 +610,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) (!yyextra->expandOnlyPredef || def->isPredefined) ) { - QCString result=def->isPredefined ? def->definition : expandMacro(yyscanner,yytext); + QCString result=def->isPredefined ? def->definition : expandMacro(yyscanner,yytext); outputArray(yyscanner,result,result.length()); } else @@ -597,13 +618,13 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputArray(yyscanner,yytext,(int)yyleng); } } -<CopyLine>"\\"\r?/\n { // strip line continuation characters +<CopyLine,LexCopyLine>"\\"\r?/\n { // strip line continuation characters if (getLanguageFromFileName(yyextra->yyFileName)==SrcLangExt_Fortran) outputChar(yyscanner,*yytext); } -<CopyLine>. { +<CopyLine,LexCopyLine>. { outputChar(yyscanner,*yytext); } -<CopyLine>\n { +<CopyLine,LexCopyLine>\n { outputChar(yyscanner,'\n'); BEGIN(Start); yyextra->yyLineNr++; @@ -641,7 +662,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <FindDefineArgs>{CHARLIT} { yyextra->defArgsStr+=yytext; } -<FindDefineArgs>"/*"[*]? { +<FindDefineArgs>{CCS}[*]? { yyextra->defArgsStr+=yytext; BEGIN(ArgCopyCComment); } @@ -668,16 +689,16 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <ArgCopyCComment>[^*\n]+ { yyextra->defArgsStr+=yytext; } -<ArgCopyCComment>"*/" { +<ArgCopyCComment>{CCE} { yyextra->defArgsStr+=yytext; BEGIN(FindDefineArgs); } -<ArgCopyCComment>\n { +<ArgCopyCComment>\n { yyextra->defArgsStr+=' '; yyextra->yyLineNr++; outputChar(yyscanner,'\n'); } -<ArgCopyCComment>. { +<ArgCopyCComment>. { yyextra->defArgsStr+=yytext; } <ReadString>"\"" { @@ -690,7 +711,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(FindDefineArgs); } -<ReadString>"//"|"/*" { +<ReadString>{CPPC}|{CCS} { yyextra->defArgsStr+=yytext; } <ReadString>\\/\r?\n { // line continuation @@ -703,20 +724,20 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } <Command>("include"|"import"){B}+/{ID} { yyextra->isImported = yytext[1]=='m'; - if (yyextra->macroExpansion) + if (yyextra->macroExpansion) BEGIN(IncludeID); } -<Command>("include"|"import"){B}*[<"] { +<Command>("include"|"import"){B}*[<"] { yyextra->isImported = yytext[1]=='m'; char c[2]; c[0]=yytext[yyleng-1];c[1]='\0'; yyextra->incName=c; - BEGIN(Include); + BEGIN(Include); } -<Command>("cmake")?"define"{B}+ { - //printf("!!!DefName\n"); +<Command>("cmake")?"define"{B}+ { + //printf("!!!DefName\n"); yyextra->yyColNr+=(int)yyleng; - BEGIN(DefName); + BEGIN(DefName); } <Command>"ifdef"/{B}*"(" { incrLevel(yyscanner); @@ -748,7 +769,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) if (!otherCaseDone(yyscanner)) { yyextra->guardExpr.resize(0); - BEGIN(Guard); + BEGIN(Guard); } else { @@ -765,7 +786,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) else { setCaseDone(yyscanner,TRUE); - } + } } <Command>"undef"{B}+ { BEGIN(UndefName); @@ -800,7 +821,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <Command>. {yyextra->yyColNr+=(int)yyleng;} <UndefName>{ID} { Define *def; - if ((def=isDefined(yyscanner,yytext)) + if ((def=isDefined(yyscanner,yytext)) /*&& !def->isPredefined*/ && !def->nonRecursive ) @@ -833,7 +854,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) if (guard) { BEGIN(Start); - } + } else { yyextra->ifcount=0; @@ -859,19 +880,19 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <DefinedExpr1,DefinedExpr2>\n { // should not happen, handle anyway yyextra->yyLineNr++; yyextra->ifcount=0; - BEGIN(SkipCPPBlock); + BEGIN(SkipCPPBlock); } <DefinedExpr2>")" { BEGIN(Guard); } <DefinedExpr1,DefinedExpr2>. <SkipCPPBlock>^{B}*"#" { BEGIN(SkipCommand); } -<SkipCPPBlock>^{B}*/[^#] { BEGIN(SkipLine); } +<SkipCPPBlock>^{Bopt}/[^#] { BEGIN(SkipLine); } <SkipCPPBlock>\n { yyextra->yyLineNr++; outputChar(yyscanner,'\n'); } <SkipCPPBlock>. -<SkipCommand>"if"(("n")?("def"))?/[ \t(!] { +<SkipCommand>"if"(("n")?("def"))?/[ \t(!] { incrLevel(yyscanner); - yyextra->ifcount++; + yyextra->ifcount++; //printf("#if... depth=%d\n",yyextra->ifcount); } <SkipCommand>"else" { @@ -884,7 +905,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } } <SkipCommand>("elif"|"else"{B}*"if")/[ \t(!] { - if (yyextra->ifcount==0) + if (yyextra->ifcount==0) { if (!otherCaseDone(yyscanner)) { @@ -898,7 +919,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } } } -<SkipCommand>"endif" { +<SkipCommand>"endif" { yyextra->expectGuard = FALSE; decrLevel(yyscanner); if (--yyextra->ifcount<0) @@ -907,13 +928,13 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(Start); } } -<SkipCommand>\n { +<SkipCommand>\n { outputChar(yyscanner,'\n'); - yyextra->yyLineNr++; + yyextra->yyLineNr++; BEGIN(SkipCPPBlock); } -<SkipCommand>{ID} { // unknown directive - BEGIN(SkipLine); +<SkipCommand>{ID} { // unknown directive + BEGIN(SkipLine); } <SkipCommand>. <SkipLine>[^'"/\n]+ @@ -922,21 +943,21 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(SkipString); } <SkipLine>. -<SkipString>"//"/[^\n]* { +<SkipString>{CPPC}/[^\n]* { } -<SkipLine,SkipCommand,SkipCPPBlock>"//"[^\n]* { +<SkipLine,SkipCommand,SkipCPPBlock>{CPPC}[^\n]* { yyextra->lastCPPContext=YY_START; BEGIN(RemoveCPPComment); } -<SkipString>"/*"/[^\n]* { +<SkipString>{CCS}/[^\n]* { } -<SkipLine,SkipCommand,SkipCPPBlock>"/*"/[^\n]* { +<SkipLine,SkipCommand,SkipCPPBlock>{CCS}/[^\n]* { yyextra->lastCContext=YY_START; BEGIN(RemoveCComment); } <SkipLine>\n { outputChar(yyscanner,'\n'); - yyextra->yyLineNr++; + yyextra->yyLineNr++; BEGIN(SkipCPPBlock); } <SkipString>[^"\\\n]+ { } @@ -945,7 +966,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(SkipLine); } <SkipString>. { } -<IncludeID>{ID}{B}*/"(" { +<IncludeID>{ID}{Bopt}/"(" { yyextra->nospaces=TRUE; yyextra->roundCount=0; yyextra->defArgsStr=yytext; @@ -957,7 +978,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) readIncludeFile(yyscanner,expandMacro(yyscanner,yytext)); BEGIN(Start); } -<Include>[^\">\n]+[\">] { +<Include>[^\">\n]+[\">] { yyextra->incName+=yytext; readIncludeFile(yyscanner,yyextra->incName); if (yyextra->isImported) @@ -969,10 +990,10 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(Start); } } -<EndImport>[^\\\n]*/\n { +<EndImport>{ENDIMPORTopt}/\n { BEGIN(Start); } -<EndImport>\\[\r]?"\n" { +<EndImport>\\[\r]?"\n" { outputChar(yyscanner,'\n'); yyextra->yyLineNr++; } @@ -1007,9 +1028,9 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) yyextra->quoteArg=FALSE; yyextra->insideComment=FALSE; yyextra->lastGuardName.resize(0); - yyextra->defText="1"; - yyextra->defLitText="1"; - BEGIN(DefineText); + yyextra->defText="1"; + yyextra->defLitText="1"; + BEGIN(DefineText); } else // define is a guard => hide { @@ -1061,7 +1082,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputArray(yyscanner,tmp.data(),tmp.length()); yyextra->quoteArg=FALSE; yyextra->insideComment=FALSE; - BEGIN(DefineText); + BEGIN(DefineText); } <DefineArg>"\\\n" { yyextra->defExtraSpacing+="\n"; @@ -1070,7 +1091,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <DefineArg>","{B}* { yyextra->defArgsStr+=yytext; } <DefineArg>"("{B}* { yyextra->defArgsStr+=yytext; } <DefineArg>{B}*")"{B}* { - yyextra->defArgsStr+=yytext; + yyextra->defArgsStr+=yytext; QCString tmp=(QCString)"#define "+yyextra->defName+yyextra->defArgsStr+yyextra->defExtraSpacing; outputArray(yyscanner,tmp.data(),tmp.length()); yyextra->quoteArg=FALSE; @@ -1108,37 +1129,37 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) yyextra->insideComment=FALSE; } */ -<DefineText>"/*"[!*]? { +<DefineText>{CCS}[!*]? { yyextra->defText+=yytext; yyextra->defLitText+=yytext; yyextra->lastCContext=YY_START; yyextra->commentCount=1; BEGIN(CopyCComment); } -<DefineText>"//"[!/]? { +<DefineText>{CPPC}[!/]? { outputArray(yyscanner,yytext,(int)yyleng); yyextra->lastCPPContext=YY_START; yyextra->defLitText+=' '; BEGIN(SkipCPPComment); } -<SkipCComment>[/]?"*/" { +<SkipCComment>[/]?{CCE} { if (yytext[0]=='/') outputChar(yyscanner,'/'); outputChar(yyscanner,'*');outputChar(yyscanner,'/'); if (--yyextra->commentCount<=0) { - if (yyextra->lastCContext==Start) + if (yyextra->lastCContext==Start) // small hack to make sure that ^... rule will // match when going to Start... Example: "/*...*/ some stuff..." { YY_CURRENT_BUFFER->yy_at_bol=1; } - BEGIN(yyextra->lastCContext); + BEGIN(yyextra->lastCContext); } } -<SkipCComment>"//"("/")* { +<SkipCComment>{CPPC}("/")* { outputArray(yyscanner,yytext,(int)yyleng); } -<SkipCComment>"/*" { +<SkipCComment>{CCS} { outputChar(yyscanner,'/');outputChar(yyscanner,'*'); //yyextra->commentCount++; } @@ -1196,12 +1217,12 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputArray(yyscanner,yytext,(int)yyleng); } <SkipCPPComment>[\\@]"cond"[ \t]+ { // conditional section - yyextra->ccomment=TRUE; + yyextra->ccomment=TRUE; yyextra->condCtx=YY_START; BEGIN(CondLineCpp); } <SkipCComment>[\\@]"cond"[ \t]+ { // conditional section - yyextra->ccomment=FALSE; + yyextra->ccomment=FALSE; yyextra->condCtx=YY_START; BEGIN(CondLineC); } @@ -1248,7 +1269,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(yyextra->condCtx); } } -<SkipCComment,SkipCPPComment>[\\@]"cond"[ \t\r]*/\n { // no guard +<SkipCComment,SkipCPPComment>[\\@]"cond"{WSopt}/\n { // no guard if (YY_START==SkipCComment) { yyextra->ccomment=TRUE; @@ -1266,15 +1287,15 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <SkipCond>\n { yyextra->yyLineNr++; outputChar(yyscanner,'\n'); } <SkipCond>. { } <SkipCond>[^\/\!*\\@\n]+ { } -<SkipCond>"//"[/!] { yyextra->ccomment=FALSE; } -<SkipCond>"/*"[*!] { yyextra->ccomment=TRUE; } +<SkipCond>{CPPC}[/!] { yyextra->ccomment=FALSE; } +<SkipCond>{CCS}[*!] { yyextra->ccomment=TRUE; } <SkipCond,SkipCComment,SkipCPPComment>[\\@][\\@]"endcond"/[^a-z_A-Z0-9\x80-\xFF] { if (!yyextra->skip) { outputArray(yyscanner,yytext,(int)yyleng); } } -<SkipCond>[\\@]"endcond"/[^a-z_A-Z0-9\x80-\xFF] { +<SkipCond>[\\@]"endcond"/[^a-z_A-Z0-9\x80-\xFF] { bool oldSkip = yyextra->skip; endCondSection(yyscanner); if (oldSkip && !yyextra->skip) @@ -1289,7 +1310,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <SkipCComment,SkipCPPComment>[\\@]"endcond"/[^a-z_A-Z0-9\x80-\xFF] { bool oldSkip = yyextra->skip; endCondSection(yyscanner); - if (oldSkip && !yyextra->skip) + if (oldSkip && !yyextra->skip) { BEGIN(yyextra->condCtx); } @@ -1319,13 +1340,13 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(SkipCComment); } } -<SkipVerbatim>"*/"|"/*" { +<SkipVerbatim>{CCE}|{CCS} { outputArray(yyscanner,yytext,(int)yyleng); } <SkipCComment,SkipVerbatim>[^*\\@\x06~`\n\/]+ { outputArray(yyscanner,yytext,(int)yyleng); } -<SkipCComment,SkipVerbatim>\n { +<SkipCComment,SkipVerbatim>\n { yyextra->yyLineNr++; outputChar(yyscanner,'\n'); } @@ -1342,17 +1363,17 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) yyextra->yyLineNr++; yyextra->yyMLines++; } -<CopyCComment>"*/" { +<CopyCComment>{CCE} { yyextra->defLitText+=yytext; yyextra->defText+=yytext; BEGIN(yyextra->lastCContext); } -<CopyCComment>\n { +<CopyCComment>\n { yyextra->yyLineNr++; yyextra->defLitText+=yytext; yyextra->defText+=' '; } -<RemoveCComment>"*/"{B}*"#" { // see bug 594021 for a usecase for this rule +<RemoveCComment>{CCE}{B}*"#" { // see bug 594021 for a usecase for this rule if (yyextra->lastCContext==SkipCPPBlock) { BEGIN(SkipCommand); @@ -1362,9 +1383,9 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) REJECT; } } -<RemoveCComment>"*/" { BEGIN(yyextra->lastCContext); } -<RemoveCComment>"//" -<RemoveCComment>"/*" +<RemoveCComment>{CCE} { BEGIN(yyextra->lastCContext); } +<RemoveCComment>{CPPC} +<RemoveCComment>{CCS} <RemoveCComment>[^*\x06\n]+ <RemoveCComment>\n { yyextra->yyLineNr++; outputChar(yyscanner,'\n'); } <RemoveCComment>. @@ -1375,10 +1396,10 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) unput(*yytext); BEGIN(yyextra->lastCPPContext); } -<SkipCPPComment>"/*" { +<SkipCPPComment>{CCS} { outputChar(yyscanner,'/');outputChar(yyscanner,'*'); } -<SkipCPPComment>"//" { +<SkipCPPComment>{CPPC} { outputChar(yyscanner,'/');outputChar(yyscanner,'/'); } <SkipCPPComment>[^\x06\@\\\n]+ { @@ -1387,8 +1408,8 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <SkipCPPComment>. { outputChar(yyscanner,*yytext); } -<RemoveCPPComment>"/*" -<RemoveCPPComment>"//" +<RemoveCPPComment>{CCS} +<RemoveCPPComment>{CPPC} <RemoveCPPComment>[^\x06\n]+ <RemoveCPPComment>. <DefineText>"#" { @@ -1447,7 +1468,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputChar(yyscanner,'\n'); Define *def=0; //printf("Define name='%s' text='%s' litTexti='%s'\n",yyextra->defName.data(),yyextra->defText.data(),yyextra->defLitText.data()); - if (yyextra->includeStack.empty() || yyextra->curlyCount>0) + if (yyextra->includeStack.empty() || yyextra->curlyCount>0) { addMacroDefinition(yyscanner); } @@ -1468,7 +1489,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) def->name = yyextra->defName; def->definition = yyextra->defText.stripWhiteSpace(); def->nargs = yyextra->defArgs; - def->fileName = yyextra->yyFileName.copy(); + def->fileName = yyextra->yyFileName.copy(); def->lineNr = yyextra->yyLineNr-yyextra->yyMLines; def->columnNr = yyextra->yyColNr; } @@ -1486,25 +1507,25 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) <DefineText>{B}* { yyextra->defText += ' '; yyextra->defLitText+=yytext; } <DefineText>{B}*"##"{B}* { yyextra->defText += "##"; yyextra->defLitText+=yytext; } <DefineText>"@" { yyextra->defText += "@@"; yyextra->defLitText+=yytext; } -<DefineText>\" { - yyextra->defText += *yytext; - yyextra->defLitText+=yytext; +<DefineText>\" { + yyextra->defText += *yytext; + yyextra->defLitText+=yytext; if (!yyextra->insideComment) { BEGIN(SkipDoubleQuote); } } <DefineText>\' { yyextra->defText += *yytext; - yyextra->defLitText+=yytext; + yyextra->defLitText+=yytext; if (!yyextra->insideComment) { BEGIN(SkipSingleQuote); } } -<SkipDoubleQuote>"//"[/]? { yyextra->defText += yytext; yyextra->defLitText+=yytext; } -<SkipDoubleQuote>"/*"[*]? { yyextra->defText += yytext; yyextra->defLitText+=yytext; } +<SkipDoubleQuote>{CPPC}[/]? { yyextra->defText += yytext; yyextra->defLitText+=yytext; } +<SkipDoubleQuote>{CCS}[*]? { yyextra->defText += yytext; yyextra->defLitText+=yytext; } <SkipDoubleQuote>\" { - yyextra->defText += *yytext; yyextra->defLitText+=yytext; + yyextra->defText += *yytext; yyextra->defLitText+=yytext; BEGIN(DefineText); } <SkipSingleQuote,SkipDoubleQuote>\\. { @@ -1541,7 +1562,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) setFileName(yyscanner,fs->fileName); DBG_CTX((stderr,"######## FileName %s\n",yyextra->yyFileName.data())); - // Deal with file changes due to + // Deal with file changes due to // #include's within { .. } blocks QCString lineStr(15+yyextra->yyFileName.length()); lineStr.sprintf("# %d \"%s\" 2",yyextra->yyLineNr,yyextra->yyFileName.data()); @@ -1582,8 +1603,8 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) yyextra->localDefines.clear(); } } -<*>"/*"/"*/" | -<*>"/*"[*!]? { +<*>{CCS}/{CCE} | +<*>{CCS}[*!]? { if (YY_START==SkipVerbatim || YY_START==SkipCond) { REJECT; @@ -1593,7 +1614,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) outputArray(yyscanner,yytext,(int)yyleng); yyextra->lastCContext=YY_START; yyextra->commentCount=1; - if (yyleng==3) + if (yyleng==3) { yyextra->isSpecialComment = true; yyextra->lastGuardName.resize(0); // reset guard in case the #define is documented! @@ -1605,7 +1626,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(SkipCComment); } } -<*>"//"[/!]? { +<*>{CPPC}[/!]? { if (YY_START==SkipVerbatim || YY_START==SkipCond || getLanguageFromFileName(yyextra->yyFileName)==SrcLangExt_Fortran) { REJECT; @@ -1626,9 +1647,9 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) BEGIN(SkipCPPComment); } } -<*>\n { +<*>\n { outputChar(yyscanner,'\n'); - yyextra->yyLineNr++; + yyextra->yyLineNr++; } <*>. { yyextra->expectGuard = FALSE; @@ -1845,23 +1866,23 @@ static QCString extractTrailingComment(const char *s) { i--; while (i>0 && !(s[i-1]=='/' && s[i]=='*')) i--; - if (i==0) + if (i==0) { i++; } // only /*!< or /**< are treated as a comment for the macro name, // otherwise the comment is treated as part of the macro definition - return ((s[i+1]=='*' || s[i+1]=='!') && s[i+2]=='<') ? &s[i-1] : ""; + return ((s[i+1]=='*' || s[i+1]=='!') && s[i+2]=='<') ? &s[i-1] : ""; } else { return ""; } - } + } break; // whitespace or line-continuation case ' ': - case '\t': + case '\t': case '\r': case '\n': case '\\': @@ -1935,7 +1956,7 @@ static QCString stringize(const QCString &s) while (i<s.length() && inString) { c=s.at(i++); - if (c=='"') + if (c=='"') { result+="\\\""; inString= pc=='\\'; @@ -1952,8 +1973,8 @@ static QCString stringize(const QCString &s) return result; } -/*! Execute all ## operators in expr. - * If the macro name before or after the operator contains a no-rescan +/*! Execute all ## operators in expr. + * If the macro name before or after the operator contains a no-rescan * marker (@-) then this is removed (before the concatenated macro name * may be expanded again. */ @@ -2023,12 +2044,12 @@ static inline void addTillEndOfString(yyscan_t yyscanner,const QCString &expr,QC } /*! replaces the function macro \a def whose argument list starts at - * \a pos in expression \a expr. + * \a pos in expression \a expr. * Notice that this routine may scan beyond the \a expr string if needed. * In that case the characters will be read from the input file. - * The replacement string will be returned in \a result and the + * The replacement string will be returned in \a result and the * length of the (unexpanded) argument list is stored in \a len. - */ + */ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCString *rest,int pos,int &len,const Define *def,QCString &result,int level) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); @@ -2037,15 +2058,15 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin len=0; result.resize(0); int cc; - while ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && isspace(cc)) - { - len++; - getNextChar(yyscanner,expr,rest,j); + while ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && isspace(cc)) + { + len++; + getNextChar(yyscanner,expr,rest,j); } - if (cc!='(') - { - unputChar(yyscanner,expr,rest,j,(char)cc); - return FALSE; + if (cc!='(') + { + unputChar(yyscanner,expr,rest,j,(char)cc); + return FALSE; } getNextChar(yyscanner,expr,rest,j); // eat the '(' character @@ -2065,7 +2086,7 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin } else { - while (!done && (argCount<def->nargs || def->varArgs) && + while (!done && (argCount<def->nargs || def->varArgs) && ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0) ) { @@ -2119,21 +2140,21 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin done=TRUE; } } - } + } else if (c=='\"') // append literal strings { - arg+=c; + arg+=c; bool found=FALSE; while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0) { found = cc=='"'; if (cc=='\\') { - c=(char)cc; + c=(char)cc; arg+=c; if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break; } - c=(char)cc; + c=(char)cc; arg+=c; } } @@ -2146,14 +2167,14 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin found = cc=='\''; if (cc=='\\') { - c=(char)cc; + c=(char)cc; arg+=c; if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break; } c=(char)cc; arg+=c; } - } + } else if (c=='/') // possible start of a comment { char prevChar = '\0'; @@ -2213,7 +2234,7 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin k++; // scan the number while (k<d.length() && d.at(k)>='0' && d.at(k)<='9') key+=d.at(k++); - if (!hash) + if (!hash) { // search for ## forward l=k; @@ -2237,7 +2258,7 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin { //printf("'%s'=stringize('%s')\n",stringize(*subst).data(),subst->data()); - // if the marker is inside a string (because a # was put + // if the marker is inside a string (because a # was put // before the macro name) we must escape " and \ characters resExpr+=stringize(substArg); } @@ -2261,7 +2282,7 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin } else // no marker, just copy { - if (!inString && d.at(k)=='\"') + if (!inString && d.at(k)=='\"') { inString=TRUE; // entering a literal string } @@ -2301,13 +2322,13 @@ static int getNextId(const QCString &expr,int p,int *l) n=p-1; while (p<(int)expr.length() && isId(expr.at(p))) p++; *l=p-n; - return n; + return n; } else if (c=='"') // skip string { char ppc=0,pc=c; if (p<(int)expr.length()) c=expr.at(p); - while (p<(int)expr.length() && (c!='"' || (pc=='\\' && ppc!='\\'))) + while (p<(int)expr.length() && (c!='"' || (pc=='\\' && ppc!='\\'))) // continue as long as no " is found, but ignoring \", but not \\" { ppc=pc; @@ -2321,11 +2342,11 @@ static int getNextId(const QCString &expr,int p,int *l) { //printf("Found C comment at p=%d\n",p); char pc=c; - if (p<(int)expr.length()) + if (p<(int)expr.length()) { c=expr.at(p); if (c=='*') // Start of C comment - { + { p++; while (p<(int)expr.length() && !(pc=='*' && c=='/')) { @@ -2386,7 +2407,7 @@ static bool expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,in //printf("found defined inside macro definition '%s'\n",expr.right(expr.length()-p).data()); definedTest=TRUE; } - else if (definedTest) // macro name was found after defined + else if (definedTest) // macro name was found after defined { if (def) expMacro = " 1 "; else expMacro = " 0 "; replaced=TRUE; @@ -2544,7 +2565,7 @@ static QCString removeIdsAndMarkers(const char *s) { if (*(p+1)=='@') { - result+=c; + result+=c; } else if (*(p+1)=='E') { @@ -2564,7 +2585,7 @@ static QCString removeIdsAndMarkers(const char *s) } else if (c=='d' && !inNum) // identifier starting with a 'd' { - if (qstrncmp(p,"defined ",8)==0 || qstrncmp(p,"defined(",8)==0) + if (qstrncmp(p,"defined ",8)==0 || qstrncmp(p,"defined(",8)==0) // defined keyword { p+=7; // skip defined @@ -2616,7 +2637,7 @@ static QCString removeIdsAndMarkers(const char *s) char pc=c; c=*++p; if (c=='*') // start of C comment - { + { while (*p && !(pc=='*' && c=='/')) // search end of comment { pc=c; @@ -2630,7 +2651,7 @@ static QCString removeIdsAndMarkers(const char *s) goto nextChar; } } - else + else { nextChar: result+=c; @@ -2645,7 +2666,7 @@ nextChar: } /*! replaces all occurrences of @@ in \a s by @ - * \par assumption: + * \par assumption: * \a s only contains pairs of @@'s */ static QCString removeMarkers(const char *s) @@ -2663,7 +2684,7 @@ static QCString removeMarkers(const char *s) { if (*(p+1)=='@') { - result+=c; + result+=c; } p+=2; } @@ -2674,12 +2695,12 @@ static QCString removeMarkers(const char *s) char pc=c; c=*++p; if (c=='*') // start of C comment - { + { while (*p && !(pc=='*' && c=='/')) // search end of comment { - if (*p=='@' && *(p+1)=='@') + if (*p=='@' && *(p+1)=='@') result+=c,p++; - else + else result+=c; pc=c; c=*++p; @@ -2744,7 +2765,7 @@ static void addDefine(yyscan_t yyscanner) def.name = state->defName; def.definition = state->defText.stripWhiteSpace(); def.nargs = state->defArgs; - def.fileName = state->yyFileName; + def.fileName = state->yyFileName; def.fileDef = state->yyFileDef; def.lineNr = state->yyLineNr-state->yyMLines; def.columnNr = state->yyColNr; @@ -2752,7 +2773,7 @@ static void addDefine(yyscan_t yyscanner) //printf("newDefine: %s %s file: %s\n",def.name.data(),def.definition.data(), // def.fileDef ? def.fileDef->name().data() : def.fileName.data()); //printf("newDefine: '%s'->'%s'\n",def.name.data(),def.definition.data()); - if (!def.name.isEmpty() && + if (!def.name.isEmpty() && Doxygen::expandAsDefinedSet.find(def.name.str())!=Doxygen::expandAsDefinedSet.end()) { def.isPredefined=TRUE; @@ -2768,7 +2789,7 @@ static void addDefine(yyscan_t yyscanner) static void addMacroDefinition(yyscan_t yyscanner) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); - if (state->skip) return; // do not add this define as it is inside a + if (state->skip) return; // do not add this define as it is inside a // conditional section (cond command) that is disabled. Define define; @@ -2909,7 +2930,7 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) //printf("Found include file!\n"); if (Debug::isFlagSet(Debug::Preprocessor)) { - for (i=0;i<state->includeStack.size();i++) + for (i=0;i<state->includeStack.size();i++) { Debug::print(Debug::Preprocessor,0," "); } @@ -2944,7 +2965,7 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) state->includeStack.emplace_back(fs); // set the scanner to the include file - // Deal with file changes due to + // Deal with file changes due to // #include's within { .. } blocks QCString lineStr(state->yyFileName.length()+20); lineStr.sprintf("# 1 \"%s\" 1\n",state->yyFileName.data()); @@ -2985,7 +3006,7 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc) if (Debug::isFlagSet(Debug::Preprocessor)) { - for (i=0;i<state->includeStack.size();i++) + for (i=0;i<state->includeStack.size();i++) { Debug::print(Debug::Preprocessor,0," "); } @@ -3106,7 +3127,7 @@ static int getNextChar(yyscan_t yyscanner,const QCString &expr,QCString *rest,ui return cc; } } - + static int getCurrentChar(yyscan_t yyscanner,const QCString &expr,QCString *rest,uint pos) { //printf("getCurrentChar(%s,%s,%d)\n",expr.data(),rest ? rest->data() : 0,pos); @@ -3377,20 +3398,20 @@ void Preprocessor::processFile(const char *fileName,BufStr &input,BufStr &output state->inputFileDef = state->yyFileDef; //yyextra->defineManager.startContext(state->yyFileName); - + initPredefined(yyscanner,fileName); - + state->yyLineNr = 1; state->yyColNr = 1; state->ifcount = 0; BEGIN( Start ); - + state->expectGuard = guessSection(fileName)==Entry::HEADER_SEC; state->guardName.resize(0); state->lastGuardName.resize(0); state->guardExpr.resize(0); - + preYYlex(yyscanner); while (!state->condStack.empty()) diff --git a/src/pycode.l b/src/pycode.l index 1ab724b..f63e885 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -247,7 +247,7 @@ KEYWORD_ARGUMENTS {KEYWORD_ITEM}(","{KEYWORD_ITEM})* KEYWORD_ITEM {IDENTIFIER}"="{EXPRESSION} POWER {PRIMARY}("**"{U_EXPR})? U_EXPR ({POWER}|"-"{U_EXPR}|"+"{U_EXPR}|"\~"{U_EXPR}) -M_EXPR ({U_EXPR}|{M_EXPR}"*"{U_EXPR}|{M_EXPR}"//"{U_EXPR}|{M_EXPR}"/"{U_EXPR}|{M_EXPR}"\%"{U_EXPR}) +M_EXPR ({U_EXPR}|{M_EXPR}"*"{U_EXPR}|{M_EXPR}"/""/"{U_EXPR}|{M_EXPR}"/"{U_EXPR}|{M_EXPR}"\%"{U_EXPR}) A_EXPR ({M_EXPR}|{A_EXPR}"+"{M_EXPR}|{A_EXPR}"-"{M_EXPR} SHIFT_EXPR ({A_EXPR}|{SHIFT_EXPR}("<<"|">>"){A_EXPR}) AND_EXPR ({SHIFT_EXPR}|{AND_EXPR}"\;SPMamp;"{SHIFT_EXPR} diff --git a/src/scanner.l b/src/scanner.l index 0193689..6b4cda3 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -232,8 +232,10 @@ static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); /* start command character */ CMD ("\\"|"@") BN [ \t\n\r] +BNopt {BN}* BL [ \t\r]*"\n" B [ \t] +Bopt {B}* ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* SCOPENAME "$"?(({ID}?{BN}*"::"{BN}*)*)(((~|!){BN}*)?{ID}) TSCOPE {ID}("<"[a-z_A-Z0-9 \t\*\&,:]*">")? @@ -253,6 +255,22 @@ LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!"|"<=>" BITOP "&"|"|"|"^"|"<<"|">>"|"~" OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) + /* no comment start / end signs inside square brackets */ +NCOMM [^/\*] + // C start comment +CCS "/\*" + // C end comment +CCE "*\/" + // Cpp comment +CPPC "/\/" + // doxygen start comment +DCOMM ("/\*!"|"/\**"|"/\/!"|"/\/\/") + + // Optional any character +ANYopt .* + // Optional all but newline +NONLopt [^\n]* + %option noyywrap /* language parsing states */ @@ -1122,7 +1140,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } */ <FindMembers>{B}*"typename"{BN}+ { lineCount(yyscanner); } -<FindMembers>{B}*"namespace"{BN}*/[^a-z_A-Z0-9] { +<FindMembers>{B}*"namespace"{BNopt}/[^a-z_A-Z0-9] { yyextra->isTypedef=FALSE; yyextra->current->section = Entry::NAMESPACE_SEC; yyextra->current->type = "namespace" ; @@ -1596,12 +1614,12 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) if (yytext[yyleng-1]=='{') unput('{'); BEGIN( CompoundName ) ; } -<Operator>"("{BN}*")"({BN}*"<"[^>]*">"){BN}*/"(" { // A::operator()<int>(int arg) +<Operator>"("{BN}*")"({BN}*"<"[^>]*">"){BNopt}/"(" { // A::operator()<int>(int arg) lineCount(yyscanner); yyextra->current->name += "()"; BEGIN( FindMembers ); } -<Operator>"("{BN}*")"{BN}*/"(" { +<Operator>"("{BN}*")"{BNopt}/"(" { lineCount(yyscanner); yyextra->current->name += yytext ; yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); @@ -1768,7 +1786,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->previous->spec |= Entry::Alias; BEGIN(FindMembers); } -<UsingAlias>";"{BN}*("/**"|"//!"|"/*!"|"///")"<" { +<UsingAlias>";"{BN}*{DCOMM}"<" { yyextra->docBlockContext = UsingAliasEnd; yyextra->docBlockInBody = FALSE; yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || @@ -1821,7 +1839,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) addType(yyscanner); yyextra->current->name=n.left(n.length()-2); } -<FindMembers>{SCOPENAME}{BN}*/"<" { // Note: this could be a return type! +<FindMembers>{SCOPENAME}{BNopt}/"<" { // Note: this could be a return type! yyextra->roundCount=0; yyextra->sharpCount=0; lineCount(yyscanner); @@ -1835,7 +1853,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) else BEGIN( EndTemplate ); } -<FindMemberName>{SCOPENAME}{BN}*/"<" { +<FindMemberName>{SCOPENAME}{BNopt}/"<" { yyextra->sharpCount=0; yyextra->roundCount=0; lineCount(yyscanner); @@ -1908,7 +1926,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN( ReadFuncArgType ) ; } } -<EndTemplate>">"{BN}*/"("({BN}*{ID}{BN}*"::")*({BN}*"*"{BN}*)+ { // function pointer returning a template instance +<EndTemplate>">"{BNopt}/"("({BN}*{ID}{BN}*"::")*({BN}*"*"{BN}*)+ { // function pointer returning a template instance lineCount(yyscanner); yyextra->current->name+='>'; if (yyextra->roundCount==0) @@ -1916,7 +1934,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN(FindMembers); } } -<EndTemplate>">"{BN}*/"::" { +<EndTemplate>">"{BNopt}/"::" { lineCount(yyscanner); yyextra->current->name+='>'; // *yyextra->currentTemplateSpec+='>'; @@ -2434,7 +2452,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->name += yytext ; addType(yyscanner); } -<FindMembers,MemberSpec,Function,NextSemi,EnumBaseType,BitFields,ReadInitializer,ReadInitializerPtr,OldStyleArgs,DefinePHPEnd>";"{BN}*("/**"|"//!"|"/*!"|"///")"<" { +<FindMembers,MemberSpec,Function,NextSemi,EnumBaseType,BitFields,ReadInitializer,ReadInitializerPtr,OldStyleArgs,DefinePHPEnd>";"{BN}*{DCOMM}"<" { if (yyextra->current->bodyLine==-1) { yyextra->current->bodyLine=yyextra->yyLineNr; @@ -2469,7 +2487,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN( DocBlock ); } } -<MemberSpec,FindFields,FindMembers,NextSemi,EnumBaseType,BitFields,ReadInitializer,ReadInitializerPtr,OldStyleArgs>","{BN}*("/**"|"//!"|"/*!"|"///")"<" { +<MemberSpec,FindFields,FindMembers,NextSemi,EnumBaseType,BitFields,ReadInitializer,ReadInitializerPtr,OldStyleArgs>","{BN}*{DCOMM}"<" { yyextra->docBlockContext = YY_START; yyextra->docBlockInBody = FALSE; yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || @@ -2498,7 +2516,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN( DocBlock ); } } -<DefineEnd,FindFields,FindFieldArg,ReadInitializer,ReadInitializerPtr,OldStyleArgs>{BN}*("/**"|"//!"|"/*!"|"///")"<" { +<DefineEnd,FindFields,FindFieldArg,ReadInitializer,ReadInitializerPtr,OldStyleArgs>{BN}*{DCOMM}"<" { if (yyextra->current->bodyLine==-1) { yyextra->current->bodyLine=yyextra->yyLineNr; @@ -2526,7 +2544,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } -<FindMembers,FindFields>("//"([!/]){B}*{CMD}"{")|("/*"([!*]){B}*{CMD}"{") { +<FindMembers,FindFields>({CPPC}([!/]){B}*{CMD}"{")|({CCS}([!*]){B}*{CMD}"{") { //handleGroupStartCommand(yyextra->current->name); if (yyextra->previous && yyextra->previous->section==Entry::GROUPDOC_SEC) { @@ -2578,7 +2596,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } } -<FindMembers,FindFields,ReadInitializer,ReadInitializerPtr>"//"([!/]){B}*{CMD}"}".*|"/*"([!*]){B}*{CMD}"}"[^*]*"*/" { +<FindMembers,FindFields,ReadInitializer,ReadInitializerPtr>{CPPC}([!/]){B}*{CMD}"}".*|{CCS}([!*]){B}*{CMD}"}"[^*]*{CCE} { bool insideEnum = YY_START==FindFields || ((YY_START==ReadInitializer || YY_START==ReadInitializerPtr) && yyextra->lastInitializerContext==FindFields); // see bug746226 yyextra->commentScanner.close(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr,insideEnum); lineCount(yyscanner); @@ -2836,7 +2854,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) *yyextra->pCopyQuotedString+=*yytext; BEGIN( yyextra->lastStringContext ); } -<CopyString,CopyPHPString>"/*"|"*/"|"//" { +<CopyString,CopyPHPString>{CCS}|{CCE}|{CPPC} { *yyextra->pCopyQuotedString+=yytext; } <CopyString,CopyPHPString>\n { @@ -2863,7 +2881,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) *yyextra->pCopyQuotedGString += yytext; BEGIN( yyextra->lastStringContext ); } -<CopyGString,CopyPHPGString>"/*"|"*/"|"//" { +<CopyGString,CopyPHPGString>{CCS}|{CCE}|{CPPC} { *yyextra->pCopyQuotedGString+=yytext; } <CopyGString,CopyPHPGString>\n { @@ -3384,20 +3402,20 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN( IDLProp ); } <IDLPropName>{BN}*"("{BN}*{ID}{BN}*")"{BN}* { - if (yyextra->odlProp) - { - yyextra->idlProp += yytext; - } + if (yyextra->odlProp) + { + yyextra->idlProp += yytext; + } } -<IDLPropName>{ID}{BN}*/";" { - if (yyextra->odlProp) - { - yyextra->current->name = yytext; - yyextra->idlProp = yyextra->idlProp.stripWhiteSpace(); - yyextra->odlProp = false; +<IDLPropName>{ID}{BNopt}/";" { + if (yyextra->odlProp) + { + yyextra->current->name = yytext; + yyextra->idlProp = yyextra->idlProp.stripWhiteSpace(); + yyextra->odlProp = false; - BEGIN( IDLProp ); - } + BEGIN( IDLProp ); + } } <IDLProp>{BN}*"["[^\]]*"]"{BN}* { // attribute of a parameter yyextra->idlAttr = yytext; @@ -3575,7 +3593,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <FindFieldArg>"," { unput(*yytext); BEGIN(FindFields); } */ <ReadBody,ReadNSBody,ReadBodyIntf>[^\r\n\#{}"@'/<]* { yyextra->current->program += yytext ; } -<ReadBody,ReadNSBody,ReadBodyIntf>"//".* { yyextra->current->program += yytext ; } +<ReadBody,ReadNSBody,ReadBodyIntf>{CPPC}.* { yyextra->current->program += yytext ; } <ReadBody,ReadNSBody,ReadBodyIntf>"#".* { if (!yyextra->insidePHP) REJECT; // append PHP comment. @@ -3603,11 +3621,11 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->lastStringContext=YY_START; BEGIN( CopyGString ); } -<ReadBody,ReadNSBody,ReadBodyIntf>"/*"{B}* { yyextra->current->program += yytext ; +<ReadBody,ReadNSBody,ReadBodyIntf>{CCS}{B}* { yyextra->current->program += yytext ; yyextra->lastContext = YY_START ; BEGIN( Comment ) ; } -<ReadBody,ReadNSBody,ReadBodyIntf>"/*"{BL} { yyextra->current->program += yytext ; +<ReadBody,ReadNSBody,ReadBodyIntf>{CCS}{BL} { yyextra->current->program += yytext ; ++yyextra->yyLineNr ; yyextra->lastContext = YY_START ; BEGIN( Comment ) ; @@ -4039,7 +4057,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <FuncPtr>. { //printf("error: FuncPtr '%c' unexpected at line %d of %s\n",*yytext,yyextra->yyLineNr,yyextra->yyFileName); } -<FuncPtrOperator>"("{BN}*")"{BN}*/"(" { +<FuncPtrOperator>"("{BN}*")"{BNopt}/"(" { yyextra->current->name += yytext; yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); lineCount(yyscanner); @@ -4055,17 +4073,17 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <FuncPtrOperator>. { yyextra->current->name += *yytext; } -<EndFuncPtr>")"{BN}*/";" { // a variable with extra braces +<EndFuncPtr>")"{BNopt}/";" { // a variable with extra braces lineCount(yyscanner); yyextra->current->type+=yyextra->funcPtrType.data()+1; BEGIN(FindMembers); } -<EndFuncPtr>")"{BN}*/"(" { // a function pointer +<EndFuncPtr>")"{BNopt}/"(" { // a function pointer lineCount(yyscanner); yyextra->current->type+=yyextra->funcPtrType+")"; BEGIN(FindMembers); } -<EndFuncPtr>")"{BN}*/"[" { // an array of variables +<EndFuncPtr>")"{BNopt}/"[" { // an array of variables lineCount(yyscanner); yyextra->current->type+=yyextra->funcPtrType.data(); yyextra->current->args += ")"; @@ -4107,12 +4125,12 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->type+=yyextra->funcPtrType+")("; BEGIN(FuncFuncType); } -<FuncFuncEnd>")"{BN}*/[;{] { +<FuncFuncEnd>")"{BNopt}/[;{] { lineCount(yyscanner); yyextra->current->type+=yyextra->funcPtrType.data()+1; BEGIN(Function); } -<FuncFuncEnd>")"{BN}*/"[" { // function returning a pointer to an array +<FuncFuncEnd>")"{BNopt}/"[" { // function returning a pointer to an array lineCount(yyscanner); yyextra->current->type+=yyextra->funcPtrType; yyextra->current->args+=")"; @@ -4246,7 +4264,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN( yyextra->currentArgumentContext ); } /* a special comment */ -<ReadFuncArgType,ReadTempArgs>("/*"[*!]|"//"[/!])("<"?) { +<ReadFuncArgType,ReadTempArgs>({CCS}[*!]|{CPPC}[/!])("<"?) { if (yyextra->currentArgumentContext==DefineEnd) { // for defines we interpret a comment @@ -4273,12 +4291,12 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } /* a non-special comment */ -<ReadFuncArgType,ReadTempArgs>"/**/" { /* empty comment */ } -<ReadFuncArgType,ReadTempArgs>"/*" { +<ReadFuncArgType,ReadTempArgs>{CCS}{CCE} { /* empty comment */ } +<ReadFuncArgType,ReadTempArgs>{CCS} { yyextra->lastCContext = YY_START; BEGIN( SkipComment ); } -<ReadFuncArgType,ReadTempArgs>"//" { +<ReadFuncArgType,ReadTempArgs>{CPPC} { yyextra->lastCContext = YY_START; BEGIN( SkipCxxComment ); } @@ -4296,7 +4314,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } */ /* ')' followed by a special comment */ -<ReadFuncArgType>")"{BN}*("/*"[*!]|"//"[/!])"<" { +<ReadFuncArgType>")"{BN}*({CCS}[*!]|{CPPC}[/!])"<" { lineCount(yyscanner); if (yyextra->currentArgumentContext==DefineEnd) { @@ -4329,7 +4347,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <CopyArgComment>^{B}*"*"+/{BN}+ <CopyArgComment>[^\n\\\@\*]+ { yyextra->fullArgString+=yytext; } -<CopyArgComment>"*/" { yyextra->fullArgString+=yytext; +<CopyArgComment>{CCE} { yyextra->fullArgString+=yytext; if (yyextra->lastCopyArgChar!=0) unput(yyextra->lastCopyArgChar); BEGIN( yyextra->lastCommentInArgContext ); @@ -4988,7 +5006,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) //addToBody(yytext); ++yyextra->curlyCount ; } -<SkipCurly>"}"/{BN}*("/*!"|"/**"|"//!"|"///")"<!--" | /* see bug710917 */ +<SkipCurly>"}"/{BN}*{DCOMM}"<!--" | /* see bug710917 */) <SkipCurly>"}" { //addToBody(yytext); if( yyextra->curlyCount ) @@ -5006,7 +5024,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN( yyextra->lastCurlyContext ) ; } } -<SkipCurly>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { +<SkipCurly>"}"{BN}*{DCOMM}"<" { lineCount(yyscanner); if ( yyextra->curlyCount ) { @@ -5037,7 +5055,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } } -<SkipCurlyEndDoc>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { // desc is followed by another one +<SkipCurlyEndDoc>"}"{BN}*{DCOMM}"<" { // desc is followed by another one yyextra->docBlockContext = SkipCurlyEndDoc; yyextra->docBlockInBody = FALSE; yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || @@ -5114,12 +5132,12 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) //addToBody(yytext); lineCount(yyscanner); } -<SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>"/*" { +<SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>{CCS} { //addToBody(yytext); yyextra->lastCContext = YY_START; BEGIN(SkipComment); } -<SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>"//" { +<SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>{CPPC} { //addToBody(yytext); yyextra->lastCContext = YY_START; BEGIN(SkipCxxComment); @@ -5172,7 +5190,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <SkipPHPString>\' { BEGIN( yyextra->lastStringContext ); } -<SkipString,SkipPHPString>"/*"|"*/"|"//" { } +<SkipString,SkipPHPString>{CCS}|{CCE}|{CPPC} { } <SkipString,SkipPHPString>\n { lineCount(yyscanner); } @@ -5397,7 +5415,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) lineCount(yyscanner); BEGIN( ClassVar ); } -<ClassVar>{SCOPENAME}{BN}*/"(" { +<ClassVar>{SCOPENAME}{BNopt}/"(" { if (yyextra->insideIDL && qstrncmp(yytext,"switch",6)==0 && !isId(yytext[6])) { // Corba IDL style union @@ -5511,8 +5529,8 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN( FindMembers ); } } -<CSConstraintType,CSConstraintName>"/**/" { /* empty comment */ } -<CSConstraintType,CSConstraintName>("/*"[*!]|"//"[/!])("<"?) { // special comment +<CSConstraintType,CSConstraintName>{CCS}{CCE} { /* empty comment */ } +<CSConstraintType,CSConstraintName>({CCS}[*!]|{CPPC}[/!])("<"?) { // special comment yyextra->fullArgString.resize(0); yyextra->lastCopyArgChar='#'; // end marker yyextra->lastCommentInArgContext=YY_START; @@ -5633,7 +5651,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } BEGIN( FindMembers ); } -<Bases,ClassVar>"///"/[^/] { +<Bases,ClassVar>{CPPC}"/"/[^/] { if (!yyextra->insideObjC) { REJECT; @@ -5649,9 +5667,9 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN( ReadBodyIntf ); } } -<Bases,ClassVar>("//"{B}*)?"/**"/[^/*] | -<Bases,ClassVar>("//"{B}*)?"/*!" | -<Bases,ClassVar>"//!" | +<Bases,ClassVar>({CPPC}{B}*)?{CCS}"*"/{NCOMM} | +<Bases,ClassVar>({CPPC}{B}*)?{CCS}"!" | +<Bases,ClassVar>{CPPC}"!" | <Bases,ClassVar>[\-+]{BN}* { if (!yyextra->insideObjC) { @@ -5955,8 +5973,8 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <Comment>{BN}+ { yyextra->current->program += yytext ; lineCount(yyscanner) ; } -<Comment>"/*" { yyextra->current->program += yytext ; } -<Comment>"//" { yyextra->current->program += yytext ; } +<Comment>{CCS} { yyextra->current->program += yytext ; } +<Comment>{CPPC} { yyextra->current->program += yytext ; } <Comment>{CMD}("code"|"verbatim") { yyextra->insideCode=TRUE; yyextra->current->program += yytext ; @@ -5966,12 +5984,12 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->program += yytext ; } <Comment>[^ \.\t\r\n\/\*]+ { yyextra->current->program += yytext ; } -<Comment>"*/" { yyextra->current->program += yytext ; +<Comment>{CCE} { yyextra->current->program += yytext ; if (!yyextra->insideCode) BEGIN( yyextra->lastContext ) ; } <Comment>. { yyextra->current->program += *yytext ; } -<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,SkipC11Inits,SkipC11Attribute,Bases,OldStyleArgs>("//"{B}*)?"/*!" { +<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,SkipC11Inits,SkipC11Attribute,Bases,OldStyleArgs>({CPPC}{B}*)?{CCS}"!" { //printf("Start doc block at %d\n",yyextra->yyLineNr); if (!yyextra->current->doc.isEmpty()) { @@ -6004,7 +6022,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) startCommentBlock(yyscanner,FALSE); BEGIN( DocBlock ); } -<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>"/**"[*]+{BL} { +<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>{CCS}"*"[*]+{BL} { bool javadocBanner = Config_getBool(JAVADOC_BANNER); lineCount(yyscanner); @@ -6043,7 +6061,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN( Comment ) ; } } -<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>("//"{B}*)?"/**"/[^/*] { +<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>({CPPC}{B}*)?{CCS}"*"/{NCOMM} { yyextra->lastDocContext = YY_START; //printf("Found comment block at %s:%d\n",yyextra->yyFileName,yyextra->yyLineNr); @@ -6070,7 +6088,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) startCommentBlock(yyscanner,FALSE); BEGIN( DocBlock ); } -<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"//!" { +<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>{CPPC}"!" { yyextra->lastDocContext = YY_START; if (yyextra->current_root->section & Entry::SCOPE_MASK) { @@ -6087,7 +6105,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) startCommentBlock(yyscanner,yyextra->current->brief.isEmpty()); BEGIN( DocLine ); } -<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"///"/[^/] { +<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>{CPPC}"/"/[^/] { yyextra->lastDocContext = YY_START; if (yyextra->current_root->section & Entry::SCOPE_MASK) { @@ -6213,8 +6231,8 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <CSAccessorDecl>"." {} <CSAccessorDecl>\n { lineCount(yyscanner); } <CSString>"\"" { BEGIN(CSAccessorDecl);} -<CSString>"//" {} // Otherwise the rule <*>"//" will kick in -<CSString>"/*" {} // Otherwise the rule <*>"/*" will kick in +<CSString>{CPPC} {} // Otherwise the rule <*>"//" will kick in +<CSString>{CCS} {} // Otherwise the rule <*>"/*" will kick in <CSString>\n { lineCount(yyscanner); } <CSString>"." {} @@ -6283,22 +6301,22 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) /**********************************************************************************/ /* ---- Single line comments ------ */ -<DocLine>[^\n]*"\n"[ \t]*"//"[/!][<]? { // continuation of multiline C++-style comment +<DocLine>[^\n]*"\n"[ \t]*{CPPC}[/!][<]? { // continuation of multiline C++-style comment yyextra->docBlock+=yytext; int markerLen = yytext[yyleng-1]=='<' ? 4 : 3; yyextra->docBlock.resize(yyextra->docBlock.length() - markerLen); lineCount(yyscanner); } -<DocLine>{B}*"///"[/]+{B}*/"\n" { // ignore marker line (see bug700345) +<DocLine>{B}*{CPPC}"/"[/]+{Bopt}/"\n" { // ignore marker line (see bug700345) handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); BEGIN( yyextra->docBlockContext ); } -<DocLine>[^\n]*/"\n"{B}*"//"[!/]{B}*{CMD}"}" { // next line is an end group marker, see bug 752712 +<DocLine>{NONLopt}/"\n"{B}*{CPPC}[!/]{B}*{CMD}"}" { // next line is an end group marker, see bug 752712 yyextra->docBlock+=yytext; handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); BEGIN( yyextra->docBlockContext ); } -<DocLine>[^\n]*/"\n" { // whole line +<DocLine>{NONLopt}/"\n" { // whole line yyextra->docBlock+=yytext; handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); BEGIN( yyextra->docBlockContext ); @@ -6306,7 +6324,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) /* ---- Comments blocks ------ */ -<DocBlock>"*"*"*/" { // end of comment block +<DocBlock>"*"*{CCE} { // end of comment block handleCommentBlock(yyscanner,yyextra->docBlock.data(),FALSE); BEGIN(yyextra->docBlockContext); } @@ -6316,17 +6334,17 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock+=indent; } -<DocBlock>^{B}*("//")?{B}*"*"+/[^//a-z_A-Z0-9*] { // start of a comment line +<DocBlock>^{B}*({CPPC})?{B}*"*"+/[^/a-z_A-Z0-9*] { // start of a comment line QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock+=indent; } -<DocBlock>^{B}*("//"){B}* { // strip embedded C++ comments if at the start of a line +<DocBlock>^{B}*({CPPC}){B}* { // strip embedded C++ comments if at the start of a line } -<DocBlock>"//" { // slashes in the middle of a comment block +<DocBlock>{CPPC} { // slashes in the middle of a comment block yyextra->docBlock+=yytext; } -<DocBlock>"/*" { // start of a new comment in the +<DocBlock>{CCS} { // start of a new comment in the // middle of a comment block yyextra->docBlock+=yytext; } @@ -6502,10 +6520,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN(DocBlock); } } -<DocCopyBlock>[^\<@/*\]~\$\\\n]+ { // any character that is not special +<DocCopyBlock>[^\<@/\*\]~\$\\\n]+ { // any character that is not special yyextra->docBlock+=yytext; } -<DocCopyBlock>"/*"|"*/"|"//" { +<DocCopyBlock>{CCS}|{CCE}|{CPPC} { if (yytext[1]=='*') { yyextra->nestedComment=TRUE; @@ -6622,7 +6640,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) lineCount(yyscanner); } } -<SkipCxxComment>.*/\n { +<SkipCxxComment>{ANYopt}/\n { BEGIN( yyextra->lastCContext ) ; } <SkipComment>[^\*\n]+ @@ -6680,12 +6698,12 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } <*>. -<SkipComment>"//"|"/*" -<*>"/*" { yyextra->lastCContext = YY_START ; +<SkipComment>{CPPC}|{CCS} +<*>{CCS} { yyextra->lastCContext = YY_START ; BEGIN( SkipComment ) ; } -<SkipComment>{B}*"*/" { BEGIN( yyextra->lastCContext ) ; } -<*>"//" { +<SkipComment>{B}*{CCE} { BEGIN( yyextra->lastCContext ) ; } +<*>{CPPC} { yyextra->lastCContext = YY_START ; BEGIN( SkipCxxComment ) ; } @@ -6846,7 +6864,8 @@ static void setContext(yyscan_t yyscanner) yyextra->insideObjC = yyextra->language==SrcLangExt_ObjC; yyextra->insideJS = yyextra->language==SrcLangExt_JS; yyextra->insideSlice = yyextra->language==SrcLangExt_Slice; - yyextra->insideCpp = yyextra->language==SrcLangExt_Cpp; + yyextra->insideCpp = (yyextra->language==SrcLangExt_Cpp || + yyextra->language==SrcLangExt_Lex); //printf("setContext(%s) yyextra->insideIDL=%d yyextra->insideJava=%d yyextra->insideCS=%d " // "yyextra->insideD=%d yyextra->insidePHP=%d yyextra->insideObjC=%d\n", // yyextra->yyFileName.data(),yyextra->insideIDL,yyextra->insideJava,yyextra->insideCS,yyextra->insideD,yyextra->insidePHP,yyextra->insideObjC @@ -7473,7 +7492,7 @@ bool COutlineParser::needsPreprocessing(const QCString &extension) const { QCString fe=extension.lower(); SrcLangExt lang = getLanguageFromFileName(extension); - return (SrcLangExt_Cpp == lang) || + return (SrcLangExt_Cpp == lang) || (SrcLangExt_Lex == lang) || !( fe==".java" || fe==".as" || fe==".d" || fe==".php" || fe==".php4" || fe==".inc" || fe==".phtml"|| fe==".php5" ); diff --git a/src/sqlcode.l b/src/sqlcode.l index c5af17f..b3a71d9 100644 --- a/src/sqlcode.l +++ b/src/sqlcode.l @@ -119,7 +119,7 @@ variable @{idchar}+ simplecomment --.* commentopen "/\*" -commentclose "\*/" +commentclose "\*\/" %x COMMENT diff --git a/src/types.h b/src/types.h index d34444c..bf24fd9 100644 --- a/src/types.h +++ b/src/types.h @@ -3,8 +3,8 @@ * Copyright (C) 1997-2015 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 + * 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. * @@ -20,7 +20,7 @@ #include <qcstring.h> /** @file - * @brief This file contains a number of basic enums and types. + * @brief This file contains a number of basic enums and types. */ /** Protection level of members */ @@ -57,18 +57,19 @@ enum SrcLangExt //SrcLangExt_Tcl = 0x08000, // no longer supported SrcLangExt_Markdown = 0x10000, SrcLangExt_SQL = 0x20000, - SrcLangExt_Slice = 0x40000 + SrcLangExt_Slice = 0x40000, + SrcLangExt_Lex = 0x80000 }; /** Grouping info */ -struct Grouping +struct Grouping { /** Grouping priority */ - enum GroupPri_t + enum GroupPri_t { GROUPING_LOWEST, - GROUPING_AUTO_WEAK = GROUPING_LOWEST, //!< membership in group was defined via \@weakgroup - GROUPING_AUTO_ADD, //!< membership in group was defined via \@add[to]group + GROUPING_AUTO_WEAK = GROUPING_LOWEST, //!< membership in group was defined via \@weakgroup + GROUPING_AUTO_ADD, //!< membership in group was defined via \@add[to]group GROUPING_AUTO_DEF, //!< membership in group was defined via \@defgroup GROUPING_AUTO_HIGHEST = GROUPING_AUTO_DEF, GROUPING_INGROUP, //!< membership in group was defined by \@ingroup @@ -87,7 +88,7 @@ struct Grouping return "@defgroup"; case GROUPING_INGROUP: return "@ingroup"; - } + } return "???"; } @@ -147,7 +148,7 @@ enum MemberListType MemberListType_allMembersList = 38, MemberListType_decDefineMembers = 39 + MemberListType_declarationLists, - MemberListType_decProtoMembers = 40 + MemberListType_declarationLists, + MemberListType_decProtoMembers = 40 + MemberListType_declarationLists, MemberListType_decTypedefMembers = 41 + MemberListType_declarationLists, MemberListType_decEnumMembers = 42 + MemberListType_declarationLists, MemberListType_decFuncMembers = 43 + MemberListType_declarationLists, diff --git a/src/util.cpp b/src/util.cpp index 1677b26..6599b42 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -342,6 +342,7 @@ int guessSection(const char *name) n.right(4)==".i++" || n.right(4)==".inl" || n.right(4)==".xml" || + n.right(4)==".lex" || n.right(4)==".sql" ) return Entry::SOURCE_SEC; if (n.right(2)==".h" || // header @@ -5515,6 +5516,7 @@ g_lang2extMap[] = { "xml", "xml", SrcLangExt_XML }, { "sql", "sql", SrcLangExt_SQL }, { "md", "md", SrcLangExt_Markdown }, + { "lex", "lex", SrcLangExt_Lex }, { 0, 0, (SrcLangExt)0 } }; @@ -5612,6 +5614,9 @@ void initDefaultExtensionMapping() updateLanguageMapping(".md", "md"); updateLanguageMapping(".markdown", "md"); updateLanguageMapping(".ice", "slice"); + updateLanguageMapping(".l", "lex"); + updateLanguageMapping(".doxygen_lex_c", "c"); // this is a placeholder so we can map initializations + // in the lex scanning to cpp } void addCodeOnlyMappings() @@ -6633,6 +6638,7 @@ QCString langToString(SrcLangExt lang) case SrcLangExt_SQL: return "SQL"; case SrcLangExt_Markdown: return "Markdown"; case SrcLangExt_Slice: return "Slice"; + case SrcLangExt_Lex: return "Lex"; } return "Unknown"; } |