From bbeaad7922660da8e17ba20aba2c1afe8931ff7e Mon Sep 17 00:00:00 2001 From: "METANEOCORTEX\\Kotti" Date: Fri, 20 Aug 2021 10:07:57 +0200 Subject: [PATCH] +upd: current Lexilla dev (chg: HTML(PHP) Lexer) --- lexilla/.gitignore | 2 +- lexilla/cppcheck.suppress | 7 +- lexilla/doc/LexillaHistory.html | 25 +++++- lexilla/lexers/LexHTML.cxx | 137 +++++++++++++++++++++++++++++--- 4 files changed, 153 insertions(+), 18 deletions(-) diff --git a/lexilla/.gitignore b/lexilla/.gitignore index a5292f2c5..635587318 100644 --- a/lexilla/.gitignore +++ b/lexilla/.gitignore @@ -22,7 +22,7 @@ __pycache__ *.suo *.aps *.sln -*.vcxproj.* +*.vcxproj.user *.idb *.bsc *.intermediate.manifest diff --git a/lexilla/cppcheck.suppress b/lexilla/cppcheck.suppress index ed034fa8e..819050d17 100644 --- a/lexilla/cppcheck.suppress +++ b/lexilla/cppcheck.suppress @@ -36,10 +36,8 @@ constParameter:lexilla/lexers/LexCoffeeScript.cxx constParameter:lexilla/lexers/LexCPP.cxx variableScope:lexilla/lexers/LexCSS.cxx variableScope:lexilla/lexers/LexDataflex.cxx -knownConditionTrueFalse:lexilla/lexers/LexECL.cxx variableScope:lexilla/lexers/LexErlang.cxx knownConditionTrueFalse:lexilla/lexers/LexErlang.cxx -knownConditionTrueFalse:lexilla/lexers/LexEScript.cxx constParameter:lexilla/lexers/LexFortran.cxx redundantCondition:lexilla/lexers/LexFSharp.cxx knownConditionTrueFalse:lexilla/lexers/LexFSharp.cxx @@ -91,9 +89,7 @@ constParameter:lexilla/lexers/LexTADS3.cxx invalidscanf:lexilla/lexers/LexTCMD.cxx constParameter:lexilla/lexers/LexTeX.cxx variableScope:lexilla/lexers/LexTeX.cxx -knownConditionTrueFalse:lexilla/lexers/LexTxt2tags.cxx constParameter:lexilla/lexers/LexVerilog.cxx -knownConditionTrueFalse:lexilla/lexers/LexVerilog.cxx constParameter:lexilla/lexers/LexVHDL.cxx shadowVariable:lexilla/lexers/LexVHDL.cxx unreadVariable:lexilla/lexers/LexVHDL.cxx @@ -141,3 +137,6 @@ redundantAssignment:lexilla/lexers/LexCPP.cxx // Suppress everything in catch.hpp as won't be changing *:lexilla/test/unit/catch.hpp +// cppcheck gives up inside catch.hpp +*:lexilla/test/unit/UnitTester.cxx +*:lexilla/test/unit/unitTest.cxx diff --git a/lexilla/doc/LexillaHistory.html b/lexilla/doc/LexillaHistory.html index fe4008a49..303cadf2b 100644 --- a/lexilla/doc/LexillaHistory.html +++ b/lexilla/doc/LexillaHistory.html @@ -567,6 +567,7 @@ Bertrand Lacoste Ivan Ustûžanin + Rainer Kottenhoff

Releases

@@ -581,7 +582,29 @@ Allow F# triple-quoted strings to interpolate string literals. Issue #21. -

Release 5.1.1

