~brian-sidebotham/wxwidgets-cmake/wxpython-2.9.4

« back to all changes in this revision

Viewing changes to src/stc/scintilla/src/LexMagik.cxx

  • Committer: Brian Sidebotham
  • Date: 2013-08-03 14:30:08 UTC
  • Revision ID: brian.sidebotham@gmail.com-20130803143008-c7806tkych1tp6fc
Initial import into Bazaar

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Scintilla source code edit control
 
2
/**
 
3
 * @file LexMagik.cxx
 
4
 * Lexer for GE(r) Smallworld(tm) MagikSF
 
5
 */
 
6
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 
7
// The License.txt file describes the conditions under which this software may be distributed.
 
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 "StyleContext.h"
 
20
#include "KeyWords.h"
 
21
#include "Scintilla.h"
 
22
#include "SciLexer.h"
 
23
 
 
24
#ifdef SCI_NAMESPACE
 
25
using namespace Scintilla;
 
26
#endif
 
27
 
 
28
/**
 
29
 * Is it a core character (C isalpha(), exclamation and question mark)
 
30
 *
 
31
 * \param  ch The character
 
32
 * \return True if ch is a character, False otherwise
 
33
 */
 
34
static inline bool IsAlphaCore(int ch) {
 
35
    return (isalpha(ch) || ch == '!' || ch == '?');
 
36
}
 
37
 
 
38
/**
 
39
 * Is it a character (IsAlphaCore() and underscore)
 
40
 *
 
41
 * \param  ch The character
 
42
 * \return True if ch is a character, False otherwise
 
43
 */
 
44
static inline bool IsAlpha(int ch) {
 
45
    return (IsAlphaCore(ch) || ch == '_');
 
46
}
 
47
 
 
48
/**
 
49
 * Is it a symbolic character (IsAlpha() and colon)
 
50
 *
 
51
 * \param  ch The character
 
52
 * \return True if ch is a character, False otherwise
 
53
 */
 
54
static inline bool IsAlphaSym(int ch) {
 
55
    return (IsAlpha(ch) || ch == ':');
 
56
}
 
57
 
 
58
/**
 
59
 * Is it a numerical character (IsAlpha() and 0 - 9)
 
60
 *
 
61
 * \param  ch The character
 
62
 * \return True if ch is a character, False otherwise
 
63
 */
 
64
static inline bool IsAlNum(int ch) {
 
65
    return ((ch >= '0' && ch <= '9') || IsAlpha(ch));
 
66
}
 
67
 
 
68
/**
 
69
 * Is it a symbolic numerical character (IsAlNum() and colon)
 
70
 *
 
71
 * \param  ch The character
 
72
 * \return True if ch is a character, False otherwise
 
73
 */
 
74
static inline bool IsAlNumSym(int ch) {
 
75
    return (IsAlNum(ch) || ch == ':');
 
76
}
 
77
 
 
78
/**
 
79
 * The lexer function
 
80
 *
 
81
 * \param  startPos Where to start scanning
 
82
 * \param  length Where to scan to
 
83
 * \param  initStyle The style at the initial point, not used in this folder
 
84
 * \param  keywordslists The keywordslists, currently, number 5 is used
 
85
 * \param  styler The styler
 
86
 */
 
