~damien-moore/+junk/codeblocks

« back to all changes in this revision

Viewing changes to src/plugins/contrib/wxSmithSTC/stc/scintilla/src/LexBasic.cxx

  • Committer: Damien Moore
  • Date: 2013-10-11 14:25:27 UTC
  • Revision ID: damienlmoore@gmail.com-20131011142527-w13ki0x8yjd7973d
copy of Code::Blocks repo based on SVN rev 9395

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Scintilla source code edit control
 
2
/** @file LexBasic.cxx
 
3
 ** Lexer for BlitzBasic and PureBasic.
 
4
 **/
 
5
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
 
6
// The License.txt file describes the conditions under which this software may be distributed.
 
7
 
 
8
// This tries to be a unified Lexer/Folder for all the BlitzBasic/BlitzMax/PurBasic basics
 
9
// and derivatives. Once they diverge enough, might want to split it into multiple
 
10
// lexers for more code clearity.
 
11
//
 
12
// Mail me (elias <at> users <dot> sf <dot> net) for any bugs.
 
13
 
 
14
// Folding only works for simple things like functions or types.
 
15
 
 
16
// You may want to have a look at my ctags lexer as well, if you additionally to coloring
 
17
// and folding need to extract things like label tags in your editor.
 
18
 
 
19
#include <stdlib.h>
 
20
#include <string.h>
 
21
#include <stdio.h>
 
22
#include <ctype.h>
 
23
#include <stdarg.h>
 
24
 
 
25
#include "Platform.h"
 
26
 
 
27
#include "PropSet.h"
 
28
#include "Accessor.h"
 
29
#include "StyleContext.h"
 
30
#include "KeyWords.h"
 
31
#include "Scintilla.h"
 
32
#include "SciLexer.h"
 
33
 
 
34
/* Bits:
 
35
 * 1  - whitespace
 
36
 * 2  - operator
 
37
 * 4  - identifier
 
38
 * 8  - decimal digit
 
39
 * 16 - hex digit
 
40
 * 32 - bin digit
 
41
 */
 
42
static int character_classification[128] =
 
43
{
 
44
    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,
 
45
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 
46
    1,  2,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  10, 2,
 
47
    60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2,  2,  2,  2,  2,  2,
 
48
    2,  20, 20, 20, 20, 20, 20, 4,  4,  4,  4,  4,  4,  4,  4,  4,
 
49
    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,  4,
 
50
    2,  20, 20, 20, 20, 20, 20, 4,  4,  4,  4,  4,  4,  4,  4,  4,
 
51
    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,  0
 
52
};
 
53
 
 
54
static bool IsSpace(int c) {
 
55
        return c < 128 && (character_classification[c] & 1);
 
56
}
 
57
 
 
58
static bool IsOperator(int c) {
 
59
        return c < 128 && (character_classification[c] & 2);
 
60
}
 
61
 
 
62
static bool IsIdentifier(int c) {
 
63
        return c < 128 && (character_classification[c] & 4);
 
64
}
 
65
 
 
66
static bool IsDigit(int c) {
 
67
        return c < 128 && (character_classification[c] & 8);
 
68
}
 
69
 
 
70
static bool IsHexDigit(int c) {
 
71
        return c < 128 && (character_classification[c] & 16);
 
72
}
 
73
 
 
74
static bool IsBinDigit(int c) {
 
75
        return c < 128 && (character_classification[c] & 32);
 
76
}
 
77
 
 
78
static int LowerCase(int c)
 
79
{
 
80
        if (c >= 'A' && c <= 'Z')
 
81
                return 'a' + c - 'A';
 
82
        return c;
 
83
}
 
84
 
 
85
static void ColouriseBasicDoc(unsigned int startPos, int length, int initStyle,
 
86
                           WordList *keywordlists[], Accessor &styler, char comment_char) {
 
87
        bool wasfirst = true, isfirst = true; // true if first token in a line
 
88
        styler.StartAt(startPos);
 
89
 
 
90
        StyleContext sc(startPos, length, initStyle, styler);
 
91
 
 
92
        // Can't use sc.More() here else we miss the last character
 
93
        for (; ; sc.Forward()) {
 
94
                if (sc.state == SCE_B_IDENTIFIER) {
 
95
                        if (!IsIdentifier(sc.ch)) {
 
96
                                // Labels
 
97
                                if (wasfirst && sc.Match(':')) {
 
98
                                        sc.ChangeState(SCE_B_LABEL);
 
99
                                        sc.ForwardSetState(SCE_B_DEFAULT);
 
100
                                } else {
 
101
                                        char s[100];
 
102
                                        int kstates[4] = {
 
103
                                                SCE_B_KEYWORD,
 
104
                                                SCE_B_KEYWORD2,
 
105
                                                SCE_B_KEYWORD3,
 
106
                                                SCE_B_KEYWORD4,
 
107
                                        };
 
108
                                        sc.GetCurrentLowered(s, sizeof(s));
 
109
                                        for (int i = 0; i < 4; i++) {
 
110
                                                if (keywordlists[i]->InList(s)) {
 
111
                                                        sc.ChangeState(kstates[i]);
 
112
                                                }
 
113
                                        }
 
114
                                        // Types, must set them as operator else they will be
 
115
                                        // matched as number/constant
 
116
                                        if (sc.Match('.') || sc.Match('$') || sc.Match('%') ||
 
117
                                                sc.Match('#')) {
 
118
                                                sc.SetState(SCE_B_OPERATOR);
 
119
                                        } else {
 
120
                                                sc.SetState(SCE_B_DEFAULT);
 
121
                                        }
 
122
                                }
 
123
                        }
 
124
                } else if (sc.state == SCE_B_OPERATOR) {
 
125
                        if (!IsOperator(sc.ch) || sc.Match('#'))
 
126
                                sc.SetState(SCE_B_DEFAULT);
 
127
                } else if (sc.state == SCE_B_LABEL) {
 
128
                        if (!IsIdentifier(sc.ch))
 
129
                                sc.SetState(SCE_B_DEFAULT);
 
130
                } else if (sc.state == SCE_B_CONSTANT) {
 
131
                        if (!IsIdentifier(sc.ch))
 
132
                                sc.SetState(SCE_B_DEFAULT);
 
133
                } else if (sc.state == SCE_B_NUMBER) {
 
134
                        if (!IsDigit(sc.ch))
 
135
                                sc.SetState(SCE_B_DEFAULT);
 
136
                } else if (sc.state == SCE_B_HEXNUMBER) {
 
137
                        if (!IsHexDigit(sc.ch))
 
138
                                sc.SetState(SCE_B_DEFAULT);
 
139
                } else if (sc.state == SCE_B_BINNUMBER) {
 
140
                        if (!IsBinDigit(sc.ch))
 
141
                                sc.SetState(SCE_B_DEFAULT);
 
142
                } else if (sc.state == SCE_B_STRING) {
 
143
                        if (sc.ch == '"') {
 
144
                                sc.ForwardSetState(SCE_B_DEFAULT);
 
145
                        }
 
146
                        if (sc.atLineEnd) {
 
147
                                sc.ChangeState(SCE_B_ERROR);
 
148
                                sc.SetState(SCE_B_DEFAULT);
 
149
                        }
 
150
                } else if (sc.state == SCE_B_COMMENT || sc.state == SCE_B_PREPROCESSOR) {
 
151
                        if (sc.atLineEnd) {
 
152
                                sc.SetState(SCE_B_DEFAULT);
 
153
                        }
 
154
                }
 
155
 
 
156
                if (sc.atLineStart)
 
157
                        isfirst = true;
 
158
 
 
159
                if (sc.state == SCE_B_DEFAULT || sc.state == SCE_B_ERROR) {
 
160
                        if (isfirst && sc.Match('.')) {
 
161
                                sc.SetState(SCE_B_LABEL);
 
162
                        } else if (isfirst && sc.Match('#')) {
 
163
                                wasfirst = isfirst;
 
164
                                sc.SetState(SCE_B_IDENTIFIER);
 
165
                        } else if (sc.Match(comment_char)) {
 
166
                                // Hack to make deprecated QBASIC '$Include show
 
167
                                // up in freebasic with SCE_B_PREPROCESSOR.
 
168
                                if (comment_char == '\'' && sc.Match(comment_char, '$'))
 
169
                                        sc.SetState(SCE_B_PREPROCESSOR);
 
170
                                else
 
171
                                        sc.SetState(SCE_B_COMMENT);
 
172
                        } else if (sc.Match('"')) {
 
173
                                sc.SetState(SCE_B_STRING);
 
174
                        } else if (IsDigit(sc.ch)) {
 
175
                                sc.SetState(SCE_B_NUMBER);
 
176
                        } else if (sc.Match('$')) {
 
177
                                sc.SetState(SCE_B_HEXNUMBER);
 
178
                        } else if (sc.Match('%')) {
 
179
                                sc.SetState(SCE_B_BINNUMBER);
 
180
                        } else if (sc.Match('#')) {
 
181
                                sc.SetState(SCE_B_CONSTANT);
 
182
                        } else if (IsOperator(sc.ch)) {
 
183
                                sc.SetState(SCE_B_OPERATOR);
 
184
                        } else if (IsIdentifier(sc.ch)) {
 
185
                                wasfirst = isfirst;
 
186
                                sc.SetState(SCE_B_IDENTIFIER);
 
187
                        } else if (!IsSpace(sc.ch)) {
 
188
                                sc.SetState(SCE_B_ERROR);
 
189
                        }
 
190
                }
 
191
 
 
192
                if (!IsSpace(sc.ch))
 
193
                        isfirst = false;
 
194
 
 
195
                if (!sc.More())
 
196
                        break;
 
197
        }
 
198
        sc.Complete();
 
199
}
 
