]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexTAL.cxx
Apply patch (plus some additional changes) upgrading Scintilla to version 2.03. ...
[wxWidgets.git] / src / stc / scintilla / src / LexTAL.cxx
1 // Scintilla source code edit control
2 /** @file LexTAL.cxx
3 ** Lexer for TAL
4 ** Based on LexPascal.cxx
5 ** Written by Laurent le Tynevez
6 ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002
7 ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments)
8 ** Updated by Rod Falck, Aug 2006 Converted to TAL
9 **/
10
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <stdio.h>
15 #include <stdarg.h>
16
17 #include "Platform.h"
18
19 #include "PropSet.h"
20 #include "Accessor.h"
21 #include "KeyWords.h"
22 #include "Scintilla.h"
23 #include "SciLexer.h"
24 #include "StyleContext.h"
25
26 #ifdef SCI_NAMESPACE
27 using namespace Scintilla;
28 #endif
29
30 inline bool isTALoperator(char ch)
31 {
32 return ch == '\'' || ch == '@' || ch == '#' || isoperator(ch);
33 }
34
35 inline bool isTALwordchar(char ch)
36 {
37 return ch == '$' || ch == '^' || iswordchar(ch);
38 }
39
40 inline bool isTALwordstart(char ch)
41 {
42 return ch == '$' || ch == '^' || iswordstart(ch);
43 }
44
45 static void getRange(unsigned int start,
46 unsigned int end,
47 Accessor &styler,
48 char *s,
49 unsigned int len) {
50 unsigned int i = 0;
51 while ((i < end - start + 1) && (i < len-1)) {
52 s[i] = static_cast<char>(tolower(styler[start + i]));
53 i++;
54 }
55 s[i] = '\0';
56 }
57
58 static bool IsStreamCommentStyle(int style) {
59 return style == SCE_C_COMMENT ||
60 style == SCE_C_COMMENTDOC ||
61 style == SCE_C_COMMENTDOCKEYWORD ||
62 style == SCE_C_COMMENTDOCKEYWORDERROR;
63 }
64
65 static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) {
66 if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) {
67 styler.ColourTo(end, SCE_C_REGEX);
68 } else
69 styler.ColourTo(end, attr);
70 }
71
72 // returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm"
73 static int classifyWordTAL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInAsm) {
74 int ret = 0;
75
76 WordList& keywords = *keywordlists[0];
77 WordList& builtins = *keywordlists[1];
78 WordList& nonreserved_keywords = *keywordlists[2];
79
80 char s[100];
81 getRange(start, end, styler, s, sizeof(s));
82
83 char chAttr = SCE_C_IDENTIFIER;
84 if (isdigit(s[0]) || (s[0] == '.')) {
85 chAttr = SCE_C_NUMBER;
86 }
87 else {
88 if (keywords.InList(s)) {
89 chAttr = SCE_C_WORD;
90
91 if (strcmp(s, "asm") == 0) {
92 ret = 2;
93 }
94 else if (strcmp(s, "end") == 0) {
95 ret = -1;
96 }
97 }
98 else if (s[0] == '$' || builtins.InList(s)) {
99 chAttr = SCE_C_WORD2;
100 }
101 else if (nonreserved_keywords.InList(s)) {
102 chAttr = SCE_C_UUID;
103 }
104 }
105 ColourTo(styler, end, chAttr, (bInAsm && ret != -1));
106 return ret;
107 }
108
109 static int classifyFoldPointTAL(const char* s) {
110 int lev = 0;
111 if (!(isdigit(s[0]) || (s[0] == '.'))) {
112 if (strcmp(s, "begin") == 0 ||
113 strcmp(s, "block") == 0) {
114 lev=1;
115 } else if (strcmp(s, "end") == 0) {
116 lev=-1;
117 }
118 }
119 return lev;
120 }
121
122 static void ColouriseTALDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
123 Accessor &styler) {
124
125 styler.StartAt(startPos);
126
127 int state = initStyle;
128 if (state == SCE_C_CHARACTER) // Does not leak onto next line
129 state = SCE_C_DEFAULT;
130 char chPrev = ' ';
131 char chNext = styler[startPos];
132 unsigned int lengthDoc = startPos + length;
133
134 bool bInClassDefinition;
135
136 int currentLine = styler.GetLine(startPos);
137 if (currentLine > 0) {
138 styler.SetLineState(currentLine, styler.GetLineState(currentLine-1));
139 bInClassDefinition = (styler.GetLineState(currentLine) == 1);
140 } else {
141 styler.SetLineState(currentLine, 0);
142 bInClassDefinition = false;
143 }
144
145 bool bInAsm = (state == SCE_C_REGEX);
146 if (bInAsm)
147 state = SCE_C_DEFAULT;
148
149 styler.StartSegment(startPos);
150 int visibleChars = 0;
151 for (unsigned int i = startPos; i < lengthDoc; i++) {
152 char ch = chNext;
153
154 chNext = styler.SafeGetCharAt(i + 1);
155
156 if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
157 // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
158 // Avoid triggering two times on Dos/Win
159 // End of line
160 if (state == SCE_C_CHARACTER) {
161 ColourTo(styler, i, state, bInAsm);
162 state = SCE_C_DEFAULT;
163 }
164 visibleChars = 0;
165 currentLine++;
166 styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0));
167 }
168
169 if (styler.IsLeadByte(ch)) {
170 chNext = styler.SafeGetCharAt(i + 2);
171 chPrev = ' ';
172 i += 1;
173 continue;
174 }
175
176 if (state == SCE_C_DEFAULT) {
177 if (isTALwordstart(ch)) {
178 ColourTo(styler, i-1, state, bInAsm);
179 state = SCE_C_IDENTIFIER;
180 } else if (ch == '!' && chNext != '*') {
181 ColourTo(styler, i-1, state, bInAsm);
182 state = SCE_C_COMMENT;
183 } else if (ch == '!' && chNext == '*') {
184 ColourTo(styler, i-1, state, bInAsm);
185 state = SCE_C_COMMENTDOC;
186 } else if (ch == '-' && chNext == '-') {
187 ColourTo(styler, i-1, state, bInAsm);
188 state = SCE_C_COMMENTLINE;
189 } else if (ch == '"') {
190 ColourTo(styler, i-1, state, bInAsm);
191 state = SCE_C_STRING;
192 } else if (ch == '?' && visibleChars == 0) {
193 ColourTo(styler, i-1, state, bInAsm);
194 state = SCE_C_PREPROCESSOR;
195 } else if (isTALoperator(ch)) {
196 ColourTo(styler, i-1, state, bInAsm);
197 ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
198 }
199 } else if (state == SCE_C_IDENTIFIER) {
200 if (!isTALwordchar(ch)) {
201 int lStateChange = classifyWordTAL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm);
202
203 if(lStateChange == 1) {
204 styler.SetLineState(currentLine, 1);
205 bInClassDefinition = true;
206 } else if(lStateChange == 2) {
207 bInAsm = true;
208 } else if(lStateChange == -1) {
209 styler.SetLineState(currentLine, 0);
210 bInClassDefinition = false;
211 bInAsm = false;
212 }
213
214 state = SCE_C_DEFAULT;
215 chNext = styler.SafeGetCharAt(i + 1);
216 if (ch == '!' && chNext != '*') {
217 state = SCE_C_COMMENT;
218 } else if (ch == '!' && chNext == '*') {
219 ColourTo(styler, i-1, state, bInAsm);
220 state = SCE_C_COMMENTDOC;
221 } else if (ch == '-' && chNext == '-') {
222 state = SCE_C_COMMENTLINE;
223 } else if (ch == '"') {
224 state = SCE_C_STRING;
225 } else if (isTALoperator(ch)) {
226 ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
227 }
228 }
229 } else {
230 if (state == SCE_C_PREPROCESSOR) {
231 if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
232 ColourTo(styler, i-1, state, bInAsm);
233 state = SCE_C_DEFAULT;
234 }
235 } else if (state == SCE_C_COMMENT) {
236 if (ch == '!' || (ch == '\r' || ch == '\n') ) {
237 ColourTo(styler, i, state, bInAsm);
238 state = SCE_C_DEFAULT;
239 }
240 } else if (state == SCE_C_COMMENTDOC) {
241 if (ch == '!' || (ch == '\r' || ch == '\n')) {
242 if (((i > styler.GetStartSegment() + 2) || (
243 (initStyle == SCE_C_COMMENTDOC) &&
244 (styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
245 ColourTo(styler, i, state, bInAsm);
246 state = SCE_C_DEFAULT;
247 }
248 }
249 } else if (state == SCE_C_COMMENTLINE) {
250 if (ch == '\r' || ch == '\n') {
251 ColourTo(styler, i-1, state, bInAsm);
252 state = SCE_C_DEFAULT;
253 }
254 } else if (state == SCE_C_STRING) {
255 if (ch == '"') {
256 ColourTo(styler, i, state, bInAsm);
257 state = SCE_C_DEFAULT;
258 }
259 }
260 }
261 if (!isspacechar(ch))
262 visibleChars++;
263 chPrev = ch;
264 }
265 ColourTo(styler, lengthDoc - 1, state, bInAsm);
266 }
267
268 static void FoldTALDoc(unsigned int startPos, int length, int initStyle, WordList *[],
269 Accessor &styler) {
270 bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
271 bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
272 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
273 unsigned int endPos = startPos + length;
274 int visibleChars = 0;
275 int lineCurrent = styler.GetLine(startPos);
276 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
277 int levelCurrent = levelPrev;
278 char chNext = styler[startPos];
279 int styleNext = styler.StyleAt(startPos);
280 int style = initStyle;
281 bool was_end = false;
282 bool section = false;
283
284 int lastStart = 0;
285
286 for (unsigned int i = startPos; i < endPos; i++) {
287 char ch = chNext;
288 chNext = styler.SafeGetCharAt(i + 1);
289 int stylePrev = style;
290 style = styleNext;
291 styleNext = styler.StyleAt(i + 1);
292 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
293
294 if (stylePrev == SCE_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_UUID || style == SCE_C_PREPROCESSOR))
295 {
296 // Store last word start point.
297 lastStart = i;
298 }
299
300 if (stylePrev == SCE_C_WORD || style == SCE_C_UUID || stylePrev == SCE_C_PREPROCESSOR) {
301 if(isTALwordchar(ch) && !isTALwordchar(chNext)) {
302 char s[100];
303 getRange(lastStart, i, styler, s, sizeof(s));
304 if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0)
305 {
306 section = true;
307 levelCurrent = 1;
308 levelPrev = 0;
309 }
310 else if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_UUID)
311 {
312 if (strcmp(s, "block") == 0)
313 {
314 // block keyword is ignored immediately after end keyword
315 if (!was_end)
316 levelCurrent++;
317 }
318 else
319 levelCurrent += classifyFoldPointTAL(s);
320 if (strcmp(s, "end") == 0)
321 {
322 was_end = true;
323 }
324 else
325 {
326 was_end = false;
327 }
328 }
329 }
330 }
331
332 if (foldComment && (style == SCE_C_COMMENTLINE)) {
333 if ((ch == '/') && (chNext == '/')) {
334 char chNext2 = styler.SafeGetCharAt(i + 2);
335 if (chNext2 == '{') {
336 levelCurrent++;
337 } else if (chNext2 == '}') {
338 levelCurrent--;
339 }
340 }
341 }
342
343 if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
344 if (ch == '{' && chNext == '$') {
345 unsigned int j=i+2; // skip {$
346 while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
347 j++;
348 }
349 if (styler.Match(j, "region") || styler.Match(j, "if")) {
350 levelCurrent++;
351 } else if (styler.Match(j, "end")) {
352 levelCurrent--;
353 }
354 }
355 }
356
357 if (foldComment && IsStreamCommentStyle(style)) {
358 if (!IsStreamCommentStyle(stylePrev)) {
359 levelCurrent++;
360 } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
361 // Comments don't end at end of line and the next character may be unstyled.
362 levelCurrent--;
363 }
364 }
365
366 if (atEOL) {
367 int lev = levelPrev | SC_FOLDLEVELBASE;
368 if (visibleChars == 0 && foldCompact)
369 lev |= SC_FOLDLEVELWHITEFLAG;
370 if ((levelCurrent > levelPrev || section) && (visibleChars > 0))
371 lev |= SC_FOLDLEVELHEADERFLAG;
372 if (lev != styler.LevelAt(lineCurrent)) {
373 styler.SetLevel(lineCurrent, lev);
374 }
375 lineCurrent++;
376 levelPrev = levelCurrent;
377 visibleChars = 0;
378 section = false;
379 }
380
381 if (!isspacechar(ch))
382 visibleChars++;
383 }
384
385 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
386 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
387 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
388 }
389
390 static const char * const TALWordListDesc[] = {
391 "Keywords",
392 "Builtins",
393 0
394 };
395
396 LexerModule lmTAL(SCLEX_TAL, ColouriseTALDoc, "TAL", FoldTALDoc, TALWordListDesc);