87
static void ColouriseMagikDoc(unsigned int startPos, int length, int initStyle,
 
88
                           WordList *keywordlists[], Accessor &styler) {
 
89
    styler.StartAt(startPos);
 
90
 
 
91
    WordList &keywords = *keywordlists[0];
 
92
    WordList &pragmatics = *keywordlists[1];
 
93
    WordList &containers = *keywordlists[2];
 
94
    WordList &flow = *keywordlists[3];
 
95
    WordList &characters = *keywordlists[4];
 
96
 
 
97
        StyleContext sc(startPos, length, initStyle, styler);
 
98
 
 
99
 
 
100
        for (; sc.More(); sc.Forward()) {
 
101
 
 
102
    repeat:
 
103
 
 
104
        if(sc.ch == '#') {
 
105
            if (sc.chNext == '#') sc.SetState(SCE_MAGIK_HYPER_COMMENT);
 
106
            else sc.SetState(SCE_MAGIK_COMMENT);
 
107
            for(; sc.More() && !(sc.atLineEnd); sc.Forward());
 
108
            sc.SetState(SCE_MAGIK_DEFAULT);
 
109
            goto repeat;
 
110
        }
 
111
 
 
112
        if(sc.ch == '"') {
 
113
            sc.SetState(SCE_MAGIK_STRING);
 
114
 
 
115
            if(sc.More())
 
116
            {
 
117
                sc.Forward();
 
118
                for(; sc.More() && sc.ch != '"'; sc.Forward());
 
119
            }
 
120
 
 
121
            sc.ForwardSetState(SCE_MAGIK_DEFAULT);
 
122
            goto repeat;
 
123
        }
 
124
 
 
125
            // The default state
 
126
            if(sc.state == SCE_MAGIK_DEFAULT) {
 
127
 
 
128
                // A certain keyword has been detected
 
129
                if (sc.ch == '_' && (
 
130
                    sc.currentPos == 0 || !IsAlNum(sc.chPrev))) {
 
131
                    char keyword[50];
 
132
                    memset(keyword, '\0', 50);
 
133
 
 
134
                    for(
 
135
                    int scanPosition = 0;
 
136
                    scanPosition < 50;
 
137
                    scanPosition++) {
 
138
                        char keywordChar = static_cast<char>(
 
139
                        tolower(styler.SafeGetCharAt(
 
140
                            scanPosition +
 
141
                                static_cast<int>(sc.currentPos+1), ' ')));
 
142
                    if(IsAlpha(keywordChar)) {
 
143
                        keyword[scanPosition] = keywordChar;
 
144
                    } else {
 
145
                        break;
 
146
                    }
 
147
                    }
 
148
 
 
149
                // It is a pragma
 
150
                    if(pragmatics.InList(keyword)) {
 
151
                        sc.SetState(SCE_MAGIK_PRAGMA);
 
152
                    }
 
153
 
 
154
                    // it is a normal keyword like _local, _self, etc.
 
155
                    else if(keywords.InList(keyword)) {
 
156
                        sc.SetState(SCE_MAGIK_KEYWORD);
 
157
                    }
 
158
 
 
159
                // It is a container keyword, such as _method, _proc, etc.
 
160
                    else if(containers.InList(keyword)) {
 
161
                        sc.SetState(SCE_MAGIK_CONTAINER);
 
162
                    }
 
163
 
 
164
                    // It is a flow keyword, such as _for, _if, _try, etc.
 
165
                    else if(flow.InList(keyword)) {
 
166
                        sc.SetState(SCE_MAGIK_FLOW);
 
167
                    }
 
168
 
 
169
                    // Interpret as unknown keyword
 
170
                    else {
 
171
                        sc.SetState(SCE_MAGIK_UNKNOWN_KEYWORD);
 
172
                    }
 
173
                }
 
174
 
 
175
            // Symbolic expression
 
176
                else if(sc.ch == ':' && !IsAlNum(sc.chPrev)) {
 
177
                    sc.SetState(SCE_MAGIK_SYMBOL);
 
178
                    bool firstTrip = true;
 
179
                    for(sc.Forward(); sc.More(); sc.Forward()) {
 
180
                        if(firstTrip && IsAlphaSym(sc.ch));
 
181
                        else if(!firstTrip && IsAlNumSym(sc.ch));
 
182
                        else if(sc.ch == '|') {
 
183
                            for(sc.Forward();
 
184
                            sc.More() && sc.ch != '|';
 
185
                            sc.Forward());
 
186
                        }
 
187
                        else break;
 
188
 
 
189
                        firstTrip = false;
 
190
                    }
 
191
                    sc.SetState(SCE_MAGIK_DEFAULT);
 
192
                    goto repeat;
 
193
                }
 
194
 
 
195
            // Identifier (label) expression
 
196
                else if(sc.ch == '@') {
 
197
                    sc.SetState(SCE_MAGIK_IDENTIFIER);
 
198
                    bool firstTrip = true;
 
199
                    for(sc.Forward(); sc.More(); sc.Forward()) {
 
200
                        if(firstTrip && IsAlphaCore(sc.ch)) {
 
201
                            firstTrip = false;
 
202
                        }
 
203
                        else if(!firstTrip && IsAlpha(sc.ch));
 
204
                        else break;
 
205
                    }
 
206
                    sc.SetState(SCE_MAGIK_DEFAULT);
 
207
                    goto repeat;
 
208
                }
 
209
 
 
210
                // Start of a character
 
211
            else if(sc.ch == '%') {
 
212
                sc.SetState(SCE_MAGIK_CHARACTER);
 
213
                sc.Forward();
 
214
                char keyword[50];
 
215
                    memset(keyword, '\0', 50);
 
216
 
 
217
                    for(
 
218
                    int scanPosition = 0;
 
219
                    scanPosition < 50;
 
220
                    scanPosition++) {
 
221
                        char keywordChar = static_cast<char>(
 
222
                        tolower(styler.SafeGetCharAt(
 
223
                            scanPosition +
 
224
                                static_cast<int>(sc.currentPos), ' ')));
 
225
                    if(IsAlpha(keywordChar)) {
 
226
                        keyword[scanPosition] = keywordChar;
 
227
                    } else {
 
228
                        break;
 
229
                    }
 
230
                    }
 
231
 
 
232
                    if(characters.InList(keyword)) {
 
233
                        sc.Forward(strlen(keyword));
 
234
                    } else {
 
235
                        sc.Forward();
 
236
                    }
 
237
 
 
238
                sc.SetState(SCE_MAGIK_DEFAULT);
 
239
                goto repeat;
 
240
            }
 
241
 
 
242
            // Operators
 
243
                else if(
 
244
                sc.ch == '>' ||
 
245
                sc.ch == '<' ||
 
246
                sc.ch == '.' ||
 
247
                sc.ch == ',' ||
 
248
                sc.ch == '+' ||
 
249
                sc.ch == '-' ||
 
250
                sc.ch == '/' ||
 
251
                sc.ch == '*' ||
 
252
                sc.ch == '~' ||
 
253
                sc.ch == '$' ||
 
254
                sc.ch == '=') {
 
255
                sc.SetState(SCE_MAGIK_OPERATOR);
 
256
            }
 
257
 
 
258
            // Braces
 
259
            else if(sc.ch == '(' || sc.ch == ')') {
 
260
                sc.SetState(SCE_MAGIK_BRACE_BLOCK);
 
261
            }
 
262
 
 
263
            // Brackets
 
264
            else if(sc.ch == '{' || sc.ch == '}') {
 
265
                sc.SetState(SCE_MAGIK_BRACKET_BLOCK);
 
266
            }
 
267
 
 
268
            // Square Brackets
 
269
            else if(sc.ch == '[' || sc.ch == ']') {
 
270
                sc.SetState(SCE_MAGIK_SQBRACKET_BLOCK);
 
271
            }
 
272
 
 
273
 
 
274
            }
 
275
 
 
276
            // It is an operator
 
277
            else if(
 
278
            sc.state == SCE_MAGIK_OPERATOR ||
 
279
            sc.state == SCE_MAGIK_BRACE_BLOCK ||
 
280
            sc.state == SCE_MAGIK_BRACKET_BLOCK ||
 
281
            sc.state == SCE_MAGIK_SQBRACKET_BLOCK) {
 
282
                sc.SetState(SCE_MAGIK_DEFAULT);
 
283
                goto repeat;
 
284
            }
 
285
 
 
286
            // It is the pragma state
 
287
            else if(sc.state == SCE_MAGIK_PRAGMA) {
 
288
                if(!IsAlpha(sc.ch)) {
 
289
                    sc.SetState(SCE_MAGIK_DEFAULT);
 
290
                goto repeat;
 
291
                }
 
292
            }
 
293
 
 
294
            // It is the keyword state
 
295
            else if(
 
296
            sc.state == SCE_MAGIK_KEYWORD ||
 
297
            sc.state == SCE_MAGIK_CONTAINER ||
 
298
            sc.state == SCE_MAGIK_FLOW ||
 
299
            sc.state == SCE_MAGIK_UNKNOWN_KEYWORD) {
 
300
                if(!IsAlpha(sc.ch)) {
 
301
                    sc.SetState(SCE_MAGIK_DEFAULT);
 
302
                    goto repeat;
 
303
                }
 
304
            }
 
305
        }
 
306
 
 
307
        sc.Complete();
 
308
}
 
