aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/ScintillaHistory.html3
-rw-r--r--include/SciLexer.h1
-rw-r--r--include/Scintilla.iface1
-rw-r--r--lexers/LexCPP.cxx64
4 files changed, 67 insertions, 2 deletions
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
index 7b762a1b9..0f0434da9 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -473,6 +473,9 @@
C++ lexer can highlight task marker keywords in comments as SCE_C_TASKMARKER.
</li>
<li>
+ C++ lexer can optionally highlight escape sequences in strings as SCE_C_ESCAPESEQUENCE.
+ </li>
+ <li>
C++ lexer supports Go back quoted raw string literals with lexer.cpp.backquoted.strings option.
<a href="http://sourceforge.net/p/scintilla/feature-requests/1047/">Feature #1047.</a>
</li>
diff --git a/include/SciLexer.h b/include/SciLexer.h
index cd8b581aa..0438f545d 100644
--- a/include/SciLexer.h
+++ b/include/SciLexer.h
@@ -170,6 +170,7 @@
#define SCE_C_PREPROCESSORCOMMENTDOC 24
#define SCE_C_USERLITERAL 25
#define SCE_C_TASKMARKER 26
+#define SCE_C_ESCAPESEQUENCE 27
#define SCE_D_DEFAULT 0
#define SCE_D_COMMENT 1
#define SCE_D_COMMENTLINE 2
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index e5167902c..78cec5731 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -2716,6 +2716,7 @@ val SCE_C_PREPROCESSORCOMMENT=23
val SCE_C_PREPROCESSORCOMMENTDOC=24
val SCE_C_USERLITERAL=25
val SCE_C_TASKMARKER=26
+val SCE_C_ESCAPESEQUENCE=27
# Lexical states for SCLEX_D
lex D=SCLEX_D SCE_D_
val SCE_D_DEFAULT=0
diff --git a/lexers/LexCPP.cxx b/lexers/LexCPP.cxx
index 5bcd0b4df..36c4c8a1a 100644
--- a/lexers/LexCPP.cxx
+++ b/lexers/LexCPP.cxx
@@ -108,6 +108,40 @@ static void highlightTaskMarker(StyleContext &sc, LexAccessor &styler,
}
}
+struct EscapeSequence {
+ int digitsLeft;
+ CharacterSet setHexDigits;
+ CharacterSet setOctDigits;
+ CharacterSet setNoneNumeric;
+ CharacterSet *escapeSetValid;
+ EscapeSequence() {
+ digitsLeft = 0;
+ escapeSetValid = 0;
+ setHexDigits = CharacterSet(CharacterSet::setDigits, "ABCDEFabcdef");
+ setOctDigits = CharacterSet(CharacterSet::setNone, "01234567");
+ }
+ void resetEscapeState(int nextChar) {
+ digitsLeft = 0;
+ escapeSetValid = &setNoneNumeric;
+ if (nextChar == 'U') {
+ digitsLeft = 9;
+ escapeSetValid = &setHexDigits;
+ } else if (nextChar == 'u') {
+ digitsLeft = 5;
+ escapeSetValid = &setHexDigits;
+ } else if (nextChar == 'x') {
+ digitsLeft = 5;
+ escapeSetValid = &setHexDigits;
+ } else if (setOctDigits.Contains(nextChar)) {
+ digitsLeft = 3;
+ escapeSetValid = &setOctDigits;
+ }
+ }
+ bool atEscapeEnd(int currChar) const {
+ return (digitsLeft <= 0) || !escapeSetValid->Contains(currChar);
+ }
+};
+
static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace) {
std::string restOfLine;
int i =0;
@@ -237,6 +271,7 @@ struct OptionsCPP {
bool triplequotedStrings;
bool hashquotedStrings;
bool backQuotedStrings;
+ bool escapeSequence;
bool fold;
bool foldSyntaxBased;
bool foldComment;
@@ -256,6 +291,7 @@ struct OptionsCPP {
triplequotedStrings = false;
hashquotedStrings = false;
backQuotedStrings = false;
+ escapeSequence = false;
fold = false;
foldSyntaxBased = true;
foldComment = false;
@@ -305,6 +341,9 @@ struct OptionSetCPP : public OptionSet<OptionsCPP> {
DefineProperty("lexer.cpp.backquoted.strings", &OptionsCPP::backQuotedStrings,
"Set to 1 to enable highlighting of back-quoted raw strings .");
+ DefineProperty("lexer.cpp.escape.sequence", &OptionsCPP::escapeSequence,
+ "Set to 1 to enable highlighting of escape sequences in strings");
+
DefineProperty("fold", &OptionsCPP::fold);
DefineProperty("fold.cpp.syntax.based", &OptionsCPP::foldSyntaxBased,
@@ -363,6 +402,7 @@ class LexerCPP : public ILexerWithSubStyles {
std::map<std::string, std::string> preprocessorDefinitionsStart;
OptionsCPP options;
OptionSetCPP osCPP;
+ EscapeSequence escapeSeq;
SparseState<std::string> rawStringTerminators;
enum { activeFlag = 0x40 };
enum { ssIdentifier, ssDocKeyword };
@@ -836,9 +876,11 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
isIncludePreprocessor = false;
}
} else if (sc.ch == '\\') {
- if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
- sc.Forward();
+ if (options.escapeSequence) {
+ sc.SetState(SCE_C_ESCAPESEQUENCE|activitySet);
+ escapeSeq.resetEscapeState(sc.chNext);
}
+ sc.Forward(); // Skip all characters after the backslash
} else if (sc.ch == '\"') {
if (sc.chNext == '_') {
sc.ChangeState(SCE_C_USERLITERAL|activitySet);
@@ -847,6 +889,24 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle,
}
}
break;
+ case SCE_C_ESCAPESEQUENCE:
+ escapeSeq.digitsLeft--;
+ if (!escapeSeq.atEscapeEnd(sc.ch)) {
+ break;
+ }
+ if (sc.ch == '"') {
+ sc.SetState(SCE_C_STRING|activitySet);
+ sc.ForwardSetState(SCE_C_DEFAULT|activitySet);
+ } else if (sc.ch == '\\') {
+ escapeSeq.resetEscapeState(sc.chNext);
+ sc.Forward();
+ } else {
+ sc.SetState(SCE_C_STRING|activitySet);
+ if (sc.atLineEnd) {
+ sc.ChangeState(SCE_C_STRINGEOL|activitySet);
+ }
+ }
+ break;
case SCE_C_HASHQUOTEDSTRING:
if (sc.ch == '\\') {
if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {