diff options
Diffstat (limited to 'src/libs/3rdparty/cplusplus/Lexer.cpp')
-rw-r--r-- | src/libs/3rdparty/cplusplus/Lexer.cpp | 71 |
1 files changed, 62 insertions, 9 deletions
diff --git a/src/libs/3rdparty/cplusplus/Lexer.cpp b/src/libs/3rdparty/cplusplus/Lexer.cpp index dc24f5e96c..92cfc5d6ec 100644 --- a/src/libs/3rdparty/cplusplus/Lexer.cpp +++ b/src/libs/3rdparty/cplusplus/Lexer.cpp @@ -25,6 +25,8 @@ #include "cppassert.h" +#include <QScopeGuard> + #include <cctype> using namespace CPlusPlus; @@ -213,14 +215,19 @@ void Lexer::scan_helper(Token *tok) return; } else if (!control() && isRawStringLiteral(s._tokenKind)) { tok->f.kind = s._tokenKind; - if (scanUntilRawStringLiteralEndSimple()) + const bool found = _expectedRawStringSuffix.isEmpty() + ? scanUntilRawStringLiteralEndSimple() : scanUntilRawStringLiteralEndPrecise(); + if (found) { + scanOptionalUserDefinedLiteral(tok); _state = 0; + } return; } else { // non-raw strings tok->f.joined = true; tok->f.kind = s._tokenKind; _state = 0; scanUntilQuote(tok, '"'); + scanOptionalUserDefinedLiteral(tok); return; } @@ -608,7 +615,12 @@ void Lexer::scan_helper(Token *tok) tok->f.kind = T_LESS_LESS; } else if (_yychar == '=') { yyinp(); - tok->f.kind = T_LESS_EQUAL; + if (_languageFeatures.cxx20Enabled && _yychar == '>') { + yyinp(); + tok->f.kind = T_LESS_EQUAL_GREATER; + } else { + tok->f.kind = T_LESS_EQUAL; + } } else if (_yychar == ':') { if (*(_currentChar+1) != ':' || *(_currentChar+2) == ':' || *(_currentChar+2) == '>') { yyinp(); @@ -744,6 +756,10 @@ void Lexer::scanStringLiteral(Token *tok, unsigned char hint) void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint) { + QScopeGuard cleanup([this] { _expectedRawStringSuffix.clear(); }); + if (control()) + cleanup.dismiss(); + const char *yytext = _currentChar; int delimLength = -1; @@ -766,6 +782,8 @@ void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint) tok->f.kind = T_ERROR; return; } + if (!control()) + _expectedRawStringSuffix.append(_yychar); yyinp(); } else { if (!closingDelimCandidate) { @@ -808,12 +826,36 @@ void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint) else tok->f.kind = T_RAW_STRING_LITERAL; - if (!control() && !closed) + if (!control() && !closed) { + cleanup.dismiss(); s._tokenKind = tok->f.kind; + _expectedRawStringSuffix.prepend(')'); + _expectedRawStringSuffix.append('"'); + } + if (closed) + scanOptionalUserDefinedLiteral(tok); +} + +bool Lexer::scanUntilRawStringLiteralEndPrecise() +{ + QByteArray slidingWindow; + slidingWindow.reserve(_expectedRawStringSuffix.size()); + while (_yychar) { + slidingWindow.append(_yychar); + if (slidingWindow.size() > _expectedRawStringSuffix.size()) + slidingWindow.remove(0, 1); + if (slidingWindow == _expectedRawStringSuffix) { + _expectedRawStringSuffix.clear(); + yyinp(); + return true; + } + yyinp(); + } + return false; } -// In the highlighting case we don't have any further information -// like the delimiter or its length, so just match for: ...)..." +// In case we don't have any further information +// like the delimiter or its length, just match for: ...)..." bool Lexer::scanUntilRawStringLiteralEndSimple() { bool closingParenthesisPassed = false; @@ -926,11 +968,15 @@ bool Lexer::scanOptionalIntegerSuffix(bool allowU) yyinp(); if (_yychar == 'l') yyinp(); + if (_yychar == 'u' || _yychar == 'U') + yyinp(); return true; case 'L': yyinp(); if (_yychar == 'L') yyinp(); + if (_yychar == 'u' || _yychar == 'U') + yyinp(); return true; default: return false; @@ -939,7 +985,7 @@ bool Lexer::scanOptionalIntegerSuffix(bool allowU) void Lexer::scanOptionalUserDefinedLiteral(Token *tok) { - if (_languageFeatures.cxx11Enabled && _yychar == '_') { + if (_languageFeatures.cxx11Enabled && (_yychar == '_' || std::isalpha(_yychar))) { tok->f.userDefinedLiteral = true; while (std::isalnum(_yychar) || _yychar == '_' || isByteOfMultiByteCodePoint(_yychar)) yyinp(); @@ -1030,7 +1076,7 @@ void Lexer::scanPreprocessorNumber(Token *tok, bool dotAlreadySkipped) yyinp(); if (_yychar == '+' || _yychar == '-') yyinp(); - } else if (std::isalnum(_yychar) || _yychar == '_' || _yychar == '.') { + } else if (std::isalnum(_yychar) || (_yychar == '\'') || _yychar == '_' || _yychar == '.') { yyinp(); } else { scanOptionalUserDefinedLiteral(tok); @@ -1052,10 +1098,17 @@ void Lexer::scanIdentifier(Token *tok, unsigned extraProcessedChars) yyinp(); } int yylen = _currentChar - yytext; - if (f._scanKeywords) + if (f._scanKeywords) { tok->f.kind = classify(yytext, yylen, _languageFeatures); - else + + if (tok->f.kind == T_FALSE || tok->f.kind == T_TRUE) { + if (control()) { + tok->number = control()->numericLiteral(yytext, yylen); + } + } + } else { tok->f.kind = T_IDENTIFIER; + } if (tok->f.kind == T_IDENTIFIER) { tok->f.kind = classifyOperator(yytext, yylen); |