diff options
Diffstat (limited to 'lexers/LexCPP.cxx')
-rw-r--r-- | lexers/LexCPP.cxx | 93 |
1 files changed, 72 insertions, 21 deletions
diff --git a/lexers/LexCPP.cxx b/lexers/LexCPP.cxx index 87482176d..f30cdfbdd 100644 --- a/lexers/LexCPP.cxx +++ b/lexers/LexCPP.cxx @@ -30,6 +30,7 @@ #include "LexerModule.h" #include "OptionSet.h" #include "SparseState.h" +#include "SubStyles.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -87,7 +88,8 @@ static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace std::string restOfLine; int i =0; char ch = styler.SafeGetCharAt(start, '\n'); - while ((ch != '\r') && (ch != '\n')) { + int endLine = styler.LineEnd(styler.GetLine(start)); + while (((start+i) < endLine) && (ch != '\r')) { char chNext = styler.SafeGetCharAt(start + i + 1, '\n'); if (ch == '/' && (chNext == '/' || chNext == '*')) break; @@ -310,7 +312,9 @@ struct OptionSetCPP : public OptionSet<OptionsCPP> { } }; -class LexerCPP : public ILexer { +static const char styleSubable[] = {SCE_C_IDENTIFIER, SCE_C_COMMENTDOCKEYWORD, 0}; + +class LexerCPP : public ILexerWithSubStyles { bool caseSensitive; CharacterSet setWord; CharacterSet setNegationOp; @@ -329,6 +333,8 @@ class LexerCPP : public ILexer { OptionSetCPP osCPP; SparseState<std::string> rawStringTerminators; enum { activeFlag = 0x40 }; + enum { ssIdentifier, ssDocKeyword }; + SubStyles subStyles; public: LexerCPP(bool caseSensitive_) : caseSensitive(caseSensitive_), @@ -336,7 +342,8 @@ public: setNegationOp(CharacterSet::setNone, "!"), setArithmethicOp(CharacterSet::setNone, "+-/*%"), setRelOp(CharacterSet::setNone, "=!<>"), - setLogicalOp(CharacterSet::setNone, "|&") { + setLogicalOp(CharacterSet::setNone, "|&"), + subStyles(styleSubable, 0x80, 0x40, activeFlag) { } virtual ~LexerCPP() { } @@ -344,7 +351,7 @@ public: delete this; } int SCI_METHOD Version() const { - return lvOriginal; + return lvSubStyles; } const char * SCI_METHOD PropertyNames() { return osCPP.PropertyNames(); @@ -367,6 +374,32 @@ public: return 0; } + int SCI_METHOD LineEndTypesSupported() { + return SC_LINE_END_TYPE_UNICODE; + }; + + int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) { + return subStyles.Allocate(styleBase, numberStyles); + } + int SCI_METHOD SubStylesStart(int styleBase) { + return subStyles.Start(styleBase); + } + int SCI_METHOD SubStylesLength(int styleBase) { + return subStyles.Length(styleBase); + } + void SCI_METHOD FreeSubStyles() { + subStyles.Free(); + } + void SCI_METHOD SetIdentifiers(int style, const char *identifiers) { + subStyles.SetIdentifiers(style, identifiers); + } + int SCI_METHOD DistanceToSecondaryStyles() { + return activeFlag; + } + const char * SCI_METHOD GetSubStyleBases() { + return styleSubable; + } + static ILexer *LexerFactoryCPP() { return new LexerCPP(true); } @@ -479,15 +512,10 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, (MaskActive(initStyle) == SCE_C_COMMENTLINEDOC)) { // Set continuationLine if last character of previous line is '\' if (lineCurrent > 0) { - int chBack = styler.SafeGetCharAt(startPos-1, 0); - int chBack2 = styler.SafeGetCharAt(startPos-2, 0); - int lineEndChar = '!'; - if (chBack2 == '\r' && chBack == '\n') { - lineEndChar = styler.SafeGetCharAt(startPos-3, 0); - } else if (chBack == '\n' || chBack == '\r') { - lineEndChar = chBack2; + int endLinePrevious = styler.LineEnd(lineCurrent - 1); + if (endLinePrevious > 0) { + continuationLine = styler.SafeGetCharAt(endLinePrevious-1) == '\\'; } - continuationLine = lineEndChar == '\\'; } } @@ -501,7 +529,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } } - StyleContext sc(startPos, length, initStyle, styler, 0x7f); + StyleContext sc(startPos, length, initStyle, styler, static_cast<char>(0xff)); LinePPState preproc = vlls.ForLine(lineCurrent); bool definitionsChanged = false; @@ -527,6 +555,11 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, int activitySet = preproc.IsInactive() ? activeFlag : 0; + const WordClassifier &classifierIdentifiers = subStyles.Classifier(SCE_C_IDENTIFIER); + const WordClassifier &classifierDocKeyWords = subStyles.Classifier(SCE_C_COMMENTDOCKEYWORD); + + int lineEndNext = styler.LineEnd(lineCurrent); + for (; sc.More();) { if (sc.atLineStart) { @@ -554,6 +587,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, if (sc.atLineEnd) { lineCurrent++; + lineEndNext = styler.LineEnd(lineCurrent); vlls.Add(lineCurrent, preproc); if (rawStringTerminator != "") { rawSTNew.Set(lineCurrent-1, rawStringTerminator); @@ -562,11 +596,13 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, // Handle line continuation generically. if (sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { + if (static_cast<int>((sc.currentPos+1)) >= lineEndNext) { lineCurrent++; + lineEndNext = styler.LineEnd(lineCurrent); vlls.Add(lineCurrent, preproc); sc.Forward(); if (sc.ch == '\r' && sc.chNext == '\n') { + // Even in UTF-8, \r and \n are separate sc.Forward(); } continuationLine = true; @@ -591,7 +627,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } break; case SCE_C_IDENTIFIER: - if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { + if (sc.atLineStart || sc.atLineEnd || !setWord.Contains(sc.ch) || (sc.ch == '.')) { char s[1000]; if (caseSensitive) { sc.GetCurrent(s, sizeof(s)); @@ -605,6 +641,11 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, sc.ChangeState(SCE_C_WORD2|activitySet); } else if (keywords4.InList(s)) { sc.ChangeState(SCE_C_GLOBALCLASS|activitySet); + } else { + int subStyle = classifierIdentifiers.ValueFor(s); + if (subStyle >= 0) { + sc.ChangeState(subStyle|activitySet); + } } const bool literalString = sc.ch == '\"'; if (literalString || sc.ch == '\'') { @@ -697,8 +738,15 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } else { sc.GetCurrentLowered(s, sizeof(s)); } - if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { + if (!IsASpace(sc.ch)) { sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet); + } else if (!keywords3.InList(s + 1)) { + int subStyleCDKW = classifierDocKeyWords.ValueFor(s+1); + if (subStyleCDKW >= 0) { + sc.ChangeState(subStyleCDKW|activitySet); + } else { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet); + } } sc.SetState(styleBeforeDCKeyword|activitySet); } @@ -755,7 +803,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, while ((sc.ch < 0x80) && islower(sc.ch)) sc.Forward(); // gobble regex flags sc.SetState(SCE_C_DEFAULT|activitySet); - } else if (sc.ch == '\\' && (sc.chNext != '\n' && sc.chNext != '\r')) { + } else if (sc.ch == '\\' && (static_cast<int>(sc.currentPos+1) < lineEndNext)) { // Gobble up the escaped character sc.Forward(); } else if (sc.ch == '[') { @@ -787,7 +835,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } break; case SCE_C_UUID: - if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { + if (sc.atLineEnd || sc.ch == ')') { sc.SetState(SCE_C_DEFAULT|activitySet); } } @@ -795,6 +843,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, if (sc.atLineEnd && !atLineEndBeforeSwitch) { // State exit processing consumed characters up to end of line. lineCurrent++; + lineEndNext = styler.LineEnd(lineCurrent); vlls.Add(lineCurrent, preproc); } @@ -816,7 +865,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } else { sc.SetState(SCE_C_NUMBER|activitySet); } - } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { + } else if (!sc.atLineEnd && (setWordStart.Contains(sc.ch) || (sc.ch == '@'))) { if (lastWordWasUUID) { sc.SetState(SCE_C_UUID|activitySet); lastWordWasUUID = false; @@ -945,7 +994,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } } } - } else if (isoperator(static_cast<char>(sc.ch))) { + } else if (isoperator(sc.ch)) { sc.SetState(SCE_C_OPERATOR|activitySet); } } @@ -980,6 +1029,7 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, int levelCurrent = SC_FOLDLEVELBASE; if (lineCurrent > 0) levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + unsigned int lineStartNext = styler.LineStart(lineCurrent+1); int levelMinCurrent = levelCurrent; int levelNext = levelCurrent; char chNext = styler[startPos]; @@ -992,7 +1042,7 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, int stylePrev = style; style = styleNext; styleNext = MaskActive(styler.StyleAt(i + 1)); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + bool atEOL = i == (lineStartNext-1); if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) { if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_C_COMMENTLINEDOC)) { levelNext++; @@ -1060,6 +1110,7 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, styler.SetLevel(lineCurrent, lev); } lineCurrent++; + lineStartNext = styler.LineStart(lineCurrent+1); levelCurrent = levelNext; levelMinCurrent = levelCurrent; if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) { |