]> git.saurik.com Git - wxWidgets.git/blame - src/stc/scintilla/src/LexTACL.cxx
Apply patch (plus some additional changes) upgrading Scintilla to version 2.03. ...
[wxWidgets.git] / src / stc / scintilla / src / LexTACL.cxx
CommitLineData
9e96e16f
RD
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 TACL
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
27using namespace Scintilla;
28#endif
29
30inline bool isTACLoperator(char ch)
31 {
32 return ch == '\'' || isoperator(ch);
33 }
34
35inline bool isTACLwordchar(char ch)
36 {
37 return ch == '#' || ch == '^' || ch == '|' || ch == '_' || iswordchar(ch);
38 }
39
40inline bool isTACLwordstart(char ch)
41 {
42 return ch == '#' || ch == '|' || ch == '_' || iswordstart(ch);
43 }
44
45static 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
58static 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
65static 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"
73static int classifyWordTACL(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& commands = *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 (s[0] == '#' || 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 (commands.InList(s)) {
102 chAttr = SCE_C_UUID;
103 }
104 else if (strcmp(s, "comment") == 0) {
105 chAttr = SCE_C_COMMENTLINE;
106 ret = 3;
107 }
108 }
109 ColourTo(styler, end, chAttr, (bInAsm && ret != -1));
110 return ret;
111}
112
113static int classifyFoldPointTACL(const char* s) {
114 int lev = 0;
115 if (s[0] == '[')
116 lev=1;
117 else if (s[0] == ']')
118 lev=-1;
119 return lev;
120}
121
122static void ColouriseTACLDoc(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 unsigned int i;
152 for (i = startPos; i < lengthDoc; i++) {
153 char ch = chNext;
154
155 chNext = styler.SafeGetCharAt(i + 1);
156
157 if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
158 // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
159 // Avoid triggering two times on Dos/Win
160 // End of line
161 if (state == SCE_C_CHARACTER) {
162 ColourTo(styler, i, state, bInAsm);
163 state = SCE_C_DEFAULT;
164 }
165 visibleChars = 0;
166 currentLine++;
167 styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0));
168 }
169
170 if (styler.IsLeadByte(ch)) {
171 chNext = styler.SafeGetCharAt(i + 2);
172 chPrev = ' ';
173 i += 1;
174 continue;
175 }
176
177 if (state == SCE_C_DEFAULT) {
178 if (isTACLwordstart(ch)) {
179 ColourTo(styler, i-1, state, bInAsm);
180 state = SCE_C_IDENTIFIER;
181 } else if (ch == '{') {
182 ColourTo(styler, i-1, state, bInAsm);
183 state = SCE_C_COMMENT;
184 } else if (ch == '{' && chNext == '*') {
185 ColourTo(styler, i-1, state, bInAsm);
186 state = SCE_C_COMMENTDOC;
187 } else if (ch == '=' && chNext == '=') {
188 ColourTo(styler, i-1, state, bInAsm);
189 state = SCE_C_COMMENTLINE;
190 } else if (ch == '"') {
191 ColourTo(styler, i-1, state, bInAsm);
192 state = SCE_C_STRING;
193 } else if (ch == '?' && visibleChars == 0) {
194 ColourTo(styler, i-1, state, bInAsm);
195 state = SCE_C_PREPROCESSOR;
196 } else if (isTACLoperator(ch)) {
197 ColourTo(styler, i-1, state, bInAsm);
198 ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
199 }
200 } else if (state == SCE_C_IDENTIFIER) {
201 if (!isTACLwordchar(ch)) {
202 int lStateChange = classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm);
203
204 if(lStateChange == 1) {
205 styler.SetLineState(currentLine, 1);
206 bInClassDefinition = true;
207 } else if(lStateChange == 2) {
208 bInAsm = true;
209 } else if(lStateChange == -1) {
210 styler.SetLineState(currentLine, 0);
211 bInClassDefinition = false;
212 bInAsm = false;
213 }
214
215 if (lStateChange == 3) {
216 state = SCE_C_COMMENTLINE;
217 }
218 else {
219 state = SCE_C_DEFAULT;
220 chNext = styler.SafeGetCharAt(i + 1);
221 if (ch == '{') {
222 state = SCE_C_COMMENT;
223 } else if (ch == '{' && chNext == '*') {
224 ColourTo(styler, i-1, state, bInAsm);
225 state = SCE_C_COMMENTDOC;
226 } else if (ch == '=' && chNext == '=') {
227 state = SCE_C_COMMENTLINE;
228 } else if (ch == '"') {
229 state = SCE_C_STRING;
230 } else if (isTACLoperator(ch)) {
231 ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
232 }
233 }
234 }
235 } else {
236 if (state == SCE_C_PREPROCESSOR) {
237 if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
238 ColourTo(styler, i-1, state, bInAsm);
239 state = SCE_C_DEFAULT;
240 }
241 } else if (state == SCE_C_COMMENT) {
242 if (ch == '}' || (ch == '\r' || ch == '\n') ) {
243 ColourTo(styler, i, state, bInAsm);
244 state = SCE_C_DEFAULT;
245 }
246 } else if (state == SCE_C_COMMENTDOC) {
247 if (ch == '}' || (ch == '\r' || ch == '\n')) {
248 if (((i > styler.GetStartSegment() + 2) || (
249 (initStyle == SCE_C_COMMENTDOC) &&
250 (styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
251 ColourTo(styler, i, state, bInAsm);
252 state = SCE_C_DEFAULT;
253 }
254 }
255 } else if (state == SCE_C_COMMENTLINE) {
256 if (ch == '\r' || ch == '\n') {
257 ColourTo(styler, i-1, state, bInAsm);
258 state = SCE_C_DEFAULT;
259 }
260 } else if (state == SCE_C_STRING) {
261 if (ch == '"' || ch == '\r' || ch == '\n') {
262 ColourTo(styler, i, state, bInAsm);
263 state = SCE_C_DEFAULT;
264 }
265 }
266 }
267 if (!isspacechar(ch))
268 visibleChars++;
269 chPrev = ch;
270 }
271
272 // Process to end of document
273 if (state == SCE_C_IDENTIFIER) {
274 classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm);
275 }
276 else
277 ColourTo(styler, lengthDoc - 1, state, bInAsm);
278}
279
280static void FoldTACLDoc(unsigned int startPos, int length, int initStyle, WordList *[],
281 Accessor &styler) {
282 bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
283 bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
284 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
285 unsigned int endPos = startPos + length;
286 int visibleChars = 0;
287 int lineCurrent = styler.GetLine(startPos);
288 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
289 int levelCurrent = levelPrev;
290 char chNext = styler[startPos];
291 int styleNext = styler.StyleAt(startPos);
292 int style = initStyle;
293 bool section = false;
294
295 int lastStart = 0;
296
297 for (unsigned int i = startPos; i < endPos; i++) {
298 char ch = chNext;
299 chNext = styler.SafeGetCharAt(i + 1);
300 int stylePrev = style;
301 style = styleNext;
302 styleNext = styler.StyleAt(i + 1);
303 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
304
305 if (stylePrev == SCE_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_PREPROCESSOR))
306 {
307 // Store last word start point.
308 lastStart = i;
309 }
310
311 if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_PREPROCESSOR) {
312 if(isTACLwordchar(ch) && !isTACLwordchar(chNext)) {
313 char s[100];
314 getRange(lastStart, i, styler, s, sizeof(s));
315 if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0)
316 {
317 section = true;
318 levelCurrent = 1;
319 levelPrev = 0;
320 }
321 else if (stylePrev == SCE_C_WORD)
322 levelCurrent += classifyFoldPointTACL(s);
323 }
324 }
325
326 if (style == SCE_C_OPERATOR) {
327 if (ch == '[') {
328 levelCurrent++;
329 } else if (ch == ']') {
330 levelCurrent--;
331 }
332 }
333 if (foldComment && (style == SCE_C_COMMENTLINE)) {
334 if ((ch == '/') && (chNext == '/')) {
335 char chNext2 = styler.SafeGetCharAt(i + 2);
336 if (chNext2 == '{') {
337 levelCurrent++;
338 } else if (chNext2 == '}') {
339 levelCurrent--;
340 }
341 }
342 }
343
344 if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
345 if (ch == '{' && chNext == '$') {
346 unsigned int j=i+2; // skip {$
347 while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
348 j++;
349 }
350 if (styler.Match(j, "region") || styler.Match(j, "if")) {
351 levelCurrent++;
352 } else if (styler.Match(j, "end")) {
353 levelCurrent--;
354 }
355 }
356 }
357
358 if (foldComment && IsStreamCommentStyle(style)) {
359 if (!IsStreamCommentStyle(stylePrev)) {
360 levelCurrent++;
361 } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
362 // Comments don't end at end of line and the next character may be unstyled.
363 levelCurrent--;
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
390static const char * const TACLWordListDesc[] = {
391 "Builtins",
392 "Labels",
393 "Commands",
394 0
395};
396
397LexerModule lmTACL(SCLEX_TACL, ColouriseTACLDoc, "TACL", FoldTACLDoc, TACLWordListDesc);