~ubuntu-branches/ubuntu/utopic/geany/utopic

« back to all changes in this revision

Viewing changes to scintilla/lexers/LexBasic.cxx

  • Committer: Package Import Robot
  • Author(s): Chow Loong Jin
  • Date: 2011-12-10 07:43:26 UTC
  • mfrom: (3.3.7 sid)
  • Revision ID: package-import@ubuntu.com-20111210074326-s8yqbew5i20h33tf
Tags: 0.21-1ubuntu1
* Merge from Debian Unstable, remaining changes:
  - debian/patches/20_use_evince_viewer.patch:
     + use evince as viewer for pdf and dvi files
  - debian/patches/20_use_x_terminal_emulator.patch:
     + use x-terminal-emulator as terminal
  - debian/control
     + Add breaks on geany-plugins-common << 0.20
* Also fixes bugs:
  - Filter for MATLAB/Octave files filters everythign (LP: 885505)

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