200
 
 
201
static int CheckBlitzFoldPoint(char const *token, int &level) {
 
202
        if (!strcmp(token, "function") ||
 
203
                !strcmp(token, "type")) {
 
204
                level |= SC_FOLDLEVELHEADERFLAG;
 
205
                return 1;
 
206
        }
 
207
        if (!strcmp(token, "end function") ||
 
208
                !strcmp(token, "end type")) {
 
209
                return -1;
 
210
        }
 
211
        return 0;
 
212
}
 
213
 
 
214
static int CheckPureFoldPoint(char const *token, int &level) {
 
215
        if (!strcmp(token, "procedure") ||
 
216
                !strcmp(token, "enumeration") ||
 
217
                !strcmp(token, "interface") ||
 
218
                !strcmp(token, "structure")) {
 
219
                level |= SC_FOLDLEVELHEADERFLAG;
 
220
                return 1;
 
221
        }
 
222
        if (!strcmp(token, "endprocedure") ||
 
223
                !strcmp(token, "endenumeration") ||
 
224
                !strcmp(token, "endinterface") ||
 
225
                !strcmp(token, "endstructure")) {
 
226
                return -1;
 
227
        }
 
228
        return 0;
 
229
}
 
230
 
 
231
static int CheckFreeFoldPoint(char const *token, int &level) {
 
232
        if (!strcmp(token, "function") ||
 
233
                !strcmp(token, "sub") ||
 
234
                !strcmp(token, "type")) {
 
235
                level |= SC_FOLDLEVELHEADERFLAG;
 
236
                return 1;
 
237
        }
 
238
        if (!strcmp(token, "end function") ||
 
239
                !strcmp(token, "end sub") ||
 
240
                !strcmp(token, "end type")) {
 
241
                return -1;
 
242
        }
 
243
        return 0;
 
244
}
 
