diff options
Diffstat (limited to 'lexers')
-rw-r--r-- | lexers/LexAU3.cxx | 2 | ||||
-rw-r--r-- | lexers/LexCPP.cxx | 21 | ||||
-rw-r--r-- | lexers/LexConf.cxx | 2 | ||||
-rw-r--r-- | lexers/LexHTML.cxx | 12 | ||||
-rw-r--r-- | lexers/LexLua.cxx | 82 | ||||
-rw-r--r-- | lexers/LexMagik.cxx | 2 | ||||
-rw-r--r-- | lexers/LexMarkdown.cxx | 23 | ||||
-rw-r--r-- | lexers/LexModula.cxx | 4 | ||||
-rw-r--r-- | lexers/LexOthers.cxx | 250 | ||||
-rw-r--r-- | lexers/LexPerl.cxx | 371 | ||||
-rw-r--r-- | lexers/LexPowerPro.cxx | 2 | ||||
-rw-r--r-- | lexers/LexTeX.cxx | 2 | ||||
-rw-r--r-- | lexers/LexVHDL.cxx | 2 |
13 files changed, 633 insertions, 142 deletions
diff --git a/lexers/LexAU3.cxx b/lexers/LexAU3.cxx index 72c918f07..e9ab75772 100644 --- a/lexers/LexAU3.cxx +++ b/lexers/LexAU3.cxx @@ -241,7 +241,7 @@ static void ColouriseAU3Doc(unsigned int startPos, if (IsAWordChar(sc.ch) || sc.ch == '}') { strcpy(s_save,s); - int tp = strlen(s_save); + int tp = static_cast<int>(strlen(s_save)); if (tp < 99) { s_save[tp] = static_cast<char>(tolower(sc.ch)); s_save[tp+1] = '\0'; diff --git a/lexers/LexCPP.cxx b/lexers/LexCPP.cxx index 22477c32f..51fd19255 100644 --- a/lexers/LexCPP.cxx +++ b/lexers/LexCPP.cxx @@ -803,15 +803,20 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, sc.SetState(SCE_C_REGEX|activitySet); // JavaScript's RegEx } else if (sc.ch == '\"') { if (sc.chPrev == 'R') { - sc.SetState(SCE_C_STRINGRAW|activitySet); - rawStringTerminator = ")"; - for (int termPos = sc.currentPos + 1;; termPos++) { - char chTerminator = styler.SafeGetCharAt(termPos, '('); - if (chTerminator == '(') - break; - rawStringTerminator += chTerminator; + styler.Flush(); + if (MaskActive(styler.StyleAt(sc.currentPos - 1)) == SCE_C_STRINGRAW) { + sc.SetState(SCE_C_STRINGRAW|activitySet); + rawStringTerminator = ")"; + for (int termPos = sc.currentPos + 1;; termPos++) { + char chTerminator = styler.SafeGetCharAt(termPos, '('); + if (chTerminator == '(') + break; + rawStringTerminator += chTerminator; + } + rawStringTerminator += '\"'; + } else { + sc.SetState(SCE_C_STRING|activitySet); } - rawStringTerminator += '\"'; } else { sc.SetState(SCE_C_STRING|activitySet); } diff --git a/lexers/LexConf.cxx b/lexers/LexConf.cxx index 5e1bd199e..23ed5a6c8 100644 --- a/lexers/LexConf.cxx +++ b/lexers/LexConf.cxx @@ -2,7 +2,7 @@ /** @file LexConf.cxx ** Lexer for Apache Configuration Files. ** - ** First working version contributed by Ahmad Zawawi <zeus_go64@hotmail.com> on October 28, 2000. + ** First working version contributed by Ahmad Zawawi <ahmad.zawawi@gmail.com> on October 28, 2000. ** i created this lexer because i needed something pretty when dealing ** when Apache Configuration files... **/ diff --git a/lexers/LexHTML.cxx b/lexers/LexHTML.cxx index b54401805..a20796387 100644 --- a/lexers/LexHTML.cxx +++ b/lexers/LexHTML.cxx @@ -57,7 +57,7 @@ inline bool IsOperator(int ch) { } static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int end, char *s, size_t len) { - size_t i = 0; + unsigned int i = 0; for (; (i < end - start + 1) && (i < len-1); i++) { s[i] = static_cast<char>(MakeLowerCase(styler[start + i])); } @@ -66,7 +66,7 @@ static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int en static const char *GetNextWord(Accessor &styler, unsigned int start, char *s, size_t sLen) { - size_t i = 0; + unsigned int i = 0; for (; i < sLen-1; i++) { char ch = static_cast<char>(styler.SafeGetCharAt(start + i)); if ((i == 0) && !IsAWordStart(ch)) @@ -960,8 +960,8 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty styler.ColourTo(i, SCE_H_ASP); if (ch != '%' && ch != '$' && ch != '/') { - i += strlen(makoBlockType); - visibleChars += strlen(makoBlockType); + i += static_cast<int>(strlen(makoBlockType)); + visibleChars += static_cast<int>(strlen(makoBlockType)); if (keywords4.InList(makoBlockType)) styler.ColourTo(i, SCE_HP_WORD); else @@ -1983,7 +1983,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty styler.ColourTo(i, StateToPrint); state = SCE_HPHP_DEFAULT; } else if (isLineEnd(chPrev)) { - const int psdLength = strlen(phpStringDelimiter); + const int psdLength = static_cast<int>(strlen(phpStringDelimiter)); const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); if (isLineEnd(chAfterPsd) || @@ -2006,7 +2006,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty state = SCE_HPHP_DEFAULT; } } else if (isLineEnd(chPrev) && styler.Match(i, phpStringDelimiter)) { - const int psdLength = strlen(phpStringDelimiter); + const int psdLength = static_cast<int>(strlen(phpStringDelimiter)); const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); if (isLineEnd(chAfterPsd) || diff --git a/lexers/LexLua.cxx b/lexers/LexLua.cxx index 1dc9d4058..9e48efcd9 100644 --- a/lexers/LexLua.cxx +++ b/lexers/LexLua.cxx @@ -59,7 +59,7 @@ static void ColouriseLuaDoc( // Accepts accented characters CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); // Not exactly following number definition (several dots are seen as OK, etc.) // but probably enough in most cases. [pP] is for hex floats. CharacterSet setNumber(CharacterSet::setDigits, ".-+abcdefpABCDEFP"); @@ -71,7 +71,7 @@ static void ColouriseLuaDoc( // Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level, // if we are inside such a string. Block comment was introduced in Lua 5.0, // blocks with separators [=[ ... ]=] in Lua 5.1. - // Continuation of a string (\* whitespace escaping) is controlled by stringWs. + // Continuation of a string (\z whitespace escaping) is controlled by stringWs. int nestLevel = 0; int sepCount = 0; int stringWs = 0; @@ -130,6 +130,61 @@ static void ColouriseLuaDoc( // Determine if the current state should terminate. if (sc.state == SCE_LUA_OPERATOR) { + if (sc.ch == ':' && sc.chPrev == ':') { // :: <label> :: forward scan + sc.Forward(); + int ln = 0, maxln = startPos + length - sc.currentPos; + int c; + while (ln < maxln) { // determine line extent + c = sc.GetRelative(ln); + if (c == '\r' || c == '\n') + break; + ln++; + } + maxln = ln; ln = 0; + while (ln < maxln) { // skip over spaces/tabs + if (!IsASpaceOrTab(sc.GetRelative(ln))) + break; + ln++; + } + int ws1 = ln; + if (setWordStart.Contains(sc.GetRelative(ln))) { + int i = 0; + char s[100]; + while (ln < maxln) { // get potential label + c = sc.GetRelative(ln); + if (!setWord.Contains(c)) + break; + if (i < 90) + s[i++] = c; + ln++; + } + s[i] = '\0'; int lbl = ln; + if (!keywords.InList(s)) { + while (ln < maxln) { // skip over spaces/tabs + if (!IsASpaceOrTab(sc.GetRelative(ln))) + break; + ln++; + } + int ws2 = ln - lbl; + if (sc.GetRelative(ln) == ':' && sc.GetRelative(ln + 1) == ':') { + // final :: found, complete valid label construct + sc.ChangeState(SCE_LUA_LABEL); + if (ws1) { + sc.SetState(SCE_LUA_DEFAULT); + sc.Forward(ws1); + } + sc.SetState(SCE_LUA_LABEL); + sc.Forward(lbl - ws1); + if (ws2) { + sc.SetState(SCE_LUA_DEFAULT); + sc.Forward(ws2); + } + sc.SetState(SCE_LUA_LABEL); + sc.Forward(2); + } + } + } + } sc.SetState(SCE_LUA_DEFAULT); } else if (sc.state == SCE_LUA_NUMBER) { // We stop the number definition on non-numerical non-dot non-eEpP non-sign non-hexdigit char @@ -140,11 +195,26 @@ static void ColouriseLuaDoc( sc.SetState(SCE_LUA_DEFAULT); } } else if (sc.state == SCE_LUA_IDENTIFIER) { - if (!setWord.Contains(sc.ch) || sc.Match('.', '.')) { + if (!(setWord.Contains(sc.ch) || sc.ch == '.') || sc.Match('.', '.')) { char s[100]; sc.GetCurrent(s, sizeof(s)); if (keywords.InList(s)) { sc.ChangeState(SCE_LUA_WORD); + if (strcmp(s, "goto") == 0) { // goto <label> forward scan + sc.SetState(SCE_LUA_DEFAULT); + while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) + sc.Forward(); + if (setWordStart.Contains(sc.ch)) { + sc.SetState(SCE_LUA_LABEL); + sc.Forward(); + while (setWord.Contains(sc.ch)) + sc.Forward(); + sc.GetCurrent(s, sizeof(s)); + if (keywords.InList(s)) + sc.ChangeState(SCE_LUA_WORD); + } + sc.SetState(SCE_LUA_DEFAULT); + } } else if (keywords2.InList(s)) { sc.ChangeState(SCE_LUA_WORD2); } else if (keywords3.InList(s)) { @@ -174,7 +244,7 @@ static void ColouriseLuaDoc( if (sc.ch == '\\') { if (setEscapeSkip.Contains(sc.chNext)) { sc.Forward(); - } else if (sc.chNext == '*') { + } else if (sc.chNext == 'z') { sc.Forward(); stringWs = 0x100; } @@ -192,7 +262,7 @@ static void ColouriseLuaDoc( if (sc.ch == '\\') { if (setEscapeSkip.Contains(sc.chNext)) { sc.Forward(); - } else if (sc.chNext == '*') { + } else if (sc.chNext == 'z') { sc.Forward(); stringWs = 0x100; } @@ -269,7 +339,7 @@ static void ColouriseLuaDoc( } } - if (setWord.Contains(sc.chPrev)) { + if (setWord.Contains(sc.chPrev) || sc.chPrev == '.') { char s[100]; sc.GetCurrent(s, sizeof(s)); if (keywords.InList(s)) { diff --git a/lexers/LexMagik.cxx b/lexers/LexMagik.cxx index 45390d45d..992080dd8 100644 --- a/lexers/LexMagik.cxx +++ b/lexers/LexMagik.cxx @@ -233,7 +233,7 @@ static void ColouriseMagikDoc(unsigned int startPos, int length, int initStyle, } if(characters.InList(keyword)) { - sc.Forward(strlen(keyword)); + sc.Forward(static_cast<int>(strlen(keyword))); } else { sc.Forward(); } diff --git a/lexers/LexMarkdown.cxx b/lexers/LexMarkdown.cxx index 393712033..a92697707 100644 --- a/lexers/LexMarkdown.cxx +++ b/lexers/LexMarkdown.cxx @@ -113,6 +113,10 @@ static bool HasPrevLineContent(StyleContext &sc) { return false; } +static bool AtTermStart(StyleContext &sc) { + return sc.currentPos == 0 || isspacechar(sc.chPrev); +} + static bool IsValidHrule(const unsigned int endPos, StyleContext &sc) { int c, count = 1; unsigned int i = 0; @@ -373,35 +377,38 @@ static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle } } // Code - also a special case for alternate inside spacing - if (sc.Match("``") && sc.GetRelative(3) != ' ') { + if (sc.Match("``") && sc.GetRelative(3) != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_CODE2); sc.Forward(); } - else if (sc.ch == '`' && sc.chNext != ' ') { + else if (sc.ch == '`' && sc.chNext != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_CODE); } // Strong - else if (sc.Match("**") && sc.GetRelative(2) != ' ') { + else if (sc.Match("**") && sc.GetRelative(2) != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_STRONG1); sc.Forward(); } - else if (sc.Match("__") && sc.GetRelative(2) != ' ') { + else if (sc.Match("__") && sc.GetRelative(2) != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_STRONG2); sc.Forward(); } // Emphasis - else if (sc.ch == '*' && sc.chNext != ' ') + else if (sc.ch == '*' && sc.chNext != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_EM1); - else if (sc.ch == '_' && sc.chNext != ' ') + } + else if (sc.ch == '_' && sc.chNext != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_EM2); + } // Strikeout - else if (sc.Match("~~") && sc.GetRelative(2) != ' ') { + else if (sc.Match("~~") && sc.GetRelative(2) != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_STRIKEOUT); sc.Forward(); } // Beginning of line - else if (IsNewline(sc.ch)) + else if (IsNewline(sc.ch)) { sc.SetState(SCE_MARKDOWN_LINE_BEGIN); + } } // Advance if not holding back the cursor for this iteration. if (!freezeCursor) diff --git a/lexers/LexModula.cxx b/lexers/LexModula.cxx index 1d0361165..cc5847fd6 100644 --- a/lexers/LexModula.cxx +++ b/lexers/LexModula.cxx @@ -92,7 +92,7 @@ static inline bool checkStatement( Accessor &styler, int &curPos, const char *stt, bool spaceAfter = true ) { - int len = strlen( stt ); + int len = static_cast<int>(strlen( stt )); int i; for( i = 0; i < len; i++ ) { if( styler.SafeGetCharAt( curPos + i ) != stt[i] ) { @@ -113,7 +113,7 @@ static inline bool checkEndSemicolon( int &curPos, int endPos ) { const char *stt = "END"; - int len = strlen( stt ); + int len = static_cast<int>(strlen( stt )); int i; for( i = 0; i < len; i++ ) { if( styler.SafeGetCharAt( curPos + i ) != stt[i] ) { diff --git a/lexers/LexOthers.cxx b/lexers/LexOthers.cxx index bc2c28773..720d97930 100644 --- a/lexers/LexOthers.cxx +++ b/lexers/LexOthers.cxx @@ -1162,21 +1162,71 @@ static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordLi } } -static int isSpecial(char s) { - return (s == '\\') || (s == ',') || (s == ';') || (s == '\'') || (s == ' ') || - (s == '\"') || (s == '`') || (s == '^') || (s == '~'); +static bool latexIsSpecial(int ch) { + return (ch == '#') || (ch == '$') || (ch == '%') || (ch == '&') || (ch == '_') || + (ch == '{') || (ch == '}') || (ch == ' '); } -static int isTag(int start, Accessor &styler) { - char s[6]; - unsigned int i = 0, e = 1; - while (i < 5 && e) { - s[i] = styler[start + i]; +static bool latexIsBlank(int ch) { + return (ch == ' ') || (ch == '\t'); +} + +static bool latexIsBlankAndNL(int ch) { + return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'); +} + +static bool latexIsLetter(int ch) { + return isascii(ch) && isalpha(ch); +} + +static bool latexIsTagValid(int &i, int l, Accessor &styler) { + while (i < l) { + if (styler.SafeGetCharAt(i) == '{') { + while (i < l) { + i++; + if (styler.SafeGetCharAt(i) == '}') { + return true; + } else if (!latexIsLetter(styler.SafeGetCharAt(i)) && + styler.SafeGetCharAt(i)!='*') { + return false; + } + } + } else if (!latexIsBlank(styler.SafeGetCharAt(i))) { + return false; + } i++; - e = (strchr("{ \t", styler[start + i]) == NULL); + } + return false; +} + +static bool latexNextNotBlankIs(int i, int l, Accessor &styler, char needle) { + char ch; + while (i < l) { + ch = styler.SafeGetCharAt(i); + if (!latexIsBlankAndNL(ch) && ch != '*') { + if (ch == needle) + return true; + else + return false; + } + i++; + } + return false; +} + +static bool latexLastWordIs(int start, Accessor &styler, const char *needle) { + unsigned int i = 0; + unsigned int l = static_cast<unsigned int>(strlen(needle)); + int ini = start-l+1; + char s[32]; + + while (i < l && i < 32) { + s[i] = styler.SafeGetCharAt(ini + i); + i++; } s[i] = '\0'; - return (strcmp(s, "begin") == 0) || (strcmp(s, "end") == 0); + + return (strcmp(s, needle) == 0); } static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle, @@ -1185,39 +1235,51 @@ static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle, styler.StartAt(startPos); int state = initStyle; - char chNext = styler[startPos]; + char chNext = styler.SafeGetCharAt(startPos); styler.StartSegment(startPos); int lengthDoc = startPos + length; + char chVerbatimDelim = '\0'; for (int i = startPos; i < lengthDoc; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); i++; + chNext = styler.SafeGetCharAt(i + 1); continue; } + switch (state) { case SCE_L_DEFAULT : switch (ch) { case '\\' : styler.ColourTo(i - 1, state); - if (isSpecial(styler[i + 1])) { - styler.ColourTo(i + 1, SCE_L_COMMAND); - i++; - chNext = styler.SafeGetCharAt(i + 1); + if (latexIsSpecial(chNext)) { + state = SCE_L_SPECIAL; } else { - if (isTag(i + 1, styler)) - state = SCE_L_TAG; - else + if (latexIsLetter(chNext)) { state = SCE_L_COMMAND; + } else { + if (chNext == '(' || chNext == '[') { + styler.ColourTo(i-1, state); + styler.ColourTo(i+1, SCE_L_SHORTCMD); + state = SCE_L_MATH; + if (chNext == '[') + state = SCE_L_MATH2; + i++; + chNext = styler.SafeGetCharAt(i+1); + } else { + state = SCE_L_SHORTCMD; + } + } } break; case '$' : styler.ColourTo(i - 1, state); state = SCE_L_MATH; if (chNext == '$') { + state = SCE_L_MATH2; i++; chNext = styler.SafeGetCharAt(i + 1); } @@ -1228,29 +1290,124 @@ static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle, break; } break; + case SCE_L_ERROR: + styler.ColourTo(i-1, state); + state = SCE_L_DEFAULT; + break; + case SCE_L_SPECIAL: + case SCE_L_SHORTCMD: + styler.ColourTo(i, state); + state = SCE_L_DEFAULT; + break; case SCE_L_COMMAND : - if (chNext == '[' || chNext == '{' || chNext == '}' || - chNext == ' ' || chNext == '\r' || chNext == '\n') { + if (!latexIsLetter(chNext)) { styler.ColourTo(i, state); state = SCE_L_DEFAULT; - i++; - chNext = styler.SafeGetCharAt(i + 1); + if (latexNextNotBlankIs(i+1, lengthDoc, styler, '[' )) { + state = SCE_L_CMDOPT; + } else if (latexLastWordIs(i, styler, "\\begin")) { + state = SCE_L_TAG; + } else if (latexLastWordIs(i, styler, "\\end")) { + state = SCE_L_TAG2; + } else if (latexLastWordIs(i, styler, "\\verb") && + chNext != '*' && chNext != ' ') { + chVerbatimDelim = chNext; + state = SCE_L_VERBATIM; + } } break; + case SCE_L_CMDOPT : + if (ch == ']') { + styler.ColourTo(i, state); + state = SCE_L_DEFAULT; + } + break; case SCE_L_TAG : - if (ch == '}') { + if (latexIsTagValid(i, lengthDoc, styler)) { + styler.ColourTo(i, state); + state = SCE_L_DEFAULT; + if (latexLastWordIs(i, styler, "{verbatim}")) { + state = SCE_L_VERBATIM; + } else if (latexLastWordIs(i, styler, "{comment}")) { + state = SCE_L_COMMENT2; + } else if (latexLastWordIs(i, styler, "{math}")) { + state = SCE_L_MATH; + } else if (latexLastWordIs(i, styler, "{displaymath}")) { + state = SCE_L_MATH2; + } else if (latexLastWordIs(i, styler, "{equation}")) { + state = SCE_L_MATH2; + } + } else { + state = SCE_L_ERROR; styler.ColourTo(i, state); state = SCE_L_DEFAULT; } + chNext = styler.SafeGetCharAt(i+1); + break; + case SCE_L_TAG2 : + if (latexIsTagValid(i, lengthDoc, styler)) { + styler.ColourTo(i, state); + state = SCE_L_DEFAULT; + } else { + state = SCE_L_ERROR; + } + chNext = styler.SafeGetCharAt(i+1); break; case SCE_L_MATH : if (ch == '$') { - if (chNext == '$') { - i++; - chNext = styler.SafeGetCharAt(i + 1); - } styler.ColourTo(i, state); state = SCE_L_DEFAULT; + } else if (ch == '\\' && chNext == ')') { + styler.ColourTo(i-1, state); + styler.ColourTo(i+1, SCE_L_SHORTCMD); + i++; + chNext = styler.SafeGetCharAt(i+1); + state = SCE_L_DEFAULT; + } else if (ch == '\\') { + int match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{math}")) { + styler.ColourTo(i-1, state); + state = SCE_L_COMMAND; + } + } + } + } + + break; + case SCE_L_MATH2 : + if (ch == '$') { + if (chNext == '$') { + i++; + chNext = styler.SafeGetCharAt(i + 1); + styler.ColourTo(i, state); + state = SCE_L_DEFAULT; + } else { + styler.ColourTo(i, SCE_L_ERROR); + state = SCE_L_DEFAULT; + } + } else if (ch == '\\' && chNext == ']') { + styler.ColourTo(i-1, state); + styler.ColourTo(i+1, SCE_L_SHORTCMD); + i++; + chNext = styler.SafeGetCharAt(i+1); + state = SCE_L_DEFAULT; + } else if (ch == '\\') { + int match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{displaymath}")) { + styler.ColourTo(i-1, state); + state = SCE_L_COMMAND; + } else if (latexLastWordIs(match, styler, "{equation}")) { + styler.ColourTo(i-1, state); + state = SCE_L_COMMAND; + } + } + } } break; case SCE_L_COMMENT : @@ -1258,6 +1415,43 @@ static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle, styler.ColourTo(i - 1, state); state = SCE_L_DEFAULT; } + break; + case SCE_L_COMMENT2 : + if (ch == '\\') { + int match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{comment}")) { + styler.ColourTo(i-1, state); + state = SCE_L_COMMAND; + } + } + } + } + break; + case SCE_L_VERBATIM : + if (ch == '\\') { + int match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{verbatim}")) { + styler.ColourTo(i-1, state); + state = SCE_L_COMMAND; + } + } + } + } else if (chNext == chVerbatimDelim) { + styler.ColourTo(i+1, state); + state = SCE_L_DEFAULT; + chVerbatimDelim = '\0'; + } else if (chVerbatimDelim != '\0' && (ch == '\n' || ch == '\r')) { + styler.ColourTo(i, SCE_L_ERROR); + state = SCE_L_DEFAULT; + chVerbatimDelim = '\0'; + } + break; } } styler.ColourTo(lengthDoc-1, state); diff --git a/lexers/LexPerl.cxx b/lexers/LexPerl.cxx index 7f0cbcf62..8a0f6422e 100644 --- a/lexers/LexPerl.cxx +++ b/lexers/LexPerl.cxx @@ -69,6 +69,10 @@ using namespace Scintilla; #define BACK_OPERATOR 1 // whitespace/comments are insignificant #define BACK_KEYWORD 2 // operators/keywords are needed for disambiguation +// all interpolated styles are different from their parent styles by a constant difference +// we also assume SCE_PL_STRING_VAR is the interpolated style with the smallest value +#define INTERPOLATE_SHIFT (SCE_PL_STRING_VAR - SCE_PL_STRING) + static bool isPerlKeyword(unsigned int start, unsigned int end, WordList &keywords, LexAccessor &styler) { // old-style keyword matcher; needed because GetCurrent() needs // current segment to be committed, but we may abandon early... @@ -246,14 +250,6 @@ static bool styleCheckSubPrototype(LexAccessor &styler, unsigned int bk) { return true; } -static bool isMatch(const char *sref, char *s) { - // match per-line delimiter - must kill trailing CR if CRLF - int i = strlen(s); - if (i != 0 && s[i - 1] == '\r') - s[i - 1] = '\0'; - return (strcmp(sref, s) == 0); -} - static int actualNumStyle(int numberStyle) { if (numberStyle == PERLNUM_VECTOR || numberStyle == PERLNUM_V_VECTOR) { return SCE_PL_STRING; @@ -360,11 +356,19 @@ struct OptionSetPerl : public OptionSet<OptionsPerl> { }; class LexerPerl : public ILexer { + CharacterSet setWordStart; + CharacterSet setWord; + CharacterSet setSpecialVar; + CharacterSet setControlVar; WordList keywords; OptionsPerl options; OptionSetPerl osPerl; public: - LexerPerl() { + LexerPerl() : + setWordStart(CharacterSet::setAlpha, "_", 0x80, true), + setWord(CharacterSet::setAlphaNum, "_", 0x80, true), + setSpecialVar(CharacterSet::setNone, "\"$;<>&`'+,./\\%:=~!?@[]"), + setControlVar(CharacterSet::setNone, "ACDEFHILMNOPRSTVWX") { } ~LexerPerl() { } @@ -398,6 +402,7 @@ public: static ILexer *LexerFactoryPerl() { return new LexerPerl(); } + void InterpolateSegment(StyleContext &sc, int maxSeg, bool isPattern=false); }; int SCI_METHOD LexerPerl::PropertySet(const char *key, const char *val) { @@ -426,6 +431,90 @@ int SCI_METHOD LexerPerl::WordListSet(int n, const char *wl) { return firstModification; } +void LexerPerl::InterpolateSegment(StyleContext &sc, int maxSeg, bool isPattern) { + // interpolate a segment (with no active backslashes or delimiters within) + // switch in or out of an interpolation style or continue current style + // commit variable patterns if found, trim segment, repeat until done + while (maxSeg > 0) { + bool isVar = false; + int sLen = 0; + if ((maxSeg > 1) && (sc.ch == '$' || sc.ch == '@')) { + // $#[$]*word [$@][$]*word (where word or {word} is always present) + bool braces = false; + sLen = 1; + if (sc.ch == '$' && sc.chNext == '#') { // starts with $# + sLen++; + } + while ((maxSeg > sLen) && (sc.GetRelative(sLen) == '$')) // >0 $ dereference within + sLen++; + if ((maxSeg > sLen) && (sc.GetRelative(sLen) == '{')) { // { start for {word} + sLen++; + braces = true; + } + if (maxSeg > sLen) { + int c = sc.GetRelative(sLen); + if (setWordStart.Contains(c)) { // word (various) + sLen++; + isVar = true; + while ((maxSeg > sLen) && setWord.Contains(sc.GetRelative(sLen))) + sLen++; + } else if (braces && IsADigit(c) && (sLen == 2)) { // digit for ${digit} + sLen++; + isVar = true; + } + } + if (braces) { + if ((maxSeg > sLen) && (sc.GetRelative(sLen) == '}')) { // } end for {word} + sLen++; + } else + isVar = false; + } + } + if (!isVar && (maxSeg > 1)) { // $- or @-specific variable patterns + sLen = 1; + int c = sc.chNext; + if (sc.ch == '$') { + if (IsADigit(c)) { // $[0-9] and slurp trailing digits + sLen++; + isVar = true; + while ((maxSeg > sLen) && IsADigit(sc.GetRelative(sLen))) + sLen++; + } else if (setSpecialVar.Contains(c)) { // $ special variables + sLen++; + isVar = true; + } else if (!isPattern && ((c == '(') || (c == ')') || (c == '|'))) { // $ additional + sLen++; + isVar = true; + } else if (c == '^') { // $^A control-char style + sLen++; + if ((maxSeg > sLen) && setControlVar.Contains(sc.GetRelative(sLen))) { + sLen++; + isVar = true; + } + } + } else if (sc.ch == '@') { + if (!isPattern && ((c == '+') || (c == '-'))) { // @ specials non-pattern + sLen++; + isVar = true; + } + } + } + if (isVar) { // commit as interpolated variable or normal character + if (sc.state < SCE_PL_STRING_VAR) + sc.SetState(sc.state + INTERPOLATE_SHIFT); + sc.Forward(sLen); + maxSeg -= sLen; + } else { + if (sc.state >= SCE_PL_STRING_VAR) + sc.SetState(sc.state - INTERPOLATE_SHIFT); + sc.Forward(); + maxSeg--; + } + } + if (sc.state >= SCE_PL_STRING_VAR) + sc.SetState(sc.state - INTERPOLATE_SHIFT); +} + void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { LexAccessor styler(pAccess); @@ -434,8 +523,6 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, reWords.Set("elsif if split while"); // charset classes - CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); CharacterSet setSingleCharOp(CharacterSet::setNone, "rwxoRWXOezsfdlpSbctugkTBMAC"); // lexing of "%*</" operators is non-trivial; these are missing in the set below CharacterSet setPerlOperator(CharacterSet::setNone, "^&\\()-+=|{}[]:;>,?!.~"); @@ -450,7 +537,7 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, CharacterSet &setPOD = setModifiers; CharacterSet setNonHereDoc(CharacterSet::setDigits, "=$@"); CharacterSet setHereDocDelim(CharacterSet::setAlphaNum, "_"); - CharacterSet setSubPrototype(CharacterSet::setNone, "\\[$@%&*];"); + CharacterSet setSubPrototype(CharacterSet::setNone, "\\[$@%&*+];"); // for format identifiers CharacterSet setFormatStart(CharacterSet::setAlpha, "_="); CharacterSet &setFormat = setHereDocDelim; @@ -520,10 +607,13 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, // Includes strings (may be multi-line), numbers (additional state), format // bodies, as well as POD sections. if (initStyle == SCE_PL_HERE_Q - || initStyle == SCE_PL_HERE_QQ - || initStyle == SCE_PL_HERE_QX - || initStyle == SCE_PL_FORMAT + || initStyle == SCE_PL_HERE_QQ + || initStyle == SCE_PL_HERE_QX + || initStyle == SCE_PL_FORMAT + || initStyle == SCE_PL_HERE_QQ_VAR + || initStyle == SCE_PL_HERE_QX_VAR ) { + // backtrack through multiple styles to reach the delimiter start int delim = (initStyle == SCE_PL_FORMAT) ? SCE_PL_FORMAT_IDENT:SCE_PL_HERE_DELIM; while ((startPos > 1) && (styler.StyleAt(startPos) != delim)) { startPos--; @@ -531,15 +621,34 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, startPos = styler.LineStart(styler.GetLine(startPos)); initStyle = styler.StyleAt(startPos - 1); } - if (initStyle == SCE_PL_STRING_Q - || initStyle == SCE_PL_STRING_QQ - || initStyle == SCE_PL_STRING_QX - || initStyle == SCE_PL_STRING_QR + if (initStyle == SCE_PL_STRING + || initStyle == SCE_PL_STRING_QQ + || initStyle == SCE_PL_BACKTICKS + || initStyle == SCE_PL_STRING_QX + || initStyle == SCE_PL_REGEX + || initStyle == SCE_PL_STRING_QR + || initStyle == SCE_PL_REGSUBST + || initStyle == SCE_PL_STRING_VAR + || initStyle == SCE_PL_STRING_QQ_VAR + || initStyle == SCE_PL_BACKTICKS_VAR + || initStyle == SCE_PL_STRING_QX_VAR + || initStyle == SCE_PL_REGEX_VAR + || initStyle == SCE_PL_STRING_QR_VAR + || initStyle == SCE_PL_REGSUBST_VAR + ) { + // for interpolation, must backtrack through a mix of two different styles + int otherStyle = (initStyle >= SCE_PL_STRING_VAR) ? + initStyle - INTERPOLATE_SHIFT : initStyle + INTERPOLATE_SHIFT; + while (startPos > 1) { + int st = styler.StyleAt(startPos - 1); + if ((st != initStyle) && (st != otherStyle)) + break; + startPos--; + } + initStyle = SCE_PL_DEFAULT; + } else if (initStyle == SCE_PL_STRING_Q || initStyle == SCE_PL_STRING_QW - || initStyle == SCE_PL_REGEX - || initStyle == SCE_PL_REGSUBST - || initStyle == SCE_PL_STRING - || initStyle == SCE_PL_BACKTICKS + || initStyle == SCE_PL_XLAT || initStyle == SCE_PL_CHARACTER || initStyle == SCE_PL_NUMBER || initStyle == SCE_PL_IDENTIFIER @@ -770,17 +879,48 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, break; case SCE_PL_HERE_Q: case SCE_PL_HERE_QQ: - case SCE_PL_HERE_QX: { - // also implies HereDoc.State == 2 - sc.Complete(); - while (!sc.atLineEnd) - sc.Forward(); - char s[HERE_DELIM_MAX]; - sc.GetCurrent(s, sizeof(s)); - if (isMatch(HereDoc.Delimiter, s)) { + case SCE_PL_HERE_QX: + // also implies HereDoc.State == 2 + sc.Complete(); + if (HereDoc.DelimiterLength == 0 || sc.Match(HereDoc.Delimiter)) { + int c = sc.GetRelative(HereDoc.DelimiterLength); + if (c == '\r' || c == '\n') { // peek first, do not consume match + sc.Forward(HereDoc.DelimiterLength); sc.SetState(SCE_PL_DEFAULT); backFlag = BACK_NONE; HereDoc.State = 0; + if (!sc.atLineEnd) + sc.Forward(); + break; + } + } + if (sc.state == SCE_PL_HERE_Q) { // \EOF and 'EOF' non-interpolated + while (!sc.atLineEnd) + sc.Forward(); + break; + } + while (!sc.atLineEnd) { // "EOF" and `EOF` interpolated + int s = 0, endType = 0; + int maxSeg = endPos - sc.currentPos; + while (s < maxSeg) { // scan to break string into segments + int c = sc.GetRelative(s); + if (c == '\\') { + endType = 1; break; + } else if (c == '\r' || c == '\n') { + endType = 2; break; + } + s++; + } + if (s > 0) // process non-empty segments + InterpolateSegment(sc, s); + if (endType == 1) { + sc.Forward(); + // \ at end-of-line does not appear to have any effect, skip + if (sc.ch != '\r' && sc.ch != '\n') + sc.Forward(); + } else if (endType == 2) { + if (!sc.atLineEnd) + sc.Forward(); } } break; @@ -833,45 +973,89 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, sc.SetState(SCE_PL_DEFAULT); } else if (!Quote.Up && !IsASpace(sc.ch)) { Quote.Open(sc.ch); - } else if (sc.ch == '\\' && Quote.Up != '\\') { - sc.Forward(); - } else if (sc.ch == Quote.Down) { - Quote.Count--; - if (Quote.Count == 0) - Quote.Rep--; - } else if (sc.ch == Quote.Up) { - Quote.Count++; + } else { + int s = 0, endType = 0; + int maxSeg = endPos - sc.currentPos; + while (s < maxSeg) { // scan to break string into segments + int c = sc.GetRelative(s); + if (IsASpace(c)) { + break; + } else if (c == '\\' && Quote.Up != '\\') { + endType = 1; break; + } else if (c == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) { + Quote.Rep--; + break; + } + } else if (c == Quote.Up) + Quote.Count++; + s++; + } + if (s > 0) { // process non-empty segments + if (Quote.Up != '\'') { + InterpolateSegment(sc, s, true); + } else // non-interpolated path + sc.Forward(s); + } + if (endType == 1) + sc.Forward(); } break; case SCE_PL_REGSUBST: + case SCE_PL_XLAT: if (Quote.Rep <= 0) { if (!setModifiers.Contains(sc.ch)) sc.SetState(SCE_PL_DEFAULT); } else if (!Quote.Up && !IsASpace(sc.ch)) { Quote.Open(sc.ch); - } else if (sc.ch == '\\' && Quote.Up != '\\') { - sc.Forward(); - } else if (Quote.Count == 0 && Quote.Rep == 1) { - // We matched something like s(...) or tr{...}, Perl 5.10 - // appears to allow almost any character for use as the - // next delimiters. Whitespace and comments are accepted in - // between, but we'll limit to whitespace here. - // For '#', if no whitespace in between, it's a delimiter. - if (IsASpace(sc.ch)) { - // Keep going - } else if (sc.ch == '#' && IsASpaceOrTab(sc.chPrev)) { - sc.SetState(SCE_PL_DEFAULT); - } else { - Quote.Open(sc.ch); + } else { + int s = 0, endType = 0; + int maxSeg = endPos - sc.currentPos; + bool isPattern = (Quote.Rep == 2); + while (s < maxSeg) { // scan to break string into segments + int c = sc.GetRelative(s); + if (c == '\\' && Quote.Up != '\\') { + endType = 2; break; + } else if (Quote.Count == 0 && Quote.Rep == 1) { + // We matched something like s(...) or tr{...}, Perl 5.10 + // appears to allow almost any character for use as the + // next delimiters. Whitespace and comments are accepted in + // between, but we'll limit to whitespace here. + // For '#', if no whitespace in between, it's a delimiter. + if (IsASpace(c)) { + // Keep going + } else if (c == '#' && IsASpaceOrTab(sc.GetRelative(s - 1))) { + endType = 3; + } else + Quote.Open(c); + break; + } else if (c == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) { + Quote.Rep--; + endType = 1; + } + if (Quote.Up == Quote.Down) + Quote.Count++; + if (endType == 1) + break; + } else if (c == Quote.Up) { + Quote.Count++; + } else if (IsASpace(c)) + break; + s++; + } + if (s > 0) { // process non-empty segments + if (sc.state == SCE_PL_REGSUBST && Quote.Up != '\'') { + InterpolateSegment(sc, s, isPattern); + } else // non-interpolated path + sc.Forward(s); } - } else if (sc.ch == Quote.Down) { - Quote.Count--; - if (Quote.Count == 0) - Quote.Rep--; - if (Quote.Up == Quote.Down) - Quote.Count++; - } else if (sc.ch == Quote.Up) { - Quote.Count++; + if (endType == 2) { + sc.Forward(); + } else if (endType == 3) + sc.SetState(SCE_PL_DEFAULT); } break; case SCE_PL_STRING_Q: @@ -883,14 +1067,45 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, case SCE_PL_BACKTICKS: if (!Quote.Down && !IsASpace(sc.ch)) { Quote.Open(sc.ch); - } else if (sc.ch == '\\' && Quote.Up != '\\') { - sc.Forward(); - } else if (sc.ch == Quote.Down) { - Quote.Count--; - if (Quote.Count == 0) + } else { + int s = 0, endType = 0; + int maxSeg = endPos - sc.currentPos; + while (s < maxSeg) { // scan to break string into segments + int c = sc.GetRelative(s); + if (IsASpace(c)) { + break; + } else if (c == '\\' && Quote.Up != '\\') { + endType = 2; break; + } else if (c == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) { + endType = 3; break; + } + } else if (c == Quote.Up) + Quote.Count++; + s++; + } + if (s > 0) { // process non-empty segments + switch (sc.state) { + case SCE_PL_STRING: + case SCE_PL_STRING_QQ: + case SCE_PL_BACKTICKS: + InterpolateSegment(sc, s); + break; + case SCE_PL_STRING_QX: + if (Quote.Up != '\'') { + InterpolateSegment(sc, s); + break; + } + // (continued for ' delim) + default: // non-interpolated path + sc.Forward(s); + } + } + if (endType == 2) { + sc.Forward(); + } else if (endType == 3) sc.ForwardSetState(SCE_PL_DEFAULT); - } else if (sc.ch == Quote.Up) { - Quote.Count++; } break; case SCE_PL_SUB_PROTOTYPE: { @@ -910,12 +1125,13 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, break; case SCE_PL_FORMAT: { sc.Complete(); + if (sc.Match('.')) { + sc.Forward(); + if (sc.atLineEnd || ((sc.ch == '\r' && sc.chNext == '\n'))) + sc.SetState(SCE_PL_DEFAULT); + } while (!sc.atLineEnd) sc.Forward(); - char s[10]; - sc.GetCurrent(s, sizeof(s)); - if (isMatch(".", s)) - sc.SetState(SCE_PL_DEFAULT); } break; case SCE_PL_ERROR: @@ -1000,9 +1216,9 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, numState = PERLNUM_DECIMAL; dotCount = 0; if (sc.ch == '0') { // hex,bin,octal - if (sc.chNext == 'x') { + if (sc.chNext == 'x' || sc.chNext == 'X') { numState = PERLNUM_HEX; - } else if (sc.chNext == 'b') { + } else if (sc.chNext == 'b' || sc.chNext == 'B') { numState = PERLNUM_BINARY; } else if (IsADigit(sc.chNext)) { numState = PERLNUM_OCTAL; @@ -1032,10 +1248,10 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, sc.ChangeState(SCE_PL_STRING_Q); Quote.New(); } else if (sc.ch == 'y' && !setWord.Contains(sc.chNext)) { - sc.ChangeState(SCE_PL_REGSUBST); + sc.ChangeState(SCE_PL_XLAT); Quote.New(2); } else if (sc.Match('t', 'r') && !setWord.Contains(sc.GetRelative(2))) { - sc.ChangeState(SCE_PL_REGSUBST); + sc.ChangeState(SCE_PL_XLAT); Quote.New(2); sc.Forward(); fw++; @@ -1127,7 +1343,6 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, bool isHereDoc = sc.Match('<', '<'); bool hereDocSpace = false; // for: SCALAR [whitespace] '<<' unsigned int bk = (sc.currentPos > 0) ? sc.currentPos - 1: 0; - unsigned int bkend; sc.Complete(); styler.Flush(); if (styler.StyleAt(bk) == SCE_PL_DEFAULT) @@ -1196,7 +1411,7 @@ void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, // keywords always forced as /PATTERN/: split, if, elsif, while // everything else /PATTERN/ unless digit/space immediately after '/' // for '//', defined-or favoured unless special keywords - bkend = bk + 1; + unsigned int bkend = bk + 1; while (bk > 0 && styler.StyleAt(bk - 1) == SCE_PL_WORD) { bk--; } diff --git a/lexers/LexPowerPro.cxx b/lexers/LexPowerPro.cxx index 89bce5800..e8a7a6689 100644 --- a/lexers/LexPowerPro.cxx +++ b/lexers/LexPowerPro.cxx @@ -155,7 +155,7 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl if ((sc.ch > 0) && setWord.Contains(sc.ch)) { strcpy(s_save,s); - int tp = strlen(s_save); + int tp = static_cast<int>(strlen(s_save)); if (tp < 99) { s_save[tp] = static_cast<char>(tolower(sc.ch)); s_save[tp+1] = '\0'; diff --git a/lexers/LexTeX.cxx b/lexers/LexTeX.cxx index 7b79670a9..062c7abb9 100644 --- a/lexers/LexTeX.cxx +++ b/lexers/LexTeX.cxx @@ -222,7 +222,7 @@ static void ColouriseTeXDoc( sc.ForwardSetState(SCE_TEX_TEXT) ; } else { sc.GetCurrent(key, sizeof(key)-1) ; - k = strlen(key) ; + k = static_cast<int>(strlen(key)) ; memmove(key,key+1,k) ; // shift left over escape token key[k] = '\0' ; k-- ; diff --git a/lexers/LexVHDL.cxx b/lexers/LexVHDL.cxx index 58bcd1a5a..5580b3c5e 100644 --- a/lexers/LexVHDL.cxx +++ b/lexers/LexVHDL.cxx @@ -235,7 +235,7 @@ static void FoldNoBoxVHDLDoc( } } } - for(j=j+strlen(prevWord); j<endPos; j++) + for(j=j+static_cast<unsigned int>(strlen(prevWord)); j<endPos; j++) { char ch = styler.SafeGetCharAt(j); int style = styler.StyleAt(j); |