aboutsummaryrefslogtreecommitdiffhomepage
path: root/lexers/LexCPP.cxx
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2014-04-19 08:12:30 +1000
committerNeil <nyamatongwe@gmail.com>2014-04-19 08:12:30 +1000
commit67e5140823331a681c9a53df7eca7fa153b815c1 (patch)
treea1c53616ad9010a645c29963aed04b057c9f2280 /lexers/LexCPP.cxx
parent7500a9df933167477b6040e99209399cc85158e3 (diff)
downloadscintilla-mirror-67e5140823331a681c9a53df7eca7fa153b815c1.tar.gz
Optionally highlight escape sequences in strings as SCE_C_ESCAPESEQUENCE.
From nkmathew.
Diffstat (limited to 'lexers/LexCPP.cxx')
-rw-r--r--lexers/LexCPP.cxx64
1 files changed, 62 insertions, 2 deletions
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 == '\\') {