309
 
 
310
/**
 
311
 * The word list description
 
312
 */
 
313
static const char * const magikWordListDesc[] = {
 
314
    "Accessors (local, global, self, super, thisthread)",
 
315
    "Pragmatic (pragma, private)",
 
316
    "Containers (method, block, proc)",
 
317
    "Flow (if, then, elif, else)",
 
318
    "Characters (space, tab, newline, return)",
 
319
    "Fold Containers (method, proc, block, if, loop)",
 
320
    0};
 
321
 
 
322
/**
 
323
 * This function detects keywords which are able to have a body. Note that it
 
324
 * uses the Fold Containers word description, not the containers description. It
 
325
 * only works when the style at that particular position is set on Containers
 
326
 * or Flow (number 3 or 4).
 
327
 *
 
328
 * \param  keywordslist The list of keywords that are scanned, they should only
 
329
 *         contain the start keywords, not the end keywords
 
330
 * \param  The actual keyword
 
331
 * \return 1 if it is a folding start-keyword, -1 if it is a folding end-keyword
 
332
 *         0 otherwise
 
333
 */
 
334
static inline int IsFoldingContainer(WordList &keywordslist, char * keyword) {
 
335
    if(
 
336
        strlen(keyword) > 3 &&
 
337
        keyword[0] == 'e' && keyword[1] == 'n' && keyword[2] == 'd') {
 
338
        if (keywordslist.InList(keyword + 3)) {
 
339
            return -1;
 
340
        }
 
341
 
 
342
    } else {
 
343
        if(keywordslist.InList(keyword)) {
 
344
            return 1;
 
345
        }
 
346
    }
 
347
 
 
348
    return 0;
 
349
}
 
