diff options
author | Neil <nyamatongwe@gmail.com> | 2014-04-19 08:12:30 +1000 |
---|---|---|
committer | Neil <nyamatongwe@gmail.com> | 2014-04-19 08:12:30 +1000 |
commit | e41bce45daca502a178554105d10a1f708e2f0a9 (patch) | |
tree | b7101e1576e8c9e1ad3eca6b7f3d927d57d81d75 /lexers/LexCPP.cxx | |
parent | d8c48fedec5b0e54e707f456b4781568e7546351 (diff) | |
download | scintilla-mirror-e41bce45daca502a178554105d10a1f708e2f0a9.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.cxx | 64 |
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 == '\\') { |