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