| 1 skipped line |
|
| 3 | | 3 | | ** Lexer for Visual Basic and VBScript. |
|
|
| 5 | | // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> | | 5 | | // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> |
| 6 | | 6 | | // The License.txt file describes the conditions under which this software may be distributed. |
|
|
|
| 11 skipped lines |
| 20 | | 20 | | #include "Scintilla.h" |
|
| 21 | | 21 | | #include "SciLexer.h" |
|
|
| | | 23 | | // Internal state, highlighted as number |
| | | 24 | | #define SCE_B_FILENUMBER SCE_B_DEFAULT+100 |
| | | 25 | | |
| | | 26 | | |
| 23 | | 27 | | static bool IsVBComment(Accessor &styler, int pos, int len) { |
|
| 24 | | return len>0 && styler[pos]=='\''; | | 28 | | return len > 0 && styler[pos] == '\''; |
|
|
| 27 | | 31 | | static inline bool IsTypeCharacter(int ch) { |
|
| 8 skipped lines |
|
| 37 | | 41 | | static inline bool IsAWordStart(int ch) { |
|
| 38 | | 42 | | return ch >= 0x80 || |
|
| 39 | | (isalnum(ch) || ch == '_'); | | 43 | | (isalpha(ch) || ch == '_'); |
|
|
| 42 | | static inline bool IsADateCharacter(const int ch) { | | 46 | | static inline bool IsANumberChar(int ch) { |
| | | 47 | | // Not exactly following number definition (several dots are seen as OK, etc.) |
| | | 48 | | // but probably enough in most cases. |
| 43 | | 49 | | return (ch < 0x80) && |
|
| | | 50 | | (isdigit(ch) || toupper(ch) == 'E' || |
| 44 | | (isalnum(ch) || ch == '|' || ch == '-' || ch == '/' || ch == ':' || ch == ' ' || ch == '\t'); | | 51 | | ch == '.' || ch == '-' || ch == '+'); |
|
|
| 47 | | 54 | | static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle, |
|
| 7 skipped lines |
| 55 | | 62 | | styler.StartAt(startPos); |
|
|
| 57 | | 64 | | int visibleChars = 0; |
|
| | | 65 | | int fileNbDigits = 0; |
| | | 66 | | |
| | | 67 | | // Do not leak onto next line |
| | | 68 | | if (initStyle == SCE_B_STRINGEOL || initStyle == SCE_B_COMMENT || initStyle == SCE_B_PREPROCESSOR) { |
| | | 69 | | initStyle = SCE_B_DEFAULT; |
| | | 70 | | } |
|
| 59 | | 72 | | StyleContext sc(startPos, length, initStyle, styler); |
|
|
| 35 skipped lines |
|
|
| 98 | | 111 | | } else if (sc.state == SCE_B_NUMBER) { |
|
| | | 112 | | // We stop the number definition on non-numerical non-dot non-eE non-sign char |
| | | 113 | | // Also accepts A-F for hex. numbers |
| 99 | | if (!IsAWordChar(sc.ch)) { | | 114 | | if (!IsANumberChar(sc.ch) && !(tolower(sc.ch) >= 'a' && tolower(sc.ch) <= 'f')) { |
| 100 | | 115 | | sc.SetState(SCE_B_DEFAULT); |
|
|
| 102 | | 117 | | } else if (sc.state == SCE_B_STRING) { |
|
| 10 skipped lines |
|
| 114 | | 129 | | } else if (sc.state == SCE_B_COMMENT) { |
|
| 115 | | 130 | | if (sc.atLineEnd) { |
|
| 116 | | sc.SetState(SCE_B_DEFAULT); | | 131 | | sc.ForwardSetState(SCE_B_DEFAULT); |
|
| 118 | | 133 | | } else if (sc.state == SCE_B_PREPROCESSOR) { |
|
| 119 | | 134 | | if (sc.atLineEnd) { |
|
| | | 135 | | sc.ForwardSetState(SCE_B_DEFAULT); |
| | | 136 | | } |
| | | 137 | | } else if (sc.state == SCE_B_FILENUMBER) { |
| | | 138 | | if (IsADigit(sc.ch)) { |
| | | 139 | | fileNbDigits++; |
| 3 skipped lines |
| | | 143 | | } else if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ',') { |
| | | 144 | | // Regular uses: Close #1; Put #1, ...; Get #1, ... etc. |
| | | 145 | | // Too bad if date is format #27, Oct, 2003# or something like that... |
| | | 146 | | // Use regular number state |
| | | 147 | | sc.ChangeState(SCE_B_NUMBER); |
| 120 | | 148 | | sc.SetState(SCE_B_DEFAULT); |
|
| | | 149 | | } else if (sc.ch == '#') { |
| | | 150 | | sc.ChangeState(SCE_B_DATE); |
| | | 151 | | sc.ForwardSetState(SCE_B_DEFAULT); |
| | | 152 | | } else { |
| | | 153 | | sc.ChangeState(SCE_B_DATE); |
| | | 154 | | } |
| | | 155 | | if (sc.state != SCE_B_FILENUMBER) { |
| | | 156 | | fileNbDigits = 0; |
|
| 122 | | 158 | | } else if (sc.state == SCE_B_DATE) { |
|
| | | 159 | | if (sc.atLineEnd) { |
| | | 160 | | sc.ChangeState(SCE_B_STRINGEOL); |
| | | 161 | | sc.ForwardSetState(SCE_B_DEFAULT); |
| 123 | | if (sc.ch == '#' || !IsADateCharacter(sc.chNext)) { | | 162 | | } else if (sc.ch == '#') { |
| 124 | | 163 | | sc.ForwardSetState(SCE_B_DEFAULT); |
|
|
|
| 7 skipped lines |
| 134 | | 173 | | // Preprocessor commands are alone on their line |
|
| 135 | | 174 | | sc.SetState(SCE_B_PREPROCESSOR); |
|
| 136 | | 175 | | } else if (sc.ch == '#') { |
|
| 137 | | int n = 1; | | 176 | | // It can be a date literal, ending with #, or a file number, from 1 to 511 |
| 138 | | int chSeek = ' '; | | 177 | | // The date literal depends on the locale, so anything can go between #'s. |
| 139 | | while ((n < 100) && (chSeek == ' ' || chSeek == '\t')) { | | 178 | | // Can be #January 1, 1993# or #1 Jan 93# or #05/11/2003#, etc. |
| 140 | | chSeek = sc.GetRelative(n); | | |
| 141 | | n++; | | |
| 142 | | } | | |
| 143 | | if (IsADigit(chSeek)) { | | |
| 144 | | sc.SetState(SCE_B_DATE); | | 179 | | // So we set the FILENUMBER state, and switch to DATE if it isn't a file number |
| 145 | | } else { | | |
| 146 | | sc.SetState(SCE_B_OPERATOR); | | 180 | | sc.SetState(SCE_B_FILENUMBER); |
| 147 | | } | | |
| 148 | | 181 | | } else if (sc.ch == '&' && tolower(sc.chNext) == 'h') { |
|
| | | 182 | | // Hexadecimal number |
| 149 | | 183 | | sc.SetState(SCE_B_NUMBER); |
|
| | | 184 | | sc.Forward(); |
| 150 | | 185 | | } else if (sc.ch == '&' && tolower(sc.chNext) == 'o') { |
|
| | | 186 | | // Octal number |
| 151 | | 187 | | sc.SetState(SCE_B_NUMBER); |
|
| | | 188 | | sc.Forward(); |
| 152 | | 189 | | } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { |
|
| 153 | | 190 | | sc.SetState(SCE_B_NUMBER); |
|
| 154 | | 191 | | } else if (IsAWordStart(sc.ch) || (sc.ch == '[')) { |
|
| 155 | | 192 | | sc.SetState(SCE_B_IDENTIFIER); |
|
| 156 | | } else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) { | | 193 | | } else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) { // Integer division |
| 157 | | 194 | | sc.SetState(SCE_B_OPERATOR); |
|
|
|
| 75 skipped lines |