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 |