]>
Commit | Line | Data |
---|---|---|
88a8b04e RD |
1 | // Scintilla source code edit control |
2 | /** @file LexScriptol.cxx | |
3 | ** Lexer for Scriptol. | |
4 | **/ | |
5 | ||
6 | #include <stdlib.h> | |
7 | #include <string.h> | |
88a8b04e RD |
8 | #include <stdio.h> |
9 | #include <stdarg.h> | |
1dcf666d RD |
10 | #include <assert.h> |
11 | #include <ctype.h> | |
88a8b04e | 12 | |
1dcf666d | 13 | #include "ILexer.h" |
88a8b04e RD |
14 | #include "Scintilla.h" |
15 | #include "SciLexer.h" | |
7e0c58e9 | 16 | |
1dcf666d RD |
17 | #include "WordList.h" |
18 | #include "LexAccessor.h" | |
19 | #include "Accessor.h" | |
20 | #include "StyleContext.h" | |
21 | #include "CharacterSet.h" | |
22 | #include "LexerModule.h" | |
23 | ||
7e0c58e9 RD |
24 | #ifdef SCI_NAMESPACE |
25 | using namespace Scintilla; | |
26 | #endif | |
88a8b04e RD |
27 | |
28 | static void ClassifyWordSol(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) | |
29 | { | |
8e54aaed RD |
30 | char s[100]; |
31 | bool wordIsNumber = isdigit(styler[start]) != 0; | |
32 | for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) | |
33 | { | |
34 | s[i] = styler[start + i]; | |
35 | s[i + 1] = '\0'; | |
36 | } | |
37 | char chAttr = SCE_SCRIPTOL_IDENTIFIER; | |
38 | if (0 == strcmp(prevWord, "class")) chAttr = SCE_SCRIPTOL_CLASSNAME; | |
39 | else if (wordIsNumber) chAttr = SCE_SCRIPTOL_NUMBER; | |
40 | else if (keywords.InList(s)) chAttr = SCE_SCRIPTOL_KEYWORD; | |
88a8b04e RD |
41 | else for (unsigned int i = 0; i < end - start + 1; i++) // test dotted idents |
42 | { | |
8e54aaed | 43 | if (styler[start + i] == '.') |
88a8b04e | 44 | { |
8e54aaed RD |
45 | styler.ColourTo(start + i - 1, chAttr); |
46 | styler.ColourTo(start + i, SCE_SCRIPTOL_OPERATOR); | |
47 | } | |
48 | } | |
49 | styler.ColourTo(end, chAttr); | |
50 | strcpy(prevWord, s); | |
88a8b04e RD |
51 | } |
52 | ||
53 | static bool IsSolComment(Accessor &styler, int pos, int len) | |
54 | { | |
88a8b04e RD |
55 | if(len > 0) |
56 | { | |
1dcf666d | 57 | char c = styler[pos]; |
88a8b04e RD |
58 | if(c == '`') return true; |
59 | if(len > 1) | |
60 | { | |
61 | if(c == '/') | |
62 | { | |
63 | c = styler[pos + 1]; | |
64 | if(c == '/') return true; | |
65 | if(c == '*') return true; | |
66 | } | |
67 | } | |
68 | } | |
69 | return false; | |
70 | } | |
71 | ||
8e54aaed | 72 | static bool IsSolStringStart(char ch) |
88a8b04e RD |
73 | { |
74 | if (ch == '\'' || ch == '"') return true; | |
8e54aaed | 75 | return false; |
88a8b04e RD |
76 | } |
77 | ||
8e54aaed | 78 | static bool IsSolWordStart(char ch) |
88a8b04e | 79 | { |
8e54aaed | 80 | return (iswordchar(ch) && !IsSolStringStart(ch)); |
88a8b04e RD |
81 | } |
82 | ||
8e54aaed | 83 | |
88a8b04e RD |
84 | static int GetSolStringState(Accessor &styler, int i, int *nextIndex) |
85 | { | |
86 | char ch = styler.SafeGetCharAt(i); | |
87 | char chNext = styler.SafeGetCharAt(i + 1); | |
88 | ||
8e54aaed RD |
89 | if (ch != '\"' && ch != '\'') |
90 | { | |
91 | *nextIndex = i + 1; | |
92 | return SCE_SCRIPTOL_DEFAULT; | |
88a8b04e | 93 | } |
8e54aaed RD |
94 | // ch is either single or double quotes in string |
95 | // code below seem non-sense but is here for future extensions | |
88a8b04e | 96 | if (ch == chNext && ch == styler.SafeGetCharAt(i + 2)) |
8e54aaed RD |
97 | { |
98 | *nextIndex = i + 3; | |
99 | if(ch == '\"') return SCE_SCRIPTOL_TRIPLE; | |
100 | if(ch == '\'') return SCE_SCRIPTOL_TRIPLE; | |
101 | return SCE_SCRIPTOL_STRING; | |
88a8b04e | 102 | } |
8e54aaed RD |
103 | else |
104 | { | |
105 | *nextIndex = i + 1; | |
106 | if (ch == '"') return SCE_SCRIPTOL_STRING; | |
107 | else return SCE_SCRIPTOL_STRING; | |
88a8b04e RD |
108 | } |
109 | } | |
110 | ||
8e54aaed | 111 | |
88a8b04e | 112 | static void ColouriseSolDoc(unsigned int startPos, int length, int initStyle, |
8e54aaed | 113 | WordList *keywordlists[], Accessor &styler) |
88a8b04e RD |
114 | { |
115 | ||
116 | int lengthDoc = startPos + length; | |
8e54aaed | 117 | char stringType = '\"'; |
88a8b04e | 118 | |
88a8b04e | 119 | if (startPos > 0) |
88a8b04e | 120 | { |
8e54aaed RD |
121 | int lineCurrent = styler.GetLine(startPos); |
122 | if (lineCurrent > 0) | |
123 | { | |
124 | startPos = styler.LineStart(lineCurrent-1); | |
125 | if (startPos == 0) initStyle = SCE_SCRIPTOL_DEFAULT; | |
126 | else initStyle = styler.StyleAt(startPos-1); | |
127 | } | |
88a8b04e RD |
128 | } |
129 | ||
130 | styler.StartAt(startPos, 127); | |
131 | ||
132 | WordList &keywords = *keywordlists[0]; | |
133 | ||
134 | int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level"); | |
135 | char prevWord[200]; | |
136 | prevWord[0] = '\0'; | |
8e54aaed | 137 | if (length == 0) return; |
88a8b04e RD |
138 | |
139 | int state = initStyle & 31; | |
140 | ||
141 | int nextIndex = 0; | |
8e54aaed RD |
142 | char chPrev = ' '; |
143 | char chPrev2 = ' '; | |
144 | char chNext = styler[startPos]; | |
88a8b04e RD |
145 | styler.StartSegment(startPos); |
146 | bool atStartLine = true; | |
147 | int spaceFlags = 0; | |
148 | for (int i = startPos; i < lengthDoc; i++) | |
8e54aaed | 149 | { |
88a8b04e | 150 | |
8e54aaed RD |
151 | if (atStartLine) |
152 | { | |
88a8b04e RD |
153 | char chBad = static_cast<char>(64); |
154 | char chGood = static_cast<char>(0); | |
155 | char chFlags = chGood; | |
156 | ||
157 | if (whingeLevel == 1) | |
158 | { | |
8e54aaed | 159 | chFlags = (spaceFlags & wsInconsistent) ? chBad : chGood; |
88a8b04e RD |
160 | } |
161 | else if (whingeLevel == 2) | |
162 | { | |
8e54aaed | 163 | chFlags = (spaceFlags & wsSpaceTab) ? chBad : chGood; |
88a8b04e RD |
164 | } |
165 | else if (whingeLevel == 3) | |
166 | { | |
8e54aaed | 167 | chFlags = (spaceFlags & wsSpace) ? chBad : chGood; |
88a8b04e RD |
168 | } |
169 | else if (whingeLevel == 4) | |
170 | { | |
8e54aaed | 171 | chFlags = (spaceFlags & wsTab) ? chBad : chGood; |
88a8b04e RD |
172 | } |
173 | styler.SetFlags(chFlags, static_cast<char>(state)); | |
174 | atStartLine = false; | |
175 | } | |
176 | ||
8e54aaed RD |
177 | char ch = chNext; |
178 | chNext = styler.SafeGetCharAt(i + 1); | |
88a8b04e | 179 | |
8e54aaed RD |
180 | if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) |
181 | { | |
182 | if ((state == SCE_SCRIPTOL_DEFAULT) || | |
183 | (state == SCE_SCRIPTOL_TRIPLE) || | |
184 | (state == SCE_SCRIPTOL_COMMENTBLOCK)) | |
185 | { | |
186 | styler.ColourTo(i, state); | |
187 | } | |
188 | atStartLine = true; | |
189 | } | |
88a8b04e | 190 | |
8e54aaed RD |
191 | if (styler.IsLeadByte(ch)) |
192 | { | |
193 | chNext = styler.SafeGetCharAt(i + 2); | |
194 | chPrev = ' '; | |
195 | chPrev2 = ' '; | |
196 | i += 1; | |
197 | continue; | |
198 | } | |
88a8b04e | 199 | |
8e54aaed RD |
200 | if (state == SCE_SCRIPTOL_STRINGEOL) |
201 | { | |
202 | if (ch != '\r' && ch != '\n') | |
88a8b04e | 203 | { |
8e54aaed RD |
204 | styler.ColourTo(i - 1, state); |
205 | state = SCE_SCRIPTOL_DEFAULT; | |
88a8b04e | 206 | } |
8e54aaed | 207 | } |
88a8b04e | 208 | |
8e54aaed RD |
209 | if (state == SCE_SCRIPTOL_DEFAULT) |
210 | { | |
211 | if (IsSolWordStart(ch)) | |
88a8b04e | 212 | { |
8e54aaed RD |
213 | styler.ColourTo(i - 1, state); |
214 | state = SCE_SCRIPTOL_KEYWORD; | |
88a8b04e RD |
215 | } |
216 | else if (ch == '`') | |
217 | { | |
8e54aaed RD |
218 | styler.ColourTo(i - 1, state); |
219 | state = SCE_SCRIPTOL_COMMENTLINE; | |
88a8b04e RD |
220 | } |
221 | else if (ch == '/') | |
222 | { | |
8e54aaed RD |
223 | styler.ColourTo(i - 1, state); |
224 | if(chNext == '/') state = SCE_SCRIPTOL_CSTYLE; | |
225 | if(chNext == '*') state = SCE_SCRIPTOL_COMMENTBLOCK; | |
88a8b04e RD |
226 | } |
227 | ||
8e54aaed | 228 | else if (IsSolStringStart(ch)) |
88a8b04e RD |
229 | { |
230 | styler.ColourTo(i - 1, state); | |
231 | state = GetSolStringState(styler, i, &nextIndex); | |
8e54aaed RD |
232 | if(state == SCE_SCRIPTOL_STRING) |
233 | { | |
234 | stringType = ch; | |
235 | } | |
88a8b04e RD |
236 | if (nextIndex != i + 1) |
237 | { | |
8e54aaed RD |
238 | i = nextIndex - 1; |
239 | ch = ' '; | |
240 | chPrev = ' '; | |
241 | chNext = styler.SafeGetCharAt(i + 1); | |
88a8b04e | 242 | } |
8e54aaed | 243 | } |
88a8b04e RD |
244 | else if (isoperator(ch)) |
245 | { | |
8e54aaed RD |
246 | styler.ColourTo(i - 1, state); |
247 | styler.ColourTo(i, SCE_SCRIPTOL_OPERATOR); | |
248 | } | |
88a8b04e | 249 | } |
8e54aaed | 250 | else if (state == SCE_SCRIPTOL_KEYWORD) |
88a8b04e RD |
251 | { |
252 | if (!iswordchar(ch)) | |
253 | { | |
254 | ClassifyWordSol(styler.GetStartSegment(), i - 1, keywords, styler, prevWord); | |
8e54aaed | 255 | state = SCE_SCRIPTOL_DEFAULT; |
88a8b04e RD |
256 | if (ch == '`') |
257 | { | |
8e54aaed | 258 | state = chNext == '`' ? SCE_SCRIPTOL_PERSISTENT : SCE_SCRIPTOL_COMMENTLINE; |
88a8b04e | 259 | } |
8e54aaed | 260 | else if (IsSolStringStart(ch)) |
88a8b04e RD |
261 | { |
262 | styler.ColourTo(i - 1, state); | |
263 | state = GetSolStringState(styler, i, &nextIndex); | |
8e54aaed | 264 | if (nextIndex != i + 1) |
88a8b04e | 265 | { |
8e54aaed RD |
266 | i = nextIndex - 1; |
267 | ch = ' '; | |
268 | chPrev = ' '; | |
269 | chNext = styler.SafeGetCharAt(i + 1); | |
270 | } | |
88a8b04e RD |
271 | } |
272 | else if (isoperator(ch)) | |
273 | { | |
8e54aaed | 274 | styler.ColourTo(i, SCE_SCRIPTOL_OPERATOR); |
88a8b04e RD |
275 | } |
276 | } | |
277 | } | |
278 | else | |
279 | { | |
8e54aaed RD |
280 | if (state == SCE_SCRIPTOL_COMMENTLINE || |
281 | state == SCE_SCRIPTOL_PERSISTENT || | |
282 | state == SCE_SCRIPTOL_CSTYLE) | |
88a8b04e | 283 | { |
8e54aaed | 284 | if (ch == '\r' || ch == '\n') |
88a8b04e | 285 | { |
8e54aaed RD |
286 | styler.ColourTo(i - 1, state); |
287 | state = SCE_SCRIPTOL_DEFAULT; | |
88a8b04e RD |
288 | } |
289 | } | |
8e54aaed | 290 | else if(state == SCE_SCRIPTOL_COMMENTBLOCK) |
88a8b04e | 291 | { |
8e54aaed RD |
292 | if(chPrev == '*' && ch == '/') |
293 | { | |
294 | styler.ColourTo(i, state); | |
295 | state = SCE_SCRIPTOL_DEFAULT; | |
296 | } | |
88a8b04e | 297 | } |
8e54aaed RD |
298 | else if ((state == SCE_SCRIPTOL_STRING) || |
299 | (state == SCE_SCRIPTOL_CHARACTER)) | |
88a8b04e | 300 | { |
8e54aaed | 301 | if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) |
88a8b04e | 302 | { |
8e54aaed RD |
303 | styler.ColourTo(i - 1, state); |
304 | state = SCE_SCRIPTOL_STRINGEOL; | |
305 | } | |
88a8b04e RD |
306 | else if (ch == '\\') |
307 | { | |
308 | if (chNext == '\"' || chNext == '\'' || chNext == '\\') | |
309 | { | |
8e54aaed RD |
310 | i++; |
311 | ch = chNext; | |
312 | chNext = styler.SafeGetCharAt(i + 1); | |
88a8b04e | 313 | } |
88a8b04e | 314 | } |
8e54aaed | 315 | else if ((ch == '\"') || (ch == '\'')) |
88a8b04e | 316 | { |
8e54aaed RD |
317 | // must match the entered quote type |
318 | if(ch == stringType) | |
319 | { | |
320 | styler.ColourTo(i, state); | |
321 | state = SCE_SCRIPTOL_DEFAULT; | |
322 | } | |
323 | } | |
324 | } | |
325 | else if (state == SCE_SCRIPTOL_TRIPLE) | |
88a8b04e | 326 | { |
8e54aaed RD |
327 | if ((ch == '\'' && chPrev == '\'' && chPrev2 == '\'') || |
328 | (ch == '\"' && chPrev == '\"' && chPrev2 == '\"')) | |
88a8b04e RD |
329 | { |
330 | styler.ColourTo(i, state); | |
8e54aaed | 331 | state = SCE_SCRIPTOL_DEFAULT; |
88a8b04e | 332 | } |
8e54aaed | 333 | } |
1dcf666d | 334 | |
8e54aaed RD |
335 | } |
336 | chPrev2 = chPrev; | |
337 | chPrev = ch; | |
88a8b04e | 338 | } |
8e54aaed RD |
339 | if (state == SCE_SCRIPTOL_KEYWORD) |
340 | { | |
341 | ClassifyWordSol(styler.GetStartSegment(), | |
342 | lengthDoc-1, keywords, styler, prevWord); | |
88a8b04e | 343 | } |
8e54aaed RD |
344 | else |
345 | { | |
346 | styler.ColourTo(lengthDoc-1, state); | |
88a8b04e RD |
347 | } |
348 | } | |
349 | ||
350 | static void FoldSolDoc(unsigned int startPos, int length, int initStyle, | |
351 | WordList *[], Accessor &styler) | |
352 | { | |
353 | int lengthDoc = startPos + length; | |
354 | ||
88a8b04e | 355 | int lineCurrent = styler.GetLine(startPos); |
8e54aaed | 356 | if (startPos > 0) |
88a8b04e | 357 | { |
8e54aaed RD |
358 | if (lineCurrent > 0) |
359 | { | |
360 | lineCurrent--; | |
361 | startPos = styler.LineStart(lineCurrent); | |
362 | if (startPos == 0) | |
363 | initStyle = SCE_SCRIPTOL_DEFAULT; | |
364 | else | |
365 | initStyle = styler.StyleAt(startPos-1); | |
366 | } | |
88a8b04e RD |
367 | } |
368 | int state = initStyle & 31; | |
369 | int spaceFlags = 0; | |
370 | int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsSolComment); | |
1dcf666d | 371 | if (state == SCE_SCRIPTOL_TRIPLE) |
8e54aaed | 372 | indentCurrent |= SC_FOLDLEVELWHITEFLAG; |
88a8b04e RD |
373 | char chNext = styler[startPos]; |
374 | for (int i = startPos; i < lengthDoc; i++) | |
8e54aaed | 375 | { |
88a8b04e RD |
376 | char ch = chNext; |
377 | chNext = styler.SafeGetCharAt(i + 1); | |
378 | int style = styler.StyleAt(i) & 31; | |
379 | ||
380 | if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) | |
88a8b04e | 381 | { |
8e54aaed RD |
382 | int lev = indentCurrent; |
383 | int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsSolComment); | |
384 | if (style == SCE_SCRIPTOL_TRIPLE) | |
385 | indentNext |= SC_FOLDLEVELWHITEFLAG; | |
386 | if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) | |
88a8b04e | 387 | { |
8e54aaed RD |
388 | // Only non whitespace lines can be headers |
389 | if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) | |
390 | { | |
391 | lev |= SC_FOLDLEVELHEADERFLAG; | |
392 | } | |
393 | else if (indentNext & SC_FOLDLEVELWHITEFLAG) | |
394 | { | |
395 | // Line after is blank so check the next - maybe should continue further? | |
396 | int spaceFlags2 = 0; | |
397 | int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsSolComment); | |
398 | if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) | |
399 | { | |
400 | lev |= SC_FOLDLEVELHEADERFLAG; | |
401 | } | |
402 | } | |
403 | } | |
404 | indentCurrent = indentNext; | |
405 | styler.SetLevel(lineCurrent, lev); | |
406 | lineCurrent++; | |
88a8b04e RD |
407 | } |
408 | } | |
409 | } | |
410 | ||
411 | LexerModule lmScriptol(SCLEX_SCRIPTOL, ColouriseSolDoc, "scriptol", FoldSolDoc); |