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