~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/sdk/wxscintilla/src/scintilla/lexers/LexTCL.cxx

  • Committer: damienlmoore at gmail
  • Date: 2016-02-02 02:43:22 UTC
  • Revision ID: damienlmoore@gmail.com-20160202024322-yql5qmtbwdyamdwd
Code::BlocksĀ 16.01

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Scintilla source code edit control
 
2
/** @file LexTCL.cxx
 
3
 ** Lexer for TCL language.
 
4
 **/
 
5
// Copyright 1998-2001 by Andre Arpin <arpin@kingston.net>
 
6
// The License.txt file describes the conditions under which this software may be distributed.
 
7
 
 
8
#include <stdlib.h>
 
9
#include <string.h>
 
10
#include <stdio.h>
 
11
#include <stdarg.h>
 
12
#include <assert.h>
 
13
#include <ctype.h>
 
14
 
 
15
#include "ILexer.h"
 
16
#include "Scintilla.h"
 
17
#include "SciLexer.h"
 
18
 
 
19
#include "WordList.h"
 
20
#include "LexAccessor.h"
 
21
#include "Accessor.h"
 
22
#include "StyleContext.h"
 
23
#include "CharacterSet.h"
 
24
#include "LexerModule.h"
 
25
 
 
26
#ifdef SCI_NAMESPACE
 
27
using namespace Scintilla;
 
28
#endif
 
29
 
 
30
// Extended to accept accented characters
 
31
static inline bool IsAWordChar(int ch) {
 
32
        return ch >= 0x80 ||
 
33
        (isalnum(ch) || ch == '_' || ch ==':' || ch=='.'); // : name space separator
 
34
}
 
35
 
 
36
static inline bool IsAWordStart(int ch) {
 
37
        return ch >= 0x80 || (ch ==':' || isalpha(ch) || ch == '_');
 
38
}
 
39
 
 
40
static inline bool IsANumberChar(int ch) {
 
41
        // Not exactly following number definition (several dots are seen as OK, etc.)
 
42
        // but probably enough in most cases.
 
43
        return (ch < 0x80) &&
 
44
               (IsADigit(ch, 0x10) || toupper(ch) == 'E' ||
 
45
                ch == '.' || ch == '-' || ch == '+');
 
46
}
 
