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 | 67e5140823331a681c9a53df7eca7fa153b815c1 (patch) | |
| tree | a1c53616ad9010a645c29963aed04b057c9f2280 /lexers/LexCPP.cxx | |
| parent | 7500a9df933167477b6040e99209399cc85158e3 (diff) | |
| download | scintilla-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.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 == '\\') {  | 
