]>
Commit | Line | Data |
---|---|---|
65ec6247 | 1 | // Scintilla source code edit control |
1dcf666d RD |
2 | /** @file LexECL.cxx |
3 | ** Lexer for ECL. | |
65ec6247 | 4 | **/ |
1dcf666d | 5 | // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> |
f6bcfd97 BP |
6 | // The License.txt file describes the conditions under which this software may be distributed. |
7 | ||
65ec6247 RD |
8 | #include <stdlib.h> |
9 | #include <string.h> | |
10 | #include <ctype.h> | |
11 | #include <stdio.h> | |
12 | #include <stdarg.h> | |
1dcf666d | 13 | #include <assert.h> |
f6bcfd97 | 14 | |
1dcf666d RD |
15 | #ifdef _MSC_VER |
16 | #pragma warning(disable: 4786) | |
17 | #endif | |
18 | #ifdef __BORLANDC__ | |
19 | // Borland C++ displays warnings in vector header without this | |
20 | #pragma option -w-ccc -w-rch | |
21 | #endif | |
f6bcfd97 | 22 | |
1dcf666d RD |
23 | #include <string> |
24 | #include <vector> | |
25 | #include <map> | |
26 | #include <algorithm> | |
27 | ||
28 | #include "ILexer.h" | |
f6bcfd97 BP |
29 | #include "Scintilla.h" |
30 | #include "SciLexer.h" | |
1dcf666d RD |
31 | |
32 | #include "PropSetSimple.h" | |
33 | #include "WordList.h" | |
34 | #include "LexAccessor.h" | |
35 | #include "Accessor.h" | |
36 | #include "StyleContext.h" | |
7e0c58e9 | 37 | #include "CharacterSet.h" |
1dcf666d RD |
38 | #include "LexerModule.h" |
39 | #include "OptionSet.h" | |
40 | ||
41 | #define SET_LOWER "abcdefghijklmnopqrstuvwxyz" | |
42 | #define SET_UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
43 | #define SET_DIGITS "0123456789" | |
f6bcfd97 | 44 | |
7e0c58e9 RD |
45 | #ifdef SCI_NAMESPACE |
46 | using namespace Scintilla; | |
47 | #endif | |
65ec6247 | 48 | |
1e9bafca | 49 | static bool IsSpaceEquiv(int state) { |
1dcf666d RD |
50 | return (state <= SCE_ECL_COMMENTDOC) || |
51 | // including SCE_ECL_DEFAULT, SCE_ECL_COMMENT, SCE_ECL_COMMENTLINE | |
52 | (state == SCE_ECL_COMMENTLINEDOC) || (state == SCE_ECL_COMMENTDOCKEYWORD) || | |
53 | (state == SCE_ECL_COMMENTDOCKEYWORDERROR); | |
b8b0e402 | 54 | } |
65ec6247 | 55 | |
1dcf666d RD |
56 | static void ColouriseEclDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], |
57 | Accessor &styler) { | |
58 | WordList &keywords0 = *keywordlists[0]; | |
59 | WordList &keywords1 = *keywordlists[1]; | |
60 | WordList &keywords2 = *keywordlists[2]; | |
61 | WordList &keywords3 = *keywordlists[3]; //Value Types | |
62 | WordList &keywords4 = *keywordlists[4]; | |
63 | WordList &keywords5 = *keywordlists[5]; | |
64 | WordList &keywords6 = *keywordlists[6]; //Javadoc Tags | |
65 | WordList cplusplus; | |
66 | cplusplus.Set("beginc endc"); | |
67 | ||
68 | bool stylingWithinPreprocessor = false; | |
69 | ||
70 | CharacterSet setOKBeforeRE(CharacterSet::setNone, "(=,"); | |
71 | CharacterSet setDoxygen(CharacterSet::setLower, "$@\\&<>#{}[]"); | |
7e0c58e9 RD |
72 | CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); |
73 | CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); | |
1dcf666d | 74 | CharacterSet setQualified(CharacterSet::setNone, "uUxX"); |
7e0c58e9 | 75 | |
65ec6247 | 76 | int chPrevNonWhite = ' '; |
d134f170 | 77 | int visibleChars = 0; |
f6bcfd97 | 78 | bool lastWordWasUUID = false; |
1dcf666d | 79 | int styleBeforeDCKeyword = SCE_ECL_DEFAULT; |
1e9bafca RD |
80 | bool continuationLine = false; |
81 | ||
1dcf666d | 82 | if (initStyle == SCE_ECL_PREPROCESSOR) { |
1e9bafca RD |
83 | // Set continuationLine if last character of previous line is '\' |
84 | int lineCurrent = styler.GetLine(startPos); | |
85 | if (lineCurrent > 0) { | |
86 | int chBack = styler.SafeGetCharAt(startPos-1, 0); | |
87 | int chBack2 = styler.SafeGetCharAt(startPos-2, 0); | |
88 | int lineEndChar = '!'; | |
89 | if (chBack2 == '\r' && chBack == '\n') { | |
90 | lineEndChar = styler.SafeGetCharAt(startPos-3, 0); | |
91 | } else if (chBack == '\n' || chBack == '\r') { | |
92 | lineEndChar = chBack2; | |
93 | } | |
94 | continuationLine = lineEndChar == '\\'; | |
95 | } | |
96 | } | |
97 | ||
98 | // look back to set chPrevNonWhite properly for better regex colouring | |
99 | if (startPos > 0) { | |
100 | int back = startPos; | |
101 | while (--back && IsSpaceEquiv(styler.StyleAt(back))) | |
102 | ; | |
1dcf666d | 103 | if (styler.StyleAt(back) == SCE_ECL_OPERATOR) { |
1e9bafca RD |
104 | chPrevNonWhite = styler.SafeGetCharAt(back); |
105 | } | |
106 | } | |
f6bcfd97 | 107 | |
b8b0e402 | 108 | StyleContext sc(startPos, length, initStyle, styler); |
f6bcfd97 | 109 | |
b8b0e402 | 110 | for (; sc.More(); sc.Forward()) { |
1e9bafca | 111 | if (sc.atLineStart) { |
1dcf666d RD |
112 | if (sc.state == SCE_ECL_STRING) { |
113 | // Prevent SCE_ECL_STRINGEOL from leaking back to previous line which | |
1e9bafca | 114 | // ends with a line continuation by locking in the state upto this position. |
1dcf666d | 115 | sc.SetState(SCE_ECL_STRING); |
1e9bafca RD |
116 | } |
117 | // Reset states to begining of colourise so no surprises | |
118 | // if different sets of lines lexed. | |
119 | visibleChars = 0; | |
120 | lastWordWasUUID = false; | |
a834585d RD |
121 | } |
122 | ||
b8b0e402 RD |
123 | // Handle line continuation generically. |
124 | if (sc.ch == '\\') { | |
a834585d | 125 | if (sc.chNext == '\n' || sc.chNext == '\r') { |
b8b0e402 | 126 | sc.Forward(); |
a834585d RD |
127 | if (sc.ch == '\r' && sc.chNext == '\n') { |
128 | sc.Forward(); | |
129 | } | |
1e9bafca | 130 | continuationLine = true; |
b8b0e402 | 131 | continue; |
f6bcfd97 | 132 | } |
b8b0e402 RD |
133 | } |
134 | ||
135 | // Determine if the current state should terminate. | |
1e9bafca | 136 | switch (sc.state) { |
1dcf666d RD |
137 | case SCE_ECL_ADDED: |
138 | case SCE_ECL_DELETED: | |
139 | case SCE_ECL_CHANGED: | |
140 | case SCE_ECL_MOVED: | |
141 | if (sc.atLineStart) | |
142 | sc.SetState(SCE_ECL_DEFAULT); | |
1e9bafca | 143 | break; |
1dcf666d RD |
144 | case SCE_ECL_OPERATOR: |
145 | sc.SetState(SCE_ECL_DEFAULT); | |
146 | break; | |
147 | case SCE_ECL_NUMBER: | |
1e9bafca | 148 | // We accept almost anything because of hex. and number suffixes |
7e0c58e9 | 149 | if (!setWord.Contains(sc.ch)) { |
1dcf666d | 150 | sc.SetState(SCE_ECL_DEFAULT); |
f6bcfd97 | 151 | } |
1e9bafca | 152 | break; |
1dcf666d | 153 | case SCE_ECL_IDENTIFIER: |
7e0c58e9 | 154 | if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { |
1e9bafca | 155 | char s[1000]; |
1dcf666d RD |
156 | sc.GetCurrentLowered(s, sizeof(s)); |
157 | if (keywords0.InList(s)) { | |
1e9bafca | 158 | lastWordWasUUID = strcmp(s, "uuid") == 0; |
1dcf666d RD |
159 | sc.ChangeState(SCE_ECL_WORD0); |
160 | } else if (keywords1.InList(s)) { | |
161 | sc.ChangeState(SCE_ECL_WORD1); | |
1e9bafca | 162 | } else if (keywords2.InList(s)) { |
1dcf666d | 163 | sc.ChangeState(SCE_ECL_WORD2); |
1e9bafca | 164 | } else if (keywords4.InList(s)) { |
1dcf666d RD |
165 | sc.ChangeState(SCE_ECL_WORD4); |
166 | } else if (keywords5.InList(s)) { | |
167 | sc.ChangeState(SCE_ECL_WORD5); | |
168 | } | |
169 | else //Data types are of from KEYWORD## | |
170 | { | |
171 | int i = static_cast<int>(strlen(s)) - 1; | |
172 | while(i >= 0 && (isdigit(s[i]) || s[i] == '_')) | |
173 | --i; | |
174 | ||
175 | char s2[1000]; | |
176 | strncpy(s2, s, i + 1); | |
177 | s2[i + 1] = 0; | |
178 | if (keywords3.InList(s2)) { | |
179 | sc.ChangeState(SCE_ECL_WORD3); | |
180 | } | |
1e9bafca | 181 | } |
1dcf666d | 182 | sc.SetState(SCE_ECL_DEFAULT); |
f6bcfd97 | 183 | } |
1e9bafca | 184 | break; |
1dcf666d | 185 | case SCE_ECL_PREPROCESSOR: |
1e9bafca | 186 | if (sc.atLineStart && !continuationLine) { |
1dcf666d | 187 | sc.SetState(SCE_ECL_DEFAULT); |
1e9bafca RD |
188 | } else if (stylingWithinPreprocessor) { |
189 | if (IsASpace(sc.ch)) { | |
1dcf666d | 190 | sc.SetState(SCE_ECL_DEFAULT); |
1e9bafca | 191 | } |
9e730a78 | 192 | } else { |
1e9bafca | 193 | if (sc.Match('/', '*') || sc.Match('/', '/')) { |
1dcf666d | 194 | sc.SetState(SCE_ECL_DEFAULT); |
1e9bafca | 195 | } |
b8b0e402 | 196 | } |
1e9bafca | 197 | break; |
1dcf666d | 198 | case SCE_ECL_COMMENT: |
1e9bafca | 199 | if (sc.Match('*', '/')) { |
b8b0e402 | 200 | sc.Forward(); |
1dcf666d | 201 | sc.ForwardSetState(SCE_ECL_DEFAULT); |
f6bcfd97 | 202 | } |
1e9bafca | 203 | break; |
1dcf666d | 204 | case SCE_ECL_COMMENTDOC: |
1e9bafca | 205 | if (sc.Match('*', '/')) { |
b8b0e402 | 206 | sc.Forward(); |
1dcf666d | 207 | sc.ForwardSetState(SCE_ECL_DEFAULT); |
1e9bafca RD |
208 | } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support |
209 | // Verify that we have the conditions to mark a comment-doc-keyword | |
210 | if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { | |
1dcf666d RD |
211 | styleBeforeDCKeyword = SCE_ECL_COMMENTDOC; |
212 | sc.SetState(SCE_ECL_COMMENTDOCKEYWORD); | |
1e9bafca | 213 | } |
f6bcfd97 | 214 | } |
1e9bafca | 215 | break; |
1dcf666d | 216 | case SCE_ECL_COMMENTLINE: |
1e9bafca | 217 | if (sc.atLineStart) { |
1dcf666d | 218 | sc.SetState(SCE_ECL_DEFAULT); |
d134f170 | 219 | } |
1e9bafca | 220 | break; |
1dcf666d | 221 | case SCE_ECL_COMMENTLINEDOC: |
1e9bafca | 222 | if (sc.atLineStart) { |
1dcf666d | 223 | sc.SetState(SCE_ECL_DEFAULT); |
1e9bafca RD |
224 | } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support |
225 | // Verify that we have the conditions to mark a comment-doc-keyword | |
226 | if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { | |
1dcf666d RD |
227 | styleBeforeDCKeyword = SCE_ECL_COMMENTLINEDOC; |
228 | sc.SetState(SCE_ECL_COMMENTDOCKEYWORD); | |
1e9bafca RD |
229 | } |
230 | } | |
231 | break; | |
1dcf666d RD |
232 | case SCE_ECL_COMMENTDOCKEYWORD: |
233 | if ((styleBeforeDCKeyword == SCE_ECL_COMMENTDOC) && sc.Match('*', '/')) { | |
234 | sc.ChangeState(SCE_ECL_COMMENTDOCKEYWORDERROR); | |
b8b0e402 | 235 | sc.Forward(); |
1dcf666d | 236 | sc.ForwardSetState(SCE_ECL_DEFAULT); |
7e0c58e9 | 237 | } else if (!setDoxygen.Contains(sc.ch)) { |
1dcf666d RD |
238 | char s[1000]; |
239 | sc.GetCurrentLowered(s, sizeof(s)); | |
240 | if (!IsASpace(sc.ch) || !keywords6.InList(s+1)) { | |
241 | sc.ChangeState(SCE_ECL_COMMENTDOCKEYWORDERROR); | |
1e9bafca RD |
242 | } |
243 | sc.SetState(styleBeforeDCKeyword); | |
244 | } | |
245 | break; | |
1dcf666d | 246 | case SCE_ECL_STRING: |
1e9bafca | 247 | if (sc.atLineEnd) { |
1dcf666d | 248 | sc.ChangeState(SCE_ECL_STRINGEOL); |
1e9bafca RD |
249 | } else if (sc.ch == '\\') { |
250 | if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { | |
251 | sc.Forward(); | |
252 | } | |
253 | } else if (sc.ch == '\"') { | |
1dcf666d | 254 | sc.ForwardSetState(SCE_ECL_DEFAULT); |
1e9bafca RD |
255 | } |
256 | break; | |
1dcf666d | 257 | case SCE_ECL_CHARACTER: |
1e9bafca | 258 | if (sc.atLineEnd) { |
1dcf666d | 259 | sc.ChangeState(SCE_ECL_STRINGEOL); |
1e9bafca RD |
260 | } else if (sc.ch == '\\') { |
261 | if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { | |
262 | sc.Forward(); | |
263 | } | |
264 | } else if (sc.ch == '\'') { | |
1dcf666d | 265 | sc.ForwardSetState(SCE_ECL_DEFAULT); |
1e9bafca RD |
266 | } |
267 | break; | |
1dcf666d | 268 | case SCE_ECL_REGEX: |
1e9bafca | 269 | if (sc.atLineStart) { |
1dcf666d | 270 | sc.SetState(SCE_ECL_DEFAULT); |
1e9bafca RD |
271 | } else if (sc.ch == '/') { |
272 | sc.Forward(); | |
273 | while ((sc.ch < 0x80) && islower(sc.ch)) | |
274 | sc.Forward(); // gobble regex flags | |
1dcf666d | 275 | sc.SetState(SCE_ECL_DEFAULT); |
1e9bafca RD |
276 | } else if (sc.ch == '\\') { |
277 | // Gobble up the quoted character | |
278 | if (sc.chNext == '\\' || sc.chNext == '/') { | |
279 | sc.Forward(); | |
280 | } | |
281 | } | |
282 | break; | |
1dcf666d | 283 | case SCE_ECL_STRINGEOL: |
1e9bafca | 284 | if (sc.atLineStart) { |
1dcf666d | 285 | sc.SetState(SCE_ECL_DEFAULT); |
1e9bafca RD |
286 | } |
287 | break; | |
1dcf666d | 288 | case SCE_ECL_VERBATIM: |
1e9bafca RD |
289 | if (sc.ch == '\"') { |
290 | if (sc.chNext == '\"') { | |
291 | sc.Forward(); | |
292 | } else { | |
1dcf666d | 293 | sc.ForwardSetState(SCE_ECL_DEFAULT); |
1e9bafca RD |
294 | } |
295 | } | |
296 | break; | |
1dcf666d | 297 | case SCE_ECL_UUID: |
1e9bafca | 298 | if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { |
1dcf666d | 299 | sc.SetState(SCE_ECL_DEFAULT); |
d134f170 | 300 | } |
1dcf666d | 301 | break; |
65ec6247 RD |
302 | } |
303 | ||
b8b0e402 | 304 | // Determine if a new state should be entered. |
1dcf666d RD |
305 | int lineCurrent = styler.GetLine(sc.currentPos); |
306 | int lineState = styler.GetLineState(lineCurrent); | |
307 | if (sc.state == SCE_ECL_DEFAULT) { | |
308 | if (lineState) { | |
309 | sc.SetState(lineState); | |
310 | } | |
311 | else if (sc.Match('@', '\"')) { | |
312 | sc.SetState(SCE_ECL_VERBATIM); | |
313 | sc.Forward(); | |
314 | } else if (setQualified.Contains(sc.ch) && sc.chNext == '\'') { | |
315 | sc.SetState(SCE_ECL_CHARACTER); | |
b8b0e402 RD |
316 | sc.Forward(); |
317 | } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { | |
65ec6247 | 318 | if (lastWordWasUUID) { |
1dcf666d | 319 | sc.SetState(SCE_ECL_UUID); |
65ec6247 RD |
320 | lastWordWasUUID = false; |
321 | } else { | |
1dcf666d | 322 | sc.SetState(SCE_ECL_NUMBER); |
f6bcfd97 | 323 | } |
7e0c58e9 | 324 | } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { |
65ec6247 | 325 | if (lastWordWasUUID) { |
1dcf666d | 326 | sc.SetState(SCE_ECL_UUID); |
65ec6247 RD |
327 | lastWordWasUUID = false; |
328 | } else { | |
1dcf666d | 329 | sc.SetState(SCE_ECL_IDENTIFIER); |
f6bcfd97 | 330 | } |
b8b0e402 RD |
331 | } else if (sc.Match('/', '*')) { |
332 | if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style | |
1dcf666d | 333 | sc.SetState(SCE_ECL_COMMENTDOC); |
b8b0e402 | 334 | } else { |
1dcf666d | 335 | sc.SetState(SCE_ECL_COMMENT); |
b8b0e402 RD |
336 | } |
337 | sc.Forward(); // Eat the * so it isn't used for the end of the comment | |
338 | } else if (sc.Match('/', '/')) { | |
a33203cb RD |
339 | if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) |
340 | // Support of Qt/Doxygen doc. style | |
1dcf666d | 341 | sc.SetState(SCE_ECL_COMMENTLINEDOC); |
65ec6247 | 342 | else |
1dcf666d RD |
343 | sc.SetState(SCE_ECL_COMMENTLINE); |
344 | } else if (sc.ch == '/' && setOKBeforeRE.Contains(chPrevNonWhite)) { | |
345 | sc.SetState(SCE_ECL_REGEX); // JavaScript's RegEx | |
346 | // } else if (sc.ch == '\"') { | |
347 | // sc.SetState(SCE_ECL_STRING); | |
b8b0e402 | 348 | } else if (sc.ch == '\'') { |
1dcf666d | 349 | sc.SetState(SCE_ECL_CHARACTER); |
b8b0e402 | 350 | } else if (sc.ch == '#' && visibleChars == 0) { |
65ec6247 | 351 | // Preprocessor commands are alone on their line |
1dcf666d | 352 | sc.SetState(SCE_ECL_PREPROCESSOR); |
65ec6247 RD |
353 | // Skip whitespace between # and preprocessor word |
354 | do { | |
b8b0e402 | 355 | sc.Forward(); |
9e730a78 | 356 | } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); |
1e9bafca | 357 | if (sc.atLineEnd) { |
1dcf666d | 358 | sc.SetState(SCE_ECL_DEFAULT); |
b8b0e402 RD |
359 | } |
360 | } else if (isoperator(static_cast<char>(sc.ch))) { | |
1dcf666d | 361 | sc.SetState(SCE_ECL_OPERATOR); |
f6bcfd97 | 362 | } |
f6bcfd97 | 363 | } |
9e730a78 | 364 | |
1e9bafca | 365 | if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) { |
b8b0e402 | 366 | chPrevNonWhite = sc.ch; |
65ec6247 RD |
367 | visibleChars++; |
368 | } | |
1e9bafca | 369 | continuationLine = false; |
f6bcfd97 | 370 | } |
b8b0e402 | 371 | sc.Complete(); |
1dcf666d | 372 | |
65ec6247 | 373 | } |
f6bcfd97 | 374 | |
a834585d | 375 | static bool IsStreamCommentStyle(int style) { |
1dcf666d RD |
376 | return style == SCE_ECL_COMMENT || |
377 | style == SCE_ECL_COMMENTDOC || | |
378 | style == SCE_ECL_COMMENTDOCKEYWORD || | |
379 | style == SCE_ECL_COMMENTDOCKEYWORDERROR; | |
380 | } | |
381 | ||
382 | bool MatchNoCase(Accessor & styler, unsigned int & pos, const char *s) { | |
383 | int i=0; | |
384 | for (; *s; i++) { | |
385 | char compare_char = tolower(*s); | |
386 | char styler_char = tolower(styler.SafeGetCharAt(pos+i)); | |
387 | if (compare_char != styler_char) | |
388 | return false; | |
389 | s++; | |
390 | } | |
391 | pos+=i-1; | |
392 | return true; | |
a834585d RD |
393 | } |
394 | ||
1dcf666d | 395 | |
e14d10b0 RD |
396 | // Store both the current line's fold level and the next lines in the |
397 | // level store to make it easy to pick up with each increment | |
398 | // and to make it possible to fiddle the current level for "} else {". | |
1dcf666d | 399 | static void FoldEclDoc(unsigned int startPos, int length, int initStyle, |
7e0c58e9 | 400 | WordList *[], Accessor &styler) { |
1dcf666d RD |
401 | bool foldComment = true; |
402 | bool foldPreprocessor = true; | |
403 | bool foldCompact = true; | |
404 | bool foldAtElse = true; | |
65ec6247 RD |
405 | unsigned int endPos = startPos + length; |
406 | int visibleChars = 0; | |
407 | int lineCurrent = styler.GetLine(startPos); | |
e14d10b0 RD |
408 | int levelCurrent = SC_FOLDLEVELBASE; |
409 | if (lineCurrent > 0) | |
410 | levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; | |
411 | int levelMinCurrent = levelCurrent; | |
412 | int levelNext = levelCurrent; | |
65ec6247 RD |
413 | char chNext = styler[startPos]; |
414 | int styleNext = styler.StyleAt(startPos); | |
415 | int style = initStyle; | |
416 | for (unsigned int i = startPos; i < endPos; i++) { | |
417 | char ch = chNext; | |
418 | chNext = styler.SafeGetCharAt(i + 1); | |
419 | int stylePrev = style; | |
420 | style = styleNext; | |
421 | styleNext = styler.StyleAt(i + 1); | |
422 | bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); | |
a834585d | 423 | if (foldComment && IsStreamCommentStyle(style)) { |
1dcf666d | 424 | if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_ECL_COMMENTLINEDOC)) { |
e14d10b0 | 425 | levelNext++; |
1dcf666d | 426 | } else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_ECL_COMMENTLINEDOC) && !atEOL) { |
65ec6247 | 427 | // Comments don't end at end of line and the next character may be unstyled. |
e14d10b0 | 428 | levelNext--; |
65ec6247 RD |
429 | } |
430 | } | |
1dcf666d | 431 | if (foldComment && (style == SCE_ECL_COMMENTLINE)) { |
a834585d RD |
432 | if ((ch == '/') && (chNext == '/')) { |
433 | char chNext2 = styler.SafeGetCharAt(i + 2); | |
434 | if (chNext2 == '{') { | |
e14d10b0 | 435 | levelNext++; |
a834585d | 436 | } else if (chNext2 == '}') { |
e14d10b0 | 437 | levelNext--; |
a834585d RD |
438 | } |
439 | } | |
440 | } | |
1dcf666d | 441 | if (foldPreprocessor && (style == SCE_ECL_PREPROCESSOR)) { |
a834585d | 442 | if (ch == '#') { |
9e730a78 RD |
443 | unsigned int j = i + 1; |
444 | while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { | |
a834585d RD |
445 | j++; |
446 | } | |
1dcf666d | 447 | if (MatchNoCase(styler, j, "region") || MatchNoCase(styler, j, "if")) { |
e14d10b0 | 448 | levelNext++; |
1dcf666d | 449 | } else if (MatchNoCase(styler, j, "endregion") || MatchNoCase(styler, j, "end")) { |
e14d10b0 | 450 | levelNext--; |
a834585d RD |
451 | } |
452 | } | |
453 | } | |
1dcf666d | 454 | if (style == SCE_ECL_OPERATOR) { |
65ec6247 | 455 | if (ch == '{') { |
e14d10b0 RD |
456 | // Measure the minimum before a '{' to allow |
457 | // folding on "} else {" | |
458 | if (levelMinCurrent > levelNext) { | |
459 | levelMinCurrent = levelNext; | |
460 | } | |
461 | levelNext++; | |
65ec6247 | 462 | } else if (ch == '}') { |
e14d10b0 | 463 | levelNext--; |
65ec6247 RD |
464 | } |
465 | } | |
1dcf666d RD |
466 | if (style == SCE_ECL_WORD2) { |
467 | if (MatchNoCase(styler, i, "record") || MatchNoCase(styler, i, "transform") || MatchNoCase(styler, i, "type") || MatchNoCase(styler, i, "function") || | |
468 | MatchNoCase(styler, i, "module") || MatchNoCase(styler, i, "service") || MatchNoCase(styler, i, "interface") || MatchNoCase(styler, i, "ifblock") || | |
469 | MatchNoCase(styler, i, "macro") || MatchNoCase(styler, i, "beginc++")) { | |
470 | levelNext++; | |
471 | } else if (MatchNoCase(styler, i, "endmacro") || MatchNoCase(styler, i, "endc++") || MatchNoCase(styler, i, "end")) { | |
472 | levelNext--; | |
473 | } | |
474 | } | |
9e96e16f | 475 | if (atEOL || (i == endPos-1)) { |
e14d10b0 RD |
476 | int levelUse = levelCurrent; |
477 | if (foldAtElse) { | |
478 | levelUse = levelMinCurrent; | |
479 | } | |
480 | int lev = levelUse | levelNext << 16; | |
65ec6247 RD |
481 | if (visibleChars == 0 && foldCompact) |
482 | lev |= SC_FOLDLEVELWHITEFLAG; | |
e14d10b0 | 483 | if (levelUse < levelNext) |
65ec6247 RD |
484 | lev |= SC_FOLDLEVELHEADERFLAG; |
485 | if (lev != styler.LevelAt(lineCurrent)) { | |
486 | styler.SetLevel(lineCurrent, lev); | |
487 | } | |
488 | lineCurrent++; | |
e14d10b0 RD |
489 | levelCurrent = levelNext; |
490 | levelMinCurrent = levelCurrent; | |
9e96e16f RD |
491 | if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) { |
492 | // There is an empty line at end of file so give it same level and empty | |
493 | styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); | |
494 | } | |
65ec6247 RD |
495 | visibleChars = 0; |
496 | } | |
1dcf666d RD |
497 | if (!IsASpace(ch)) |
498 | visibleChars++; | |
f6bcfd97 BP |
499 | } |
500 | } | |
501 | ||
1dcf666d RD |
502 | static const char * const EclWordListDesc[] = { |
503 | "Keywords", | |
504 | 0 | |
505 | }; | |
506 | ||
507 | LexerModule lmECL( | |
508 | SCLEX_ECL, | |
509 | ColouriseEclDoc, | |
510 | "ecl", | |
511 | FoldEclDoc, | |
512 | EclWordListDesc); |