diff --git a/lexilla/lexers/LexHTML.cxx b/lexilla/lexers/LexHTML.cxx index 902f25f53..104cec90f 100644 --- a/lexilla/lexers/LexHTML.cxx +++ b/lexilla/lexers/LexHTML.cxx @@ -524,6 +524,119 @@ bool isDjangoBlockEnd(const int ch, const int chNext, const std::string &blockTy } } +class PhpNumberState { + enum NumberBase { BASE_10 = 0, BASE_2, BASE_8, BASE_16 }; + static constexpr const char *const digitList[] = { "_0123456789", "_01", "_01234567", "_0123456789abcdefABCDEF" }; + + NumberBase base = BASE_10; + bool decimalPart = false; + bool exponentPart = false; + bool invalid = false; + bool finished = false; + + bool leadingZero = false; + bool invalidBase8 = false; + + bool betweenDigits = false; + bool decimalChar = false; + bool exponentChar = false; + +public: + inline bool isInvalid() { return invalid; } + inline bool isFinished() { return finished; } + + bool init(int ch, int chPlus1, int chPlus2) { + base = BASE_10; + decimalPart = false; + exponentPart = false; + invalid = false; + finished = false; + + leadingZero = false; + invalidBase8 = false; + + betweenDigits = false; + decimalChar = false; + exponentChar = false; + + if (ch == '.' && strchr(digitList[BASE_10] + !betweenDigits, chPlus1) != nullptr) { + decimalPart = true; + betweenDigits = true; + } else if (ch == '0' && (chPlus1 == 'b' || chPlus1 == 'B')) { + base = BASE_2; + } else if (ch == '0' && (chPlus1 == 'o' || chPlus1 == 'O')) { + base = BASE_8; + } else if (ch == '0' && (chPlus1 == 'x' || chPlus1 == 'X')) { + base = BASE_16; + } else if (strchr(digitList[BASE_10] + !betweenDigits, ch) != nullptr) { + leadingZero = ch == '0'; + betweenDigits = true; + check(chPlus1, chPlus2); + if (finished && leadingZero) { + // single zero should be base 10 + base = BASE_10; + } + } else { + return false; + } + return true; + } + + bool check(int ch, int chPlus1) { + if (strchr(digitList[base] + !betweenDigits, ch) != nullptr) { + if (leadingZero) { + invalidBase8 = invalidBase8 || strchr(digitList[BASE_8] + !betweenDigits, ch) == nullptr; + } + + betweenDigits = ch != '_'; + decimalChar = false; + exponentChar = false; + } else if (ch == '_') { + invalid = true; + + betweenDigits = false; + decimalChar = false; + // exponentChar is unchanged + } else if (base == BASE_10 && ch == '.' && ( + !(decimalPart || exponentPart) || strchr(digitList[BASE_10] + !betweenDigits, chPlus1) != nullptr) + ) { + invalid = invalid || !betweenDigits || decimalPart || exponentPart; + decimalPart = true; + + betweenDigits = false; + decimalChar = true; + exponentChar = false; + } else if (base == BASE_10 && (ch == 'e' || ch == 'E')) { + invalid = invalid || !(betweenDigits || decimalChar) || exponentPart; + exponentPart = true; + + betweenDigits = false; + decimalChar = false; + exponentChar = true; + } else if (base == BASE_10 && (ch == '-' || ch == '+') && exponentChar) { + invalid = invalid || strchr(digitList[BASE_10] + !betweenDigits, chPlus1) == nullptr; + + betweenDigits = false; + decimalChar = false; + // exponentChar is unchanged + } else if (IsPhpWordChar(ch)) { + invalid = true; + + betweenDigits = false; + decimalChar = false; + exponentChar = false; + } else { + invalid = invalid || !(betweenDigits || decimalChar); + finished = true; + if (base == BASE_10 && leadingZero && !decimalPart && !exponentPart) { + base = BASE_8; + invalid = invalid || invalidBase8; + } + } + return finished; + } +}; + bool isPHPStringState(int state) { return (state == SCE_HPHP_HSTRING) || @@ -960,6 +1073,7 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int } styler.StartAt(startPos); std::string prevWord; + PhpNumberState phpNumber; std::string phpStringDelimiter; int StateToPrint = initStyle; int state = stateForPrintState(StateToPrint); @@ -2273,7 +2387,7 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int break; ///////////// start - PHP state handling case SCE_HPHP_WORD: - if (!IsAWordChar(ch)) { + if (!IsPhpWordChar(ch)) { classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler); if (ch == '/' && chNext == '*') { i++; @@ -2306,15 +2420,9 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int } break; case SCE_HPHP_NUMBER: - // recognize bases 8,10 or 16 integers OR floating-point numbers - if (!IsADigit(ch) - && strchr(".xXabcdefABCDEF_", ch) == NULL - && ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) { - styler.ColourTo(i - 1, SCE_HPHP_NUMBER); - if (IsOperator(ch)) - state = SCE_HPHP_OPERATOR; - else - state = SCE_HPHP_DEFAULT; + if (phpNumber.check(chNext, chNext2)) { + styler.ColourTo(i, phpNumber.isInvalid() ? SCE_HPHP_DEFAULT : SCE_HPHP_NUMBER); + state = SCE_HPHP_DEFAULT; } break; case SCE_HPHP_VARIABLE: @@ -2395,8 +2503,13 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int case SCE_HPHP_OPERATOR: case SCE_HPHP_DEFAULT: styler.ColourTo(i - 1, StateToPrint); - if (IsADigit(ch) || (ch == '.' && IsADigit(chNext))) { - state = SCE_HPHP_NUMBER; + if (phpNumber.init(ch, chNext, chNext2)) { + if (phpNumber.isFinished()) { + styler.ColourTo(i, phpNumber.isInvalid() ? SCE_HPHP_DEFAULT : SCE_HPHP_NUMBER); + state = SCE_HPHP_DEFAULT; + } else { + state = SCE_HPHP_NUMBER; + } } else if (IsAWordStart(ch)) { state = SCE_HPHP_WORD; } else if (ch == '/' && chNext == '*') {