]>
Commit | Line | Data |
---|---|---|
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 <stdio.h> | |
9 | #include <stdarg.h> | |
10 | #include <assert.h> | |
11 | #include <ctype.h> | |
12 | ||
13 | #include "ILexer.h" | |
14 | #include "Scintilla.h" | |
15 | #include "SciLexer.h" | |
16 | ||
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 | ||
24 | #ifdef SCI_NAMESPACE | |
25 | using namespace Scintilla; | |
26 | #endif | |
27 | ||
28 | static void ClassifyWordSol(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) | |
29 | { | |
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; | |
41 | else for (unsigned int i = 0; i < end - start + 1; i++) // test dotted idents | |
42 | { | |
43 | if (styler[start + i] == '.') | |
44 | { | |
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); | |
51 | } | |
52 | ||
53 | static bool IsSolComment(Accessor &styler, int pos, int len) | |
54 | { | |
55 | if(len > 0) | |
56 | { | |
57 | char c = styler[pos]; | |
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 | ||
72 | static bool IsSolStringStart(char ch) | |
73 | { | |
74 | if (ch == '\'' || ch == '"') return true; | |
75 | return false; | |
76 | } | |
77 | ||
78 | static bool IsSolWordStart(char ch) | |
79 | { | |
80 | return (iswordchar(ch) && !IsSolStringStart(ch)); | |
81 | } | |
82 | ||
83 | ||
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 | ||
89 | if (ch != '\"' && ch != '\'') | |
90 | { | |
91 | *nextIndex = i + 1; | |
92 | return SCE_SCRIPTOL_DEFAULT; | |
93 | } | |
94 | // ch is either single or double quotes in string | |
95 | // code below seem non-sense but is here for future extensions | |
96 | if (ch == chNext && ch == styler.SafeGetCharAt(i + 2)) | |
97 | { | |
98 | *nextIndex = i + 3; | |
99 | if(ch == '\"') return SCE_SCRIPTOL_TRIPLE; | |
100 | if(ch == '\'') return SCE_SCRIPTOL_TRIPLE; | |
101 | return SCE_SCRIPTOL_STRING; | |
102 | } | |
103 | else | |
104 | { | |
105 | *nextIndex = i + 1; | |
106 | if (ch == '"') return SCE_SCRIPTOL_STRING; | |
107 | else return SCE_SCRIPTOL_STRING; | |
108 | } | |
109 | } | |
110 | ||
111 | ||
112 | static void ColouriseSolDoc(unsigned int startPos, int length, int initStyle, | |
113 | WordList *keywordlists[], Accessor &styler) | |
114 | { | |
115 | ||
116 | int lengthDoc = startPos + length; | |
117 | char stringType = '\"'; | |
118 | ||
119 | if (startPos > 0) | |
120 | { | |
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 | } | |
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'; | |
137 | if (length == 0) return; | |
138 | ||
139 | int state = initStyle & 31; | |
140 | ||
141 | int nextIndex = 0; | |
142 | char chPrev = ' '; | |
143 | char chPrev2 = ' '; | |
144 | char chNext = styler[startPos]; | |
145 | styler.StartSegment(startPos); | |
146 | bool atStartLine = true; | |
147 | int spaceFlags = 0; | |
148 | for (int i = startPos; i < lengthDoc; i++) | |
149 | { | |
150 | ||
151 | if (atStartLine) | |
152 | { | |
153 | char chBad = static_cast<char>(64); | |
154 | char chGood = static_cast<char>(0); | |
155 | char chFlags = chGood; | |
156 | ||
157 | if (whingeLevel == 1) | |
158 | { | |
159 | chFlags = (spaceFlags & wsInconsistent) ? chBad : chGood; | |
160 | } | |
161 | else if (whingeLevel == 2) | |
162 | { | |
163 | chFlags = (spaceFlags & wsSpaceTab) ? chBad : chGood; | |
164 | } | |
165 | else if (whingeLevel == 3) | |
166 | { | |
167 | chFlags = (spaceFlags & wsSpace) ? chBad : chGood; | |
168 | } | |
169 | else if (whingeLevel == 4) | |
170 | { | |
171 | chFlags = (spaceFlags & wsTab) ? chBad : chGood; | |
172 | } | |
173 | styler.SetFlags(chFlags, static_cast<char>(state)); | |
174 | atStartLine = false; | |
175 | } | |
176 | ||
177 | char ch = chNext; | |
178 | chNext = styler.SafeGetCharAt(i + 1); | |
179 | ||
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 | } | |
190 | ||
191 | if (styler.IsLeadByte(ch)) | |
192 | { | |
193 | chNext = styler.SafeGetCharAt(i + 2); | |
194 | chPrev = ' '; | |
195 | chPrev2 = ' '; | |
196 | i += 1; | |
197 | continue; | |
198 | } | |
199 | ||
200 | if (state == SCE_SCRIPTOL_STRINGEOL) | |
201 | { | |
202 | if (ch != '\r' && ch != '\n') | |
203 | { | |
204 | styler.ColourTo(i - 1, state); | |
205 | state = SCE_SCRIPTOL_DEFAULT; | |
206 | } | |
207 | } | |
208 | ||
209 | if (state == SCE_SCRIPTOL_DEFAULT) | |
210 | { | |
211 | if (IsSolWordStart(ch)) | |
212 | { | |
213 | styler.ColourTo(i - 1, state); | |
214 | state = SCE_SCRIPTOL_KEYWORD; | |
215 | } | |
216 | else if (ch == '`') | |
217 | { | |
218 | styler.ColourTo(i - 1, state); | |
219 | state = SCE_SCRIPTOL_COMMENTLINE; | |
220 | } | |
221 | else if (ch == '/') | |
222 | { | |
223 | styler.ColourTo(i - 1, state); | |
224 | if(chNext == '/') state = SCE_SCRIPTOL_CSTYLE; | |
225 | if(chNext == '*') state = SCE_SCRIPTOL_COMMENTBLOCK; | |
226 | } | |
227 | ||
228 | else if (IsSolStringStart(ch)) | |
229 | { | |
230 | styler.ColourTo(i - 1, state); | |
231 | state = GetSolStringState(styler, i, &nextIndex); | |
232 | if(state == SCE_SCRIPTOL_STRING) | |
233 | { | |
234 | stringType = ch; | |
235 | } | |
236 | if (nextIndex != i + 1) | |
237 | { | |
238 | i = nextIndex - 1; | |
239 | ch = ' '; | |
240 | chPrev = ' '; | |
241 | chNext = styler.SafeGetCharAt(i + 1); | |
242 | } | |
243 | } | |
244 | else if (isoperator(ch)) | |
245 | { | |
246 | styler.ColourTo(i - 1, state); | |
247 | styler.ColourTo(i, SCE_SCRIPTOL_OPERATOR); | |
248 | } | |
249 | } | |
250 | else if (state == SCE_SCRIPTOL_KEYWORD) | |
251 | { | |
252 | if (!iswordchar(ch)) | |
253 | { | |
254 | ClassifyWordSol(styler.GetStartSegment(), i - 1, keywords, styler, prevWord); | |
255 | state = SCE_SCRIPTOL_DEFAULT; | |
256 | if (ch == '`') | |
257 | { | |
258 | state = chNext == '`' ? SCE_SCRIPTOL_PERSISTENT : SCE_SCRIPTOL_COMMENTLINE; | |
259 | } | |
260 | else if (IsSolStringStart(ch)) | |
261 | { | |
262 | styler.ColourTo(i - 1, state); | |
263 | state = GetSolStringState(styler, i, &nextIndex); | |
264 | if (nextIndex != i + 1) | |
265 | { | |
266 | i = nextIndex - 1; | |
267 | ch = ' '; | |
268 | chPrev = ' '; | |
269 | chNext = styler.SafeGetCharAt(i + 1); | |
270 | } | |
271 | } | |
272 | else if (isoperator(ch)) | |
273 | { | |
274 | styler.ColourTo(i, SCE_SCRIPTOL_OPERATOR); | |
275 | } | |
276 | } | |
277 | } | |
278 | else | |
279 | { | |
280 | if (state == SCE_SCRIPTOL_COMMENTLINE || | |
281 | state == SCE_SCRIPTOL_PERSISTENT || | |
282 | state == SCE_SCRIPTOL_CSTYLE) | |
283 | { | |
284 | if (ch == '\r' || ch == '\n') | |
285 | { | |
286 | styler.ColourTo(i - 1, state); | |
287 | state = SCE_SCRIPTOL_DEFAULT; | |
288 | } | |
289 | } | |
290 | else if(state == SCE_SCRIPTOL_COMMENTBLOCK) | |
291 | { | |
292 | if(chPrev == '*' && ch == '/') | |
293 | { | |
294 | styler.ColourTo(i, state); | |
295 | state = SCE_SCRIPTOL_DEFAULT; | |
296 | } | |
297 | } | |
298 | else if ((state == SCE_SCRIPTOL_STRING) || | |
299 | (state == SCE_SCRIPTOL_CHARACTER)) | |
300 | { | |
301 | if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) | |
302 | { | |
303 | styler.ColourTo(i - 1, state); | |
304 | state = SCE_SCRIPTOL_STRINGEOL; | |
305 | } | |
306 | else if (ch == '\\') | |
307 | { | |
308 | if (chNext == '\"' || chNext == '\'' || chNext == '\\') | |
309 | { | |
310 | i++; | |
311 | ch = chNext; | |
312 | chNext = styler.SafeGetCharAt(i + 1); | |
313 | } | |
314 | } | |
315 | else if ((ch == '\"') || (ch == '\'')) | |
316 | { | |
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) | |
326 | { | |
327 | if ((ch == '\'' && chPrev == '\'' && chPrev2 == '\'') || | |
328 | (ch == '\"' && chPrev == '\"' && chPrev2 == '\"')) | |
329 | { | |
330 | styler.ColourTo(i, state); | |
331 | state = SCE_SCRIPTOL_DEFAULT; | |
332 | } | |
333 | } | |
334 | ||
335 | } | |
336 | chPrev2 = chPrev; | |
337 | chPrev = ch; | |
338 | } | |
339 | if (state == SCE_SCRIPTOL_KEYWORD) | |
340 | { | |
341 | ClassifyWordSol(styler.GetStartSegment(), | |
342 | lengthDoc-1, keywords, styler, prevWord); | |
343 | } | |
344 | else | |
345 | { | |
346 | styler.ColourTo(lengthDoc-1, state); | |
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 | ||
355 | int lineCurrent = styler.GetLine(startPos); | |
356 | if (startPos > 0) | |
357 | { | |
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 | } | |
367 | } | |
368 | int state = initStyle & 31; | |
369 | int spaceFlags = 0; | |
370 | int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsSolComment); | |
371 | if (state == SCE_SCRIPTOL_TRIPLE) | |
372 | indentCurrent |= SC_FOLDLEVELWHITEFLAG; | |
373 | char chNext = styler[startPos]; | |
374 | for (int i = startPos; i < lengthDoc; i++) | |
375 | { | |
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)) | |
381 | { | |
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)) | |
387 | { | |
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++; | |
407 | } | |
408 | } | |
409 | } | |
410 | ||
411 | LexerModule lmScriptol(SCLEX_SCRIPTOL, ColouriseSolDoc, "scriptol", FoldSolDoc); |