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

« back to all changes in this revision

Viewing changes to src/stc/scintilla/src/LexRebol.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
/** @file LexRebol.cxx
 
3
 ** Lexer for REBOL.
 
4
 ** Written by Pascal Hurni, inspired from LexLua by Paul Winwood & Marcos E. Wurzius & Philippe Lhoste
 
5
 **
 
6
 ** History:
 
7
 **             2005-04-07      First release.
 
8
 **             2005-04-10      Closing parens and brackets go now in default style
 
9
 **                                     String and comment nesting should be more safe
 
10
 **/
 
11
// Copyright 2005 by Pascal Hurni <pascal_hurni@fastmail.fm>
 
12
// The License.txt file describes the conditions under which this software may be distributed.
 
13
 
 
14
#include <stdlib.h>
 
15
#include <string.h>
 
16
#include <ctype.h>
 
17
#include <stdio.h>
 
18
#include <stdarg.h>
 
19
 
 
20
#include "Platform.h"
 
21
 
 
22
#include "PropSet.h"
 
23
#include "Accessor.h"
 
24
#include "KeyWords.h"
 
25
#include "Scintilla.h"
 
26
#include "SciLexer.h"
 
27
#include "StyleContext.h"
 
28
 
 
29
#ifdef SCI_NAMESPACE
 
30
using namespace Scintilla;
 
31
#endif
 
32
 
 
33
static inline bool IsAWordChar(const int ch) {
 
34
        return (isalnum(ch) || ch == '?' || ch == '!' || ch == '.' || ch == '\'' || ch == '+' || ch == '-' || ch == '*' || ch == '&' || ch == '|' || ch == '=' || ch == '_' || ch == '~');
 
35
}
 
36
 
 
37
static inline bool IsAWordStart(const int ch, const int ch2) {
 
38
        return ((ch == '+' || ch == '-' || ch == '.') && !isdigit(ch2)) ||
 
39
                (isalpha(ch) || ch == '?' || ch == '!' || ch == '\'' || ch == '*' || ch == '&' || ch == '|' || ch == '=' || ch == '_' || ch == '~');
 
40
}
 
41
 
 
42
static inline bool IsAnOperator(const int ch, const int ch2, const int ch3) {
 
43
        // One char operators
 
44
        if (IsASpaceOrTab(ch2)) {
 
45
                return ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '<' || ch == '>' || ch == '=' || ch == '?';
 
46
        }
 
47
 
 
48
        // Two char operators
 
49
        if (IsASpaceOrTab(ch3)) {
 
50
                return (ch == '*' && ch2 == '*') ||
 
51
                           (ch == '/' && ch2 == '/') ||
 
52
                           (ch == '<' && (ch2 == '=' || ch2 == '>')) ||
 
53
                           (ch == '>' && ch2 == '=') ||
 
54
                           (ch == '=' && (ch2 == '=' || ch2 == '?')) ||
 
55
                           (ch == '?' && ch2 == '?');
 
56
        }
 
57
 
 
58
        return false;
 
59
}
 
60
 
 
61
static inline bool IsBinaryStart(const int ch, const int ch2, const int ch3, const int ch4) {
 
62
        return (ch == '#' && ch2 == '{') ||
 
63
                   (IsADigit(ch) && ch2 == '#' && ch3 == '{' ) ||
 
64
                   (IsADigit(ch) && IsADigit(ch2) && ch3 == '#' && ch4 == '{' );
 
65
}
 