47
 
 
48
static void ColouriseTCLDoc(unsigned int startPos, int length, int , WordList *keywordlists[], Accessor &styler) {
 
49
#define  isComment(s) (s==SCE_TCL_COMMENT || s==SCE_TCL_COMMENTLINE || s==SCE_TCL_COMMENT_BOX || s==SCE_TCL_BLOCK_COMMENT)
 
50
        bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
 
51
        bool commentLevel = false;
 
52
    bool subBrace = false; // substitution begin with a brace ${.....}
 
53
        enum tLineState {LS_DEFAULT, LS_OPEN_COMMENT, LS_OPEN_DOUBLE_QUOTE, LS_COMMENT_BOX, LS_MASK_STATE = 0xf,
 
54
        LS_COMMAND_EXPECTED = 16, LS_BRACE_ONLY = 32 } lineState = LS_DEFAULT;
 
55
        bool prevSlash = false;
 
56
        int currentLevel = 0;
 
57
    bool expected = 0;
 
58
    bool subParen = 0;
 
59
 
 
60
        int currentLine = styler.GetLine(startPos);
 
61
    if (currentLine > 0)
 
62
        currentLine--;
 
63
        length += startPos - styler.LineStart(currentLine);
 
64
        // make sure lines overlap
 
65
        startPos = styler.LineStart(currentLine);
 
66
 
 
67
        WordList &keywords = *keywordlists[0];
 
68
        WordList &keywords2 = *keywordlists[1];
 
69
        WordList &keywords3 = *keywordlists[2];
 
70
        WordList &keywords4 = *keywordlists[3];
 
71
        WordList &keywords5 = *keywordlists[4];
 
72
        WordList &keywords6 = *keywordlists[5];
 
73
        WordList &keywords7 = *keywordlists[6];
 
74
    WordList &keywords8 = *keywordlists[7];
 
75
    WordList &keywords9 = *keywordlists[8];
 
76
 
 
77
        if (currentLine > 0) {
 
78
        int ls = styler.GetLineState(currentLine - 1);
 
79
                lineState = tLineState(ls & LS_MASK_STATE);
 
80
                expected = LS_COMMAND_EXPECTED == tLineState(ls & LS_COMMAND_EXPECTED);
 
81
        subBrace = LS_BRACE_ONLY == tLineState(ls & LS_BRACE_ONLY);
 
82
                currentLevel = styler.LevelAt(currentLine - 1) >> 17;
 
83
                commentLevel = (styler.LevelAt(currentLine - 1) >> 16) & 1;
 
84
        } else
 
85
                styler.SetLevel(0, SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG);
 
86
        bool visibleChars = false;
 
87
 
 
88
        int previousLevel = currentLevel;
 
89
    StyleContext sc(startPos, length, SCE_TCL_DEFAULT, styler);
 
90
        for (; ; sc.Forward()) {
 
91
next:
 
92
        if (sc.ch=='\r' && sc.chNext == '\n') // only ignore \r on PC process on the mac
 
93
            continue;
 
94
        bool atEnd = !sc.More();  // make sure we coloured the last word
 
95
        if (lineState != LS_DEFAULT) {
 
96
            sc.SetState(SCE_TCL_DEFAULT);
 
97
            if (lineState == LS_OPEN_COMMENT)
 
98
                sc.SetState(SCE_TCL_COMMENTLINE);
 
99
            else if (lineState == LS_OPEN_DOUBLE_QUOTE)
 
100
                sc.SetState(SCE_TCL_IN_QUOTE);
 
101
            else if (lineState == LS_COMMENT_BOX && (sc.ch == '#' || (sc.ch == ' ' && sc.chNext=='#')))
 
102
                sc.SetState(SCE_TCL_COMMENT_BOX);
 
103
            lineState = LS_DEFAULT;
 
104
        }
 
105
        if (subBrace) { // ${ overrides every thing even \ except }
 
106
            if (sc.ch == '}') {
 
107
                subBrace = false;
 
108
                sc.SetState(SCE_TCL_OPERATOR);
 
109
                sc.ForwardSetState(SCE_TCL_DEFAULT);
 
110
                goto next;
 
111
            }
 
112
            else
 
113
                sc.SetState(SCE_TCL_SUB_BRACE);
 
114
            if (!sc.atLineEnd)
 
115
                continue;
 
116
        } else if (sc.state == SCE_TCL_DEFAULT || sc.state ==SCE_TCL_OPERATOR) {
 
117
            expected &= isspacechar(static_cast<unsigned char>(sc.ch)) || IsAWordStart(sc.ch) || sc.ch =='#';
 
118
        } else if (sc.state == SCE_TCL_SUBSTITUTION) {
 
119
            switch(sc.ch) {
 
120
            case '(':
 
121
                subParen=true;
 
122
                sc.SetState(SCE_TCL_OPERATOR);
 
123
                sc.ForwardSetState(SCE_TCL_SUBSTITUTION);
 
124
                continue;
 
125
            case ')':
 
126
                sc.SetState(SCE_TCL_OPERATOR);
 
127
                subParen=false;
 
128
                continue;
 
129
            case '$':
 
130
                continue;
 
131
            case ',':
 
132
                sc.SetState(SCE_TCL_OPERATOR);
 
133
                if (subParen)
 
134
                    sc.ForwardSetState(SCE_TCL_SUBSTITUTION);
 
135
                continue;
 
136
            default :
 
137
                // maybe spaces should be allowed ???
 
138
                if (!IsAWordChar(sc.ch)) { // probably the code is wrong
 
139
                    sc.SetState(SCE_TCL_DEFAULT);
 
140
                    subParen = 0;
 
141
                }
 
142
                break;
 
143
            }
 
144
        } else if (isComment(sc.state)) {
 
145
        } else if (!IsAWordChar(sc.ch)) {
 
146
            if ((sc.state == SCE_TCL_IDENTIFIER && expected) ||  sc.state == SCE_TCL_MODIFIER) {
 
147
                char w[100];
 
148
                char *s=w;
 
149
                sc.GetCurrent(w, sizeof(w));
 
150
                if (w[strlen(w)-1]=='\r')
 
151
                    w[strlen(w)-1]=0;
 
152
                while(*s == ':') // ignore leading : like in ::set a 10
 
153
                    ++s;
 
154
                bool quote = sc.state == SCE_TCL_IN_QUOTE;
 
155
                if (commentLevel  || expected) {
 
156
                    if (keywords.InList(s)) {
 
157
                        sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD);
 
158
                    } else if (keywords2.InList(s)) {
 
159
                        sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD2);
 
160
                    } else if (keywords3.InList(s)) {
 
161
                        sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD3);
 
162
                    } else if (keywords4.InList(s)) {
 
163
                        sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD4);
 
164
                    } else if (sc.GetRelative(-static_cast<int>(strlen(s))-1) == '{' &&
 
165
                        keywords5.InList(s) && sc.ch == '}') { // {keyword} exactly no spaces
 
166
                            sc.ChangeState(SCE_TCL_EXPAND);
 
167
                    }
 
168
                    if (keywords6.InList(s)) {
 
169
                        sc.ChangeState(SCE_TCL_WORD5);
 
170
                    } else if (keywords7.InList(s)) {
 
171
                        sc.ChangeState(SCE_TCL_WORD6);
 
172
                    } else if (keywords8.InList(s)) {
 
173
                        sc.ChangeState(SCE_TCL_WORD7);
 
174
                    } else if (keywords9.InList(s)) {
 
175
                        sc.ChangeState(SCE_TCL_WORD8);
 
176
                    }
 
177
                }
 
