Merge pull request #3587 from RaiKoHoff/Dev_RC

Current Lexilla dev (chg: HTML(PHP) Lexer)
This commit is contained in:
Pairi Daiza 2021-08-20 10:52:37 +02:00 committed by GitHub
commit f9dfcd1578
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 153 additions and 18 deletions

2
lexilla/.gitignore vendored
View File

@ -22,7 +22,7 @@ __pycache__
*.suo
*.aps
*.sln
*.vcxproj.*
*.vcxproj.user
*.idb
*.bsc
*.intermediate.manifest

View File

@ -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

View File

@ -567,6 +567,7 @@
<td>Bertrand Lacoste</td>
</tr><tr>
<td>Ivan Ustûžanin</td>
<td>Rainer Kottenhoff</td>
</tr>
</table>
<h2>Releases</h2>
@ -581,7 +582,29 @@
Allow F# triple-quoted strings to interpolate string literals.
<a href="https://github.com/ScintillaOrg/lexilla/issues/21">Issue #21</a>.
</li>
<ul>
<li>
Highlight F# printf specifiers in type-checked interpolated strings.
<a href="https://github.com/ScintillaOrg/lexilla/issues/24">Issue #24</a>.
</li>
<li>
Fix Markdown hang when document ends with "`", "*", "_", or similar.
<a href="https://github.com/ScintillaOrg/lexilla/issues/23">Issue #23</a>.
</li>
<li>
Treat '.' as an operator instead of part of a word for PHP.
<a href="https://github.com/ScintillaOrg/lexilla/issues/22">Issue #22</a>.
<a href="https://sourceforge.net/p/scintilla/bugs/2225/">Bug #2225</a>.
</li>
<li>
Check PHP numeric literals, showing invalid values with default style instead of numeric.
<a href="https://github.com/ScintillaOrg/lexilla/issues/20">Issue #20</a>.
</li>
<li>
For PHP, recognize start of comment after numeric literal.
<a href="https://github.com/ScintillaOrg/lexilla/issues/20">Issue #20</a>.
<a href="https://sourceforge.net/p/scintilla/bugs/2143/">Bug #2143</a>.
</li>
</ul>
<h3>
<a href="https://www.scintilla.org/lexilla511.zip">Release 5.1.1</a>
</h3>

View File

@ -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 == '*') {