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