178
                expected = false;
 
179
                sc.SetState(quote ? SCE_TCL_IN_QUOTE : SCE_TCL_DEFAULT);
 
180
            } else if (sc.state == SCE_TCL_MODIFIER || sc.state == SCE_TCL_IDENTIFIER) {
 
181
                sc.SetState(SCE_TCL_DEFAULT);
 
182
            }
 
183
        }
 
184
                if (atEnd)
 
185
                        break;
 
186
        if (sc.atLineEnd) {
 
187
            lineState = LS_DEFAULT;
 
188
                        currentLine = styler.GetLine(sc.currentPos);
 
189
                        if (foldComment && sc.state!=SCE_TCL_COMMENT && isComment(sc.state)) {
 
190
                                if (currentLevel == 0) {
 
191
                                        ++currentLevel;
 
192
                                        commentLevel = true;
 
193
                                }
 
194
                        } else {
 
195
                                if (visibleChars && commentLevel) {
 
196
                                        --currentLevel;
 
197
                                        --previousLevel;
 
198
                                        commentLevel = false;
 
199
                                }
 
200
                        }
 
201
                        int flag = 0;
 
202
                        if (!visibleChars)
 
203
                                flag = SC_FOLDLEVELWHITEFLAG;
 
204
                        if (currentLevel > previousLevel)
 
205
                                flag = SC_FOLDLEVELHEADERFLAG;
 
206
                        styler.SetLevel(currentLine, flag + previousLevel + SC_FOLDLEVELBASE + (currentLevel << 17) + (commentLevel << 16));
 
207
 
 
208
                        // Update the line state, so it can be seen by next line
 
209
                        if (sc.state == SCE_TCL_IN_QUOTE)
 
210
                                lineState = LS_OPEN_DOUBLE_QUOTE;
 
211
                        else {
 
212
                             if (prevSlash) {
 
213
                                    if (isComment(sc.state))
 
214
                                            lineState = LS_OPEN_COMMENT;
 
215
                } else if (sc.state == SCE_TCL_COMMENT_BOX)
 
216
                    lineState = LS_COMMENT_BOX;
 
217
                        }
 
218
            styler.SetLineState(currentLine,
 
219
                (subBrace ? LS_BRACE_ONLY : 0) |
 
220
                (expected ? LS_COMMAND_EXPECTED : 0)  | lineState);
 
221
            if (lineState == LS_COMMENT_BOX)
 
222
                sc.ForwardSetState(SCE_TCL_COMMENT_BOX);
 
223
            else if (lineState == LS_OPEN_DOUBLE_QUOTE)
 
224
                sc.ForwardSetState(SCE_TCL_IN_QUOTE);
 
225
            else
 
226
                sc.ForwardSetState(SCE_TCL_DEFAULT);
 
227
                        prevSlash = false;
 
228
                        previousLevel = currentLevel;
 
229
                        goto next;
 
230
                }
 
231
 
 
232
                if (prevSlash) {
 
233
            prevSlash = false;
 
234
            if (sc.ch == '#' && IsANumberChar(sc.chNext))
 
235
                sc.ForwardSetState(SCE_TCL_NUMBER);
 
236
            continue;
 
237
                }
 
238
        prevSlash = sc.ch == '\\';
 
239
        if (isComment(sc.state))
 
240
            continue;
 
241
                if (sc.atLineStart) {
 
242
                        visibleChars = false;
 
243
                        if (sc.state!=SCE_TCL_IN_QUOTE && !isComment(sc.state))
 
244
            {
 
245
                                sc.SetState(SCE_TCL_DEFAULT);
 
246
                expected = IsAWordStart(sc.ch)|| isspacechar(static_cast<unsigned char>(sc.ch));
 
247
            }
 
248
                }
 
249
 
 
250
                switch (sc.state) {
 
251
                case SCE_TCL_NUMBER:
 
252
                        if (!IsANumberChar(sc.ch))
 
253
                                sc.SetState(SCE_TCL_DEFAULT);
 
254
                        break;
 
255
                case SCE_TCL_IN_QUOTE:
 
256
                        if (sc.ch == '"') {
 
257
                                sc.ForwardSetState(SCE_TCL_DEFAULT);
 
258
                                visibleChars = true; // necessary if a " is the first and only character on a line
 
259
                                goto next;
 
260
                        } else if (sc.ch == '[' || sc.ch == ']' || sc.ch == '$') {
 
261
                                sc.SetState(SCE_TCL_OPERATOR);
 
262
                expected = sc.ch == '[';
 
263
                sc.ForwardSetState(SCE_TCL_IN_QUOTE);
 
264
                                goto next;
 
265
                        }
 
266
            continue;
 
267
        case SCE_TCL_OPERATOR:
 
268
                        sc.SetState(SCE_TCL_DEFAULT);
 
269
                        break;
 
270
                }
 