66
 
 
67
 
 
68
static void ColouriseRebolDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {
 
69
 
 
70
        WordList &keywords = *keywordlists[0];
 
71
        WordList &keywords2 = *keywordlists[1];
 
72
        WordList &keywords3 = *keywordlists[2];
 
73
        WordList &keywords4 = *keywordlists[3];
 
74
        WordList &keywords5 = *keywordlists[4];
 
75
        WordList &keywords6 = *keywordlists[5];
 
76
        WordList &keywords7 = *keywordlists[6];
 
77
        WordList &keywords8 = *keywordlists[7];
 
78
 
 
79
        int currentLine = styler.GetLine(startPos);
 
80
        // Initialize the braced string {.. { ... } ..} nesting level, if we are inside such a string.
 
81
        int stringLevel = 0;
 
82
        if (initStyle == SCE_REBOL_BRACEDSTRING || initStyle == SCE_REBOL_COMMENTBLOCK) {
 
83
                stringLevel = styler.GetLineState(currentLine - 1);
 
84
        }
 
85
 
 
86
        bool blockComment = initStyle == SCE_REBOL_COMMENTBLOCK;
 
87
        int dotCount = 0;
 
88
 
 
89
        // Do not leak onto next line
 
90
        if (initStyle == SCE_REBOL_COMMENTLINE) {
 
91
                initStyle = SCE_REBOL_DEFAULT;
 
92
        }
 
93
 
 
94
        StyleContext sc(startPos, length, initStyle, styler);
 
95
        if (startPos == 0) {
 
96
                sc.SetState(SCE_REBOL_PREFACE);
 
97
        }
 
98
        for (; sc.More(); sc.Forward()) {
 
99
 
 
100
                //--- What to do at line end ?
 
101
                if (sc.atLineEnd) {
 
102
                        // Can be either inside a {} string or simply at eol
 
103
                        if (sc.state != SCE_REBOL_BRACEDSTRING && sc.state != SCE_REBOL_COMMENTBLOCK &&
 
104
                                sc.state != SCE_REBOL_BINARY && sc.state != SCE_REBOL_PREFACE)
 
105
                                sc.SetState(SCE_REBOL_DEFAULT);
 
106
 
 
107
                        // Update the line state, so it can be seen by next line
 
108
                        currentLine = styler.GetLine(sc.currentPos);
 
109
                        switch (sc.state) {
 
110
                        case SCE_REBOL_BRACEDSTRING:
 
111
                        case SCE_REBOL_COMMENTBLOCK:
 
112
                                // Inside a braced string, we set the line state
 
113
                                styler.SetLineState(currentLine, stringLevel);
 
114
                                break;
 
115
                        default:
 
116
                                // Reset the line state
 
117
                                styler.SetLineState(currentLine, 0);
 
118
                                break;
 
119
                        }
 
120
 
 
121
                        // continue with next char
 
122
                        continue;
 
123
                }
 
124
 
 
125
                //--- What to do on white-space ?
 
126
                if (IsASpaceOrTab(sc.ch))
 
127
                {
 
128
                        // Return to default if any of these states
 
129
                        if (sc.state == SCE_REBOL_OPERATOR || sc.state == SCE_REBOL_CHARACTER ||
 
130
                                sc.state == SCE_REBOL_NUMBER || sc.state == SCE_REBOL_PAIR ||
 
131
                                sc.state == SCE_REBOL_TUPLE || sc.state == SCE_REBOL_FILE ||
 
132
                                sc.state == SCE_REBOL_DATE || sc.state == SCE_REBOL_TIME ||
 
133
                                sc.state == SCE_REBOL_MONEY || sc.state == SCE_REBOL_ISSUE ||
 
134
                                sc.state == SCE_REBOL_URL || sc.state == SCE_REBOL_EMAIL) {
 
135
                                sc.SetState(SCE_REBOL_DEFAULT);
 
136
                        }
 
137
                }
 
138
 
 
139
                //--- Specialize state ?
 
140
                // URL, Email look like identifier
 
141
                if (sc.state == SCE_REBOL_IDENTIFIER)
 
142
                {
 
143
                        if (sc.ch == ':' && !IsASpace(sc.chNext)) {
 
144
                                sc.ChangeState(SCE_REBOL_URL);
 
145
                        } else if (sc.ch == '@') {
 
146
                                sc.ChangeState(SCE_REBOL_EMAIL);
 
147
                        } else if (sc.ch == '$') {
 
148
                                sc.ChangeState(SCE_REBOL_MONEY);
 
149
                        }
 
150
                }
 
151
                // Words look like identifiers
 
152
                if (sc.state == SCE_REBOL_IDENTIFIER || (sc.state >= SCE_REBOL_WORD && sc.state <= SCE_REBOL_WORD8)) {
 
153
                        // Keywords ?
 
154
                        if (!IsAWordChar(sc.ch) || sc.Match('/')) {
 
155
                                char s[100];
 
156
                                sc.GetCurrentLowered(s, sizeof(s));
 
157
                                blockComment = strcmp(s, "comment") == 0;
 
158
                                if (keywords8.InList(s)) {
 
159
                                        sc.ChangeState(SCE_REBOL_WORD8);
 
160
                                } else if (keywords7.InList(s)) {
 
161
                                        sc.ChangeState(SCE_REBOL_WORD7);
 
162
                                } else if (keywords6.InList(s)) {
 
163
                                        sc.ChangeState(SCE_REBOL_WORD6);
 
164
                                } else if (keywords5.InList(s)) {
 
165
                                        sc.ChangeState(SCE_REBOL_WORD5);
 
166
                                } else if (keywords4.InList(s)) {
 
167
                                        sc.ChangeState(SCE_REBOL_WORD4);
 
168
                                } else if (keywords3.InList(s)) {
 
169
                                        sc.ChangeState(SCE_REBOL_WORD3);
 
170
                                } else if (keywords2.InList(s)) {
 
171
                                        sc.ChangeState(SCE_REBOL_WORD2);
 
172
                                } else if (keywords.InList(s)) {
 
173
                                        sc.ChangeState(SCE_REBOL_WORD);
 
174
                                }
 
175
                                // Keep same style if there are refinements
 
176
                                if (!sc.Match('/')) {
 
177
                                        sc.SetState(SCE_REBOL_DEFAULT);
 
178
                                }
 
179
                        }
 
180
                // special numbers
 
181
                } else if (sc.state == SCE_REBOL_NUMBER) {
 
182
                        switch (sc.ch) {
 
183
                        case 'x':       sc.ChangeState(SCE_REBOL_PAIR);
 
184
                                                break;
 
185
                        case ':':       sc.ChangeState(SCE_REBOL_TIME);
 
186
                                                break;
 
187
                        case '-':
 
188
                        case '/':       sc.ChangeState(SCE_REBOL_DATE);
 
189
                                                break;
 
190
                        case '.':       if (++dotCount >= 2) sc.ChangeState(SCE_REBOL_TUPLE);
 
191
                                                break;
 
192
                        }
 
193
                }
 
194
 
 
195
                //--- Determine if the current state should terminate
 
196
                if (sc.state == SCE_REBOL_QUOTEDSTRING || sc.state == SCE_REBOL_CHARACTER) {
 
197
                        if (sc.ch == '^' && sc.chNext == '\"') {
 
198
                                sc.Forward();
 
199
                        } else if (sc.ch == '\"') {
 
200
                                sc.ForwardSetState(SCE_REBOL_DEFAULT);
 
201
                        }
 
202
                } else if (sc.state == SCE_REBOL_BRACEDSTRING || sc.state == SCE_REBOL_COMMENTBLOCK) {
 
203
                        if (sc.ch == '}') {
 
204
                                if (--stringLevel == 0) {
 
205
                                        sc.ForwardSetState(SCE_REBOL_DEFAULT);
 
206
                                }
 
207
                        } else if (sc.ch == '{') {
 
208
                                stringLevel++;
 
209
                        }
 
210
                } else if (sc.state == SCE_REBOL_BINARY) {
 
211
                        if (sc.ch == '}') {
 
212
                                sc.ForwardSetState(SCE_REBOL_DEFAULT);
 
213
                        }
 
214
                } else if (sc.state == SCE_REBOL_TAG) {
 
215
                        if (sc.ch == '>') {
 
216
                                sc.ForwardSetState(SCE_REBOL_DEFAULT);
 
217
                        }
 
218
                } else if (sc.state == SCE_REBOL_PREFACE) {
 
219
                        if (sc.MatchIgnoreCase("rebol"))
 
220
                        {
 
221
                                int i;
 
222
                                for (i=5; IsASpaceOrTab(styler.SafeGetCharAt(sc.currentPos+i, 0)); i++);
 
223
                                if (sc.GetRelative(i) == '[')
 
224
                                        sc.SetState(SCE_REBOL_DEFAULT);
 
225
                        }
 
226
                }
 
227
 
 
228
                //--- Parens and bracket changes to default style when the current is a number
 
229
                if (sc.state == SCE_REBOL_NUMBER || sc.state == SCE_REBOL_PAIR || sc.state == SCE_REBOL_TUPLE ||
 
230
                        sc.state == SCE_REBOL_MONEY || sc.state == SCE_REBOL_ISSUE || sc.state == SCE_REBOL_EMAIL ||
 
231
                        sc.state == SCE_REBOL_URL || sc.state == SCE_REBOL_DATE || sc.state == SCE_REBOL_TIME) {
 
232
                        if (sc.ch == '(' || sc.ch == '[' || sc.ch == ')' || sc.ch == ']') {
 
233
                                sc.SetState(SCE_REBOL_DEFAULT);
 
234
                        }
 
235
                }
 
236
 
 
237
                //--- Determine if a new state should be entered.
 
238
                if (sc.state == SCE_REBOL_DEFAULT) {
 
239
                        if (IsAnOperator(sc.ch, sc.chNext, sc.GetRelative(2))) {
 
240
                                sc.SetState(SCE_REBOL_OPERATOR);
 
241
                        } else if (IsBinaryStart(sc.ch, sc.chNext, sc.GetRelative(2), sc.GetRelative(3))) {
 
242
                                sc.SetState(SCE_REBOL_BINARY);
 
243
                        } else if (IsAWordStart(sc.ch, sc.chNext)) {
 
244
                                sc.SetState(SCE_REBOL_IDENTIFIER);
 
245
                        } else if (IsADigit(sc.ch) || sc.ch == '+' || sc.ch == '-' || /*Decimal*/ sc.ch == '.' || sc.ch == ',') {
 
246
                                dotCount = 0;
 
247
                                sc.SetState(SCE_REBOL_NUMBER);
 
248
                        } else if (sc.ch == '\"') {
 
249
                                sc.SetState(SCE_REBOL_QUOTEDSTRING);
 
250
                        } else if (sc.ch == '{') {
 
251
                                sc.SetState(blockComment ? SCE_REBOL_COMMENTBLOCK : SCE_REBOL_BRACEDSTRING);
 
252
                                ++stringLevel;
 
253
                        } else if (sc.ch == ';') {
 
254
                                sc.SetState(SCE_REBOL_COMMENTLINE);
 
255
                        } else if (sc.ch == '$') {
 
256
                                sc.SetState(SCE_REBOL_MONEY);
 
257
                        } else if (sc.ch == '%') {
 
258
                                sc.SetState(SCE_REBOL_FILE);
 
259
                        } else if (sc.ch == '<') {
 
260
                                sc.SetState(SCE_REBOL_TAG);
 
261
                        } else if (sc.ch == '#' && sc.chNext == '"') {
 
262
                                sc.SetState(SCE_REBOL_CHARACTER);
 
263
                                sc.Forward();
 
264
                        } else if (sc.ch == '#' && sc.chNext != '"' && sc.chNext != '{' ) {
 
265
                                sc.SetState(SCE_REBOL_ISSUE);
 
266
                        }
 
267
                }
 
268
        }
 
269
        sc.Complete();
 
270
}
 
