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