245
 
 
246
static void FoldBasicDoc(unsigned int startPos, int length,
 
247
        Accessor &styler, int (*CheckFoldPoint)(char const *, int &)) {
 
248
        int line = styler.GetLine(startPos);
 
249
        int level = styler.LevelAt(line);
 
250
        int go = 0, done = 0;
 
251
        int endPos = startPos + length;
 
252
        char word[256];
 
253
        int wordlen = 0;
 
254
        int i;
 
255
        bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
 
256
        // Scan for tokens at the start of the line (they may include
 
257
        // whitespace, for tokens like "End Function"
 
258
        for (i = startPos; i < endPos; i++) {
 
259
                int c = styler.SafeGetCharAt(i);
 
260
                if (!done && !go) {
 
261
                        if (wordlen) { // are we scanning a token already?
 
262
                                word[wordlen] = static_cast<char>(LowerCase(c));
 
263
                                if (!IsIdentifier(c)) { // done with token
 
264
                                        word[wordlen] = '\0';
 
265
                                        go = CheckFoldPoint(word, level);
 
266
                                        if (!go) {
 
267
                                                // Treat any whitespace as single blank, for
 
268
                                                // things like "End   Function".
 
269
                                                if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) {
 
270
                                                        word[wordlen] = ' ';
 
271
                                                        if (wordlen < 255)
 
272
                                                                wordlen++;
 
273
                                                }
 
274
                                                else // done with this line
 
275
                                                        done = 1;
 
276
                                        }
 
277
                                } else if (wordlen < 255) {
 
278
                                        wordlen++;
 
279
                                }
 
280
                        } else { // start scanning at first non-whitespace character
 
281
                                if (!IsSpace(c)) {
 
282
                                        if (IsIdentifier(c)) {
 
283
                                                word[0] = static_cast<char>(LowerCase(c));
 
284
                                                wordlen = 1;
 
285
                                        } else // done with this line
 
286
                                                done = 1;
 
287
                                }
 
288
                        }
 
289
                }
 
290
                if (c == '\n') { // line end
 
291
                        if (!done && wordlen == 0 && foldCompact) // line was only space
 
292
                                level |= SC_FOLDLEVELWHITEFLAG;
 
293
                        if (level != styler.LevelAt(line))
 
294
                                styler.SetLevel(line, level);
 
295
                        level += go;
 
296
                        line++;
 
297
                        // reset state
 
298
                        wordlen = 0;
 
299
                        level &= ~SC_FOLDLEVELHEADERFLAG;
 
300
                        level &= ~SC_FOLDLEVELWHITEFLAG;
 
301
                        go = 0;
 
302
                        done = 0;
 
303
                }
 
304
        }
 
305
}
 
306
 
 
307
static void ColouriseBlitzBasicDoc(unsigned int startPos, int length, int initStyle,
 
308
                           WordList *keywordlists[], Accessor &styler) {
 
309
        ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, ';');
 
310
}
 
311
 
 
312
static void ColourisePureBasicDoc(unsigned int startPos, int length, int initStyle,
 
313
                           WordList *keywordlists[], Accessor &styler) {
 
314
        ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, ';');
 
315
}
 
316
 
 
317
static void ColouriseFreeBasicDoc(unsigned int startPos, int length, int initStyle,
 
318
                           WordList *keywordlists[], Accessor &styler) {
 
319
        ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, '\'');
 
320
}
 
321
 
 
322
static void FoldBlitzBasicDoc(unsigned int startPos, int length, int,
 
323
        WordList *[], Accessor &styler) {
 
324
        FoldBasicDoc(startPos, length, styler, CheckBlitzFoldPoint);
 
325
}
 
326
 
 
327
static void FoldPureBasicDoc(unsigned int startPos, int length, int,
 
328
        WordList *[], Accessor &styler) {
 
329
        FoldBasicDoc(startPos, length, styler, CheckPureFoldPoint);
 
330
}
 
331
 
 
332
static void FoldFreeBasicDoc(unsigned int startPos, int length, int,
 
333
        WordList *[], Accessor &styler) {
 
334
        FoldBasicDoc(startPos, length, styler, CheckFreeFoldPoint);
 
335
}
 
336
 
 
337
static const char * const blitzbasicWordListDesc[] = {
 
338
        "BlitzBasic Keywords",
 
339
        "user1",
 
340
        "user2",
 
341
        "user3",
 
342
        0
 
343
};
 
344
 
 
345
static const char * const purebasicWordListDesc[] = {
 
346
        "PureBasic Keywords",
 
347
        "PureBasic PreProcessor Keywords",
 
348
        "user defined 1",
 
349
        "user defined 2",
 
350
        0
 
351
};
 
352
 
 
353
static const char * const freebasicWordListDesc[] = {
 
354
        "FreeBasic Keywords",
 
355
        "FreeBasic PreProcessor Keywords",
 
356
        "user defined 1",
 
357
        "user defined 2",
 
358
        0
 
359
};
 
360
 
 
361
LexerModule lmBlitzBasic(SCLEX_BLITZBASIC, ColouriseBlitzBasicDoc, "blitzbasic",
 
362
        FoldBlitzBasicDoc, blitzbasicWordListDesc);
 
363
 
 
364
LexerModule lmPureBasic(SCLEX_PUREBASIC, ColourisePureBasicDoc, "purebasic",
 
365
        FoldPureBasicDoc, purebasicWordListDesc);
 
366
 
 
367
LexerModule lmFreeBasic(SCLEX_FREEBASIC, ColouriseFreeBasicDoc, "freebasic",
 
368
        FoldFreeBasicDoc, freebasicWordListDesc);
 
369