271
 
 
272
 
 
273
static void FoldRebolDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
 
274
                            Accessor &styler) {
 
275
        unsigned int lengthDoc = startPos + length;
 
276
        int visibleChars = 0;
 
277
        int lineCurrent = styler.GetLine(startPos);
 
278
        int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
 
279
        int levelCurrent = levelPrev;
 
280
        char chNext = styler[startPos];
 
281
        int styleNext = styler.StyleAt(startPos);
 
282
        for (unsigned int i = startPos; i < lengthDoc; i++) {
 
283
                char ch = chNext;
 
284
                chNext = styler.SafeGetCharAt(i + 1);
 
285
                int style = styleNext;
 
286
                styleNext = styler.StyleAt(i + 1);
 
287
                bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
 
288
                if (style == SCE_REBOL_DEFAULT) {
 
289
                        if (ch == '[') {
 
290
                                levelCurrent++;
 
291
                        } else if (ch == ']') {
 
292
                                levelCurrent--;
 
293
                        }
 
294
                }
 
295
                if (atEOL) {
 
296
                        int lev = levelPrev;
 
297
                        if (visibleChars == 0)
 
298
                                lev |= SC_FOLDLEVELWHITEFLAG;
 
299
                        if ((levelCurrent > levelPrev) && (visibleChars > 0))
 
300
                                lev |= SC_FOLDLEVELHEADERFLAG;
 
301
                        if (lev != styler.LevelAt(lineCurrent)) {
 
302
                                styler.SetLevel(lineCurrent, lev);
 
303
                        }
 
304
                        lineCurrent++;
 
305
                        levelPrev = levelCurrent;
 
306
                        visibleChars = 0;
 
307
                }
 
308
                if (!isspacechar(ch))
 
309
                        visibleChars++;
 
310
        }
 
311
        // Fill in the real level of the next line, keeping the current flags as they will be filled in later
 
312
        int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
 
313
        styler.SetLevel(lineCurrent, levelPrev | flagsNext);
 
314
}
 
315
 
 
316
static const char * const rebolWordListDesc[] = {
 
317
        "Keywords",
 
318
        0
 
319
};
 
320
 
 
321
LexerModule lmREBOL(SCLEX_REBOL, ColouriseRebolDoc, "rebol", FoldRebolDoc, rebolWordListDesc);
 
322