350
 
 
351
/**
 
352
 * The folding function
 
353
 *
 
354
 * \param  startPos Where to start scanning
 
355
 * \param  length Where to scan to
 
356
 * \param  keywordslists The keywordslists, currently, number 5 is used
 
357
 * \param  styler The styler
 
358
 */
 
359
static void FoldMagikDoc(unsigned int startPos, int length, int,
 
360
    WordList *keywordslists[], Accessor &styler) {
 
361
 
 
362
    bool compact = styler.GetPropertyInt("fold.compact") != 0;
 
363
 
 
364
    WordList &foldingElements = *keywordslists[5];
 
365
    int endPos = startPos + length;
 
366
    int line = styler.GetLine(startPos);
 
367
    int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK;
 
368
    int flags = styler.LevelAt(line) & ~SC_FOLDLEVELNUMBERMASK;
 
369
 
 
370
    for(
 
371
        int currentPos = startPos;
 
372
        currentPos < endPos;
 
373
        currentPos++) {
 
374
            char currentState = styler.StyleAt(currentPos);
 
375
            char c = styler.SafeGetCharAt(currentPos, ' ');
 
376
            int prevLine = styler.GetLine(currentPos - 1);
 
377
            line = styler.GetLine(currentPos);
 
378
 
 
379
            // Default situation
 
380
            if(prevLine < line) {
 
381
                styler.SetLevel(line, (level|flags) & ~SC_FOLDLEVELHEADERFLAG);
 
382
                flags = styler.LevelAt(line) & ~SC_FOLDLEVELNUMBERMASK;
 
383
            }
 
384
 
 
385
            if(
 
386
                (
 
387
                    currentState == SCE_MAGIK_CONTAINER ||
 
388
                    currentState == SCE_MAGIK_FLOW
 
389
                ) &&
 
390
                c == '_') {
 
391
 
 
392
                char keyword[50];
 
393
                memset(keyword, '\0', 50);
 
394
 
 
395
                for(
 
396
                    int scanPosition = 0;
 
397
                    scanPosition < 50;
 
398
                    scanPosition++) {
 
399
                    char keywordChar = static_cast<char>(
 
400
                        tolower(styler.SafeGetCharAt(
 
401
                            scanPosition +
 
402
                                currentPos + 1, ' ')));
 
403
                    if(IsAlpha(keywordChar)) {
 
404
                        keyword[scanPosition] = keywordChar;
 
405
                    } else {
 
406
                        break;
 
407
                    }
 
408
                }
 
409
 
 
410
                if(IsFoldingContainer(foldingElements, keyword) > 0) {
 
411
                    styler.SetLevel(
 
412
                        line,
 
413
                        styler.LevelAt(line) | SC_FOLDLEVELHEADERFLAG);
 
414
                    level++;
 
415
                } else if(IsFoldingContainer(foldingElements, keyword) < 0) {
 
416
                    styler.SetLevel(line, styler.LevelAt(line));
 
417
                    level--;
 
418
                }
 
419
            }
 
420
 
 
421
            if(
 
422
                compact && (
 
423
                    currentState == SCE_MAGIK_BRACE_BLOCK ||
 
424
                    currentState == SCE_MAGIK_BRACKET_BLOCK ||
 
425
                    currentState == SCE_MAGIK_SQBRACKET_BLOCK)) {
 
426
                if(c == '{' || c == '[' || c == '(') {
 
427
                    styler.SetLevel(
 
428
                        line,
 
429
                        styler.LevelAt(line) | SC_FOLDLEVELHEADERFLAG);
 
430
                    level++;
 
431
                } else if(c == '}' || c == ']' || c == ')') {
 
432
                    styler.SetLevel(line, styler.LevelAt(line));
 
433
                    level--;
 
434
                }
 
435
            }
 
436
        }
 
437
 
 
438
}
 
439
 
 
440
/**
 
441
 * Injecting the module
 
442
 */
 
443
LexerModule lmMagikSF(
 
444
    SCLEX_MAGIK, ColouriseMagikDoc, "magiksf", FoldMagikDoc, magikWordListDesc);
 
445