271
 
 
272
                if (sc.ch == '#') {
 
273
                        if (visibleChars) {
 
274
                if (sc.state != SCE_TCL_IN_QUOTE && expected)
 
275
                                        sc.SetState(SCE_TCL_COMMENT);
 
276
                        } else {
 
277
                sc.SetState(SCE_TCL_COMMENTLINE);
 
278
                if (sc.chNext == '~')
 
279
                    sc.SetState(SCE_TCL_BLOCK_COMMENT);
 
280
                if (sc.atLineStart && (sc.chNext == '#' || sc.chNext == '-'))
 
281
                        sc.SetState(SCE_TCL_COMMENT_BOX);
 
282
            }
 
283
        }
 
284
 
 
285
                if (!isspacechar(static_cast<unsigned char>(sc.ch))) {
 
286
                        visibleChars = true;
 
287
                }
 
288
 
 
289
                if (sc.ch == '\\') {
 
290
                        prevSlash = true;
 
291
                        continue;
 
292
                }
 
293
 
 
294
                // Determine if a new state should be entered.
 
295
                if (sc.state == SCE_TCL_DEFAULT) {
 
296
            if (IsAWordStart(sc.ch)) {
 
297
                                sc.SetState(SCE_TCL_IDENTIFIER);
 
298
                        } else if (IsADigit(sc.ch) && !IsAWordChar(sc.chPrev)) {
 
299
                                sc.SetState(SCE_TCL_NUMBER);
 
300
                        } else {
 
301
                                switch (sc.ch) {
 
302
                                case '\"':
 
303
                                        sc.SetState(SCE_TCL_IN_QUOTE);
 
304
                                        break;
 
305
                                case '{':
 
306
                                        sc.SetState(SCE_TCL_OPERATOR);
 
307
                                        expected = true;
 
308
                                        ++currentLevel;
 
309
                                        break;
 
310
                                case '}':
 
311
                                        sc.SetState(SCE_TCL_OPERATOR);
 
312
                                        expected = true;
 
313
                                        --currentLevel;
 
314
                                        break;
 
315
                                case '[':
 
316
                    expected = true;
 
317
                                case ']':
 
318
                                case '(':
 
319
                                case ')':
 
320
                                        sc.SetState(SCE_TCL_OPERATOR);
 
321
                                        break;
 
322
                                case ';':
 
323
                    expected = true;
 
324
                                        break;
 
325
                case '$':
 
326
                    subParen = 0;
 
327
                    if (sc.chNext != '{') {
 
328
                        sc.SetState(SCE_TCL_SUBSTITUTION);
 
329
                    }
 
330
                    else {
 
331
                        sc.SetState(SCE_TCL_OPERATOR);  // $
 
332
                        sc.Forward();  // {
 
333
                        sc.ForwardSetState(SCE_TCL_SUB_BRACE);
 
334
                        subBrace = true;
 
335
                    }
 
336
                    break;
 
337
                case '#':
 
338
                    if ((isspacechar(static_cast<unsigned char>(sc.chPrev))||
 
339
                            isoperator(static_cast<char>(sc.chPrev))) && IsADigit(sc.chNext,0x10))
 
340
                        sc.SetState(SCE_TCL_NUMBER);
 
341
                    break;
 
342
                case '-':
 
343
                    sc.SetState(IsADigit(sc.chNext)? SCE_TCL_NUMBER: SCE_TCL_MODIFIER);
 
344
                    break;
 
345
                default:
 
346
                    if (isoperator(static_cast<char>(sc.ch))) {
 
347
                        sc.SetState(SCE_TCL_OPERATOR);
 
348
                    }
 
349
                                }
 
350
                        }
 
351
                }
 
352
        }
 
353
        sc.Complete();
 
354
}
 
355
 
 
356
static const char * const tclWordListDesc[] = {
 
357
            "TCL Keywords",
 
358
            "TK Keywords",
 
359
            "iTCL Keywords",
 
360
            "tkCommands",
 
361
            "expand",
 
362
            "user1",
 
363
            "user2",
 
364
            "user3",
 
365
            "user4",
 
366
            0
 
367
        };
 
368
 
 
369
// this code supports folding in the colourizer
 
370
LexerModule lmTCL(SCLEX_TCL, ColouriseTCLDoc, "tcl", 0, tclWordListDesc);