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