]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexOpal.cxx
Allow unsetting wxMenuItem as start of radio group too.
[wxWidgets.git] / src / stc / scintilla / lexers / LexOpal.cxx
1 // Scintilla source code edit control
2 /** @file LexOpal.cxx
3 ** Lexer for OPAL (functional language similar to Haskell)
4 ** Written by Sebastian Pipping <webmaster@hartwork.org>
5 **/
6
7 #include <stdlib.h>
8 #include <string.h>
9 #include <stdio.h>
10 #include <stdarg.h>
11 #include <assert.h>
12 #include <ctype.h>
13
14 #include "ILexer.h"
15 #include "Scintilla.h"
16 #include "SciLexer.h"
17
18 #include "WordList.h"
19 #include "LexAccessor.h"
20 #include "Accessor.h"
21 #include "StyleContext.h"
22 #include "CharacterSet.h"
23 #include "LexerModule.h"
24
25 #ifdef SCI_NAMESPACE
26 using namespace Scintilla;
27 #endif
28
29 inline static void getRange( unsigned int start, unsigned int end, Accessor & styler, char * s, unsigned int len )
30 {
31 unsigned int i = 0;
32 while( ( i < end - start + 1 ) && ( i < len - 1 ) )
33 {
34 s[i] = static_cast<char>( styler[ start + i ] );
35 i++;
36 }
37 s[ i ] = '\0';
38 }
39
40 inline bool HandleString( unsigned int & cur, unsigned int one_too_much, Accessor & styler )
41 {
42 char ch;
43
44 // Wait for string to close
45 bool even_backslash_count = true; // Without gaps in between
46 cur++; // Skip initial quote
47 for( ; ; )
48 {
49 if( cur >= one_too_much )
50 {
51 styler.ColourTo( cur - 1, SCE_OPAL_STRING );
52 return false; // STOP
53 }
54
55 ch = styler.SafeGetCharAt( cur );
56 if( ( ch == '\015' ) || ( ch == '\012' ) ) // Deny multi-line strings
57 {
58 styler.ColourTo( cur - 1, SCE_OPAL_STRING );
59 styler.StartSegment( cur );
60 return true;
61 }
62 else
63 {
64 if( even_backslash_count )
65 {
66 if( ch == '"' )
67 {
68 styler.ColourTo( cur, SCE_OPAL_STRING );
69 cur++;
70 if( cur >= one_too_much )
71 {
72 return false; // STOP
73 }
74 else
75 {
76 styler.StartSegment( cur );
77 return true;
78 }
79 }
80 else if( ch == '\\' )
81 {
82 even_backslash_count = false;
83 }
84 }
85 else
86 {
87 even_backslash_count = true;
88 }
89 }
90
91 cur++;
92 }
93 }
94
95 inline bool HandleCommentBlock( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail )
96 {
97 char ch;
98
99 if( could_fail )
100 {
101 cur++;
102 if( cur >= one_too_much )
103 {
104 styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
105 return false; // STOP
106 }
107
108 ch = styler.SafeGetCharAt( cur );
109 if( ch != '*' )
110 {
111 styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
112 styler.StartSegment( cur );
113 return true;
114 }
115 }
116
117 // Wait for comment close
118 cur++;
119 bool star_found = false;
120 for( ; ; )
121 {
122 if( cur >= one_too_much )
123 {
124 styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_BLOCK );
125 return false; // STOP
126 }
127
128 ch = styler.SafeGetCharAt( cur );
129 if( star_found )
130 {
131 if( ch == '/' )
132 {
133 styler.ColourTo( cur, SCE_OPAL_COMMENT_BLOCK );
134 cur++;
135 if( cur >= one_too_much )
136 {
137 return false; // STOP
138 }
139 else
140 {
141 styler.StartSegment( cur );
142 return true;
143 }
144 }
145 else if( ch != '*' )
146 {
147 star_found = false;
148 }
149 }
150 else if( ch == '*' )
151 {
152 star_found = true;
153 }
154 cur++;
155 }
156 }
157
158 inline bool HandleCommentLine( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail )
159 {
160 char ch;
161
162 if( could_fail )
163 {
164 cur++;
165 if( cur >= one_too_much )
166 {
167 styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
168 return false; // STOP
169 }
170
171 ch = styler.SafeGetCharAt( cur );
172 if( ch != '-' )
173 {
174 styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
175 styler.StartSegment( cur );
176 return true;
177 }
178
179 cur++;
180 if( cur >= one_too_much )
181 {
182 styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
183 return false; // STOP
184 }
185
186 ch = styler.SafeGetCharAt( cur );
187 if( ( ch != ' ' ) && ( ch != '\t' ) )
188 {
189 styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
190 styler.StartSegment( cur );
191 return true;
192 }
193 }
194
195 // Wait for end of line
196 bool fifteen_found = false;
197
198 for( ; ; )
199 {
200 cur++;
201
202 if( cur >= one_too_much )
203 {
204 styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE );
205 return false; // STOP
206 }
207
208 ch = styler.SafeGetCharAt( cur );
209 if( fifteen_found )
210 {
211 /*
212 if( ch == '\012' )
213 {
214 // One newline on Windows (015, 012)
215 }
216 else
217 {
218 // One newline on MAC (015) and another char
219 }
220 */
221 cur--;
222 styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE );
223 styler.StartSegment( cur );
224 return true;
225 }
226 else
227 {
228 if( ch == '\015' )
229 {
230 fifteen_found = true;
231 }
232 else if( ch == '\012' )
233 {
234 // One newline on Linux (012)
235 styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE );
236 styler.StartSegment( cur );
237 return true;
238 }
239 }
240 }
241 }
242
243 inline bool HandlePar( unsigned int & cur, Accessor & styler )
244 {
245 styler.ColourTo( cur, SCE_OPAL_PAR );
246
247 cur++;
248
249 styler.StartSegment( cur );
250 return true;
251 }
252
253 inline bool HandleSpace( unsigned int & cur, unsigned int one_too_much, Accessor & styler )
254 {
255 char ch;
256
257 cur++;
258 for( ; ; )
259 {
260 if( cur >= one_too_much )
261 {
262 styler.ColourTo( cur - 1, SCE_OPAL_SPACE );
263 return false;
264 }
265
266 ch = styler.SafeGetCharAt( cur );
267 switch( ch )
268 {
269 case ' ':
270 case '\t':
271 case '\015':
272 case '\012':
273 cur++;
274 break;
275
276 default:
277 styler.ColourTo( cur - 1, SCE_OPAL_SPACE );
278 styler.StartSegment( cur );
279 return true;
280 }
281 }
282 }
283
284 inline bool HandleInteger( unsigned int & cur, unsigned int one_too_much, Accessor & styler )
285 {
286 char ch;
287
288 for( ; ; )
289 {
290 cur++;
291 if( cur >= one_too_much )
292 {
293 styler.ColourTo( cur - 1, SCE_OPAL_INTEGER );
294 return false; // STOP
295 }
296
297 ch = styler.SafeGetCharAt( cur );
298 if( !( isascii( ch ) && isdigit( ch ) ) )
299 {
300 styler.ColourTo( cur - 1, SCE_OPAL_INTEGER );
301 styler.StartSegment( cur );
302 return true;
303 }
304 }
305 }
306
307 inline bool HandleWord( unsigned int & cur, unsigned int one_too_much, Accessor & styler, WordList * keywordlists[] )
308 {
309 char ch;
310 const unsigned int beg = cur;
311
312 cur++;
313 for( ; ; )
314 {
315 ch = styler.SafeGetCharAt( cur );
316 if( ( ch != '_' ) && ( ch != '-' ) &&
317 !( isascii( ch ) && ( islower( ch ) || isupper( ch ) || isdigit( ch ) ) ) ) break;
318
319 cur++;
320 if( cur >= one_too_much )
321 {
322 break;
323 }
324 }
325
326 const int ide_len = cur - beg + 1;
327 char * ide = new char[ ide_len ];
328 getRange( beg, cur, styler, ide, ide_len );
329
330 WordList & keywords = *keywordlists[ 0 ];
331 WordList & classwords = *keywordlists[ 1 ];
332
333 if( keywords.InList( ide ) ) // Keyword
334 {
335 delete [] ide;
336
337 styler.ColourTo( cur - 1, SCE_OPAL_KEYWORD );
338 if( cur >= one_too_much )
339 {
340 return false; // STOP
341 }
342 else
343 {
344 styler.StartSegment( cur );
345 return true;
346 }
347 }
348 else if( classwords.InList( ide ) ) // Sort
349 {
350 delete [] ide;
351
352 styler.ColourTo( cur - 1, SCE_OPAL_SORT );
353 if( cur >= one_too_much )
354 {
355 return false; // STOP
356 }
357 else
358 {
359 styler.StartSegment( cur );
360 return true;
361 }
362 }
363 else if( !strcmp( ide, "true" ) || !strcmp( ide, "false" ) ) // Bool const
364 {
365 delete [] ide;
366
367 styler.ColourTo( cur - 1, SCE_OPAL_BOOL_CONST );
368 if( cur >= one_too_much )
369 {
370 return false; // STOP
371 }
372 else
373 {
374 styler.StartSegment( cur );
375 return true;
376 }
377 }
378 else // Unknown keyword
379 {
380 delete [] ide;
381
382 styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
383 if( cur >= one_too_much )
384 {
385 return false; // STOP
386 }
387 else
388 {
389 styler.StartSegment( cur );
390 return true;
391 }
392 }
393
394 }
395
396 inline bool HandleSkip( unsigned int & cur, unsigned int one_too_much, Accessor & styler )
397 {
398 cur++;
399 styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
400 if( cur >= one_too_much )
401 {
402 return false; // STOP
403 }
404 else
405 {
406 styler.StartSegment( cur );
407 return true;
408 }
409 }
410
411 static void ColouriseOpalDoc( unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor & styler )
412 {
413 styler.StartAt( startPos );
414 styler.StartSegment( startPos );
415
416 unsigned int & cur = startPos;
417 const unsigned int one_too_much = startPos + length;
418
419 int state = initStyle;
420
421 for( ; ; )
422 {
423 switch( state )
424 {
425 case SCE_OPAL_KEYWORD:
426 case SCE_OPAL_SORT:
427 if( !HandleWord( cur, one_too_much, styler, keywordlists ) ) return;
428 state = SCE_OPAL_DEFAULT;
429 break;
430
431 case SCE_OPAL_INTEGER:
432 if( !HandleInteger( cur, one_too_much, styler ) ) return;
433 state = SCE_OPAL_DEFAULT;
434 break;
435
436 case SCE_OPAL_COMMENT_BLOCK:
437 if( !HandleCommentBlock( cur, one_too_much, styler, false ) ) return;
438 state = SCE_OPAL_DEFAULT;
439 break;
440
441 case SCE_OPAL_COMMENT_LINE:
442 if( !HandleCommentLine( cur, one_too_much, styler, false ) ) return;
443 state = SCE_OPAL_DEFAULT;
444 break;
445
446 case SCE_OPAL_STRING:
447 if( !HandleString( cur, one_too_much, styler ) ) return;
448 state = SCE_OPAL_DEFAULT;
449 break;
450
451 default: // SCE_OPAL_DEFAULT:
452 {
453 char ch = styler.SafeGetCharAt( cur );
454
455 switch( ch )
456 {
457 // String
458 case '"':
459 if( !HandleString( cur, one_too_much, styler ) ) return;
460 break;
461
462 // Comment block
463 case '/':
464 if( !HandleCommentBlock( cur, one_too_much, styler, true ) ) return;
465 break;
466
467 // Comment line
468 case '-':
469 if( !HandleCommentLine( cur, one_too_much, styler, true ) ) return;
470 break;
471
472 // Par
473 case '(':
474 case ')':
475 case '[':
476 case ']':
477 case '{':
478 case '}':
479 if( !HandlePar( cur, styler ) ) return;
480 break;
481
482 // Whitespace
483 case ' ':
484 case '\t':
485 case '\015':
486 case '\012':
487 if( !HandleSpace( cur, one_too_much, styler ) ) return;
488 break;
489
490 default:
491 {
492 // Integer
493 if( isascii( ch ) && isdigit( ch ) )
494 {
495 if( !HandleInteger( cur, one_too_much, styler ) ) return;
496 }
497
498 // Keyword
499 else if( isascii( ch ) && ( islower( ch ) || isupper( ch ) ) )
500 {
501 if( !HandleWord( cur, one_too_much, styler, keywordlists ) ) return;
502
503 }
504
505 // Skip
506 else
507 {
508 if( !HandleSkip( cur, one_too_much, styler ) ) return;
509 }
510 }
511 }
512
513 break;
514 }
515 }
516 }
517 }
518
519 static const char * const opalWordListDesc[] = {
520 "Keywords",
521 "Sorts",
522 0
523 };
524
525 LexerModule lmOpal(SCLEX_OPAL, ColouriseOpalDoc, "opal", NULL, opalWordListDesc);