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