~ubuntu-branches/ubuntu/quantal/mysql-workbench/quantal

« back to all changes in this revision

Viewing changes to ext/scintilla/lexers/LexPS.cxx

  • Committer: Package Import Robot
  • Author(s): Dmitry Smirnov
  • Date: 2012-03-01 21:57:30 UTC
  • Revision ID: package-import@ubuntu.com-20120301215730-o7y8av8y38n162ro
Tags: upstream-5.2.38+dfsg
ImportĀ upstreamĀ versionĀ 5.2.38+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Scintilla source code edit control
 
2
/** @file LexPS.cxx
 
3
 ** Lexer for PostScript
 
4
 **
 
5
 ** Written by Nigel Hathaway <nigel@bprj.co.uk>.
 
6
 ** The License.txt file describes the conditions under which this software may be distributed.
 
7
 **/
 
8
 
 
9
#include <stdlib.h>
 
10
#include <string.h>
 
11
#include <stdio.h>
 
12
#include <stdarg.h>
 
13
#include <assert.h>
 
14
#include <ctype.h>
 
15
 
 
16
#include "ILexer.h"
 
17
#include "Scintilla.h"
 
18
#include "SciLexer.h"
 
19
 
 
20
#include "WordList.h"
 
21
#include "LexAccessor.h"
 
22
#include "Accessor.h"
 
23
#include "StyleContext.h"
 
24
#include "CharacterSet.h"
 
25
#include "LexerModule.h"
 
26
 
 
27
#ifdef SCI_NAMESPACE
 
28
using namespace Scintilla;
 
29
#endif
 
30
 
 
31
static inline bool IsASelfDelimitingChar(const int ch) {
 
32
    return (ch == '[' || ch == ']' || ch == '{' || ch == '}' ||
 
33
            ch == '/' || ch == '<' || ch == '>' ||
 
34
            ch == '(' || ch == ')' || ch == '%');
 
35
}
 
36
 
 
37
static inline bool IsAWhitespaceChar(const int ch) {
 
38
    return (ch == ' '  || ch == '\t' || ch == '\r' ||
 
39
            ch == '\n' || ch == '\f' || ch == '\0');
 
40
}
 
41
 
 
42
static bool IsABaseNDigit(const int ch, const int base) {
 
43
    int maxdig = '9';
 
44
    int letterext = -1;
 
45
 
 
46
    if (base <= 10)
 
47
        maxdig = '0' + base - 1;
 
48
    else
 
49
        letterext = base - 11;
 
50
 
 
51
    return ((ch >= '0' && ch <= maxdig) ||
 
52
            (ch >= 'A' && ch <= ('A' + letterext)) ||
 
53
            (ch >= 'a' && ch <= ('a' + letterext)));
 
54
}
 
55
 
 
56
static inline bool IsABase85Char(const int ch) {
 
57
    return ((ch >= '!' && ch <= 'u') || ch == 'z');
 
58
}
 
59
 
 
60
static void ColourisePSDoc(
 
61
    unsigned int startPos,
 
62
    int length,
 
63
    int initStyle,
 
64
    WordList *keywordlists[],
 
65
    Accessor &styler) {
 
66
 
 
67
    WordList &keywords1 = *keywordlists[0];
 
68
    WordList &keywords2 = *keywordlists[1];
 
69
    WordList &keywords3 = *keywordlists[2];
 
70
    WordList &keywords4 = *keywordlists[3];
 
71
    WordList &keywords5 = *keywordlists[4];
 
72
 
 
73
    StyleContext sc(startPos, length, initStyle, styler);
 
74
 
 
75
    bool tokenizing = styler.GetPropertyInt("ps.tokenize") != 0;
 
76
    int pslevel = styler.GetPropertyInt("ps.level", 3);
 
77
    int lineCurrent = styler.GetLine(startPos);
 
78
    int nestTextCurrent = 0;
 
79
    if (lineCurrent > 0 && initStyle == SCE_PS_TEXT)
 
80
        nestTextCurrent = styler.GetLineState(lineCurrent - 1);
 
81
    int numRadix = 0;
 
82
    bool numHasPoint = false;
 
83
    bool numHasExponent = false;
 
84
    bool numHasSign = false;
 
85
 
 
86
    // Clear out existing tokenization
 
87
    if (tokenizing && length > 0) {
 
88
        styler.StartAt(startPos, static_cast<char>(INDIC2_MASK));
 
89
        styler.ColourTo(startPos + length-1, 0);
 
90
        styler.Flush();
 
91
        styler.StartAt(startPos);
 
92
        styler.StartSegment(startPos);
 
93
    }
 
94
 
 
95
    for (; sc.More(); sc.Forward()) {
 
96
        if (sc.atLineStart)
 
97
            lineCurrent = styler.GetLine(sc.currentPos);
 
98
 
 
99
        // Determine if the current state should terminate.
 
100
        if (sc.state == SCE_PS_COMMENT || sc.state == SCE_PS_DSC_VALUE) {
 
101
            if (sc.atLineEnd) {
 
102
                sc.SetState(SCE_C_DEFAULT);
 
103
            }
 
104
        } else if (sc.state == SCE_PS_DSC_COMMENT) {
 
105
            if (sc.ch == ':') {
 
106
                sc.Forward();
 
107
                if (!sc.atLineEnd)
 
108
                    sc.SetState(SCE_PS_DSC_VALUE);
 
109
                else
 
110
                    sc.SetState(SCE_C_DEFAULT);
 
111
            } else if (sc.atLineEnd) {
 
112
                sc.SetState(SCE_C_DEFAULT);
 
113
            } else if (IsAWhitespaceChar(sc.ch) && sc.ch != '\r') {
 
114
                sc.ChangeState(SCE_PS_COMMENT);
 
115
            }
 
116
        } else if (sc.state == SCE_PS_NUMBER) {
 
117
            if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) {
 
118
                if ((sc.chPrev == '+' || sc.chPrev == '-' ||
 
119
                     sc.chPrev == 'E' || sc.chPrev == 'e') && numRadix == 0)
 
120
                    sc.ChangeState(SCE_PS_NAME);
 
121
                sc.SetState(SCE_C_DEFAULT);
 
122
            } else if (sc.ch == '#') {
 
123
                if (numHasPoint || numHasExponent || numHasSign || numRadix != 0) {
 
124
                    sc.ChangeState(SCE_PS_NAME);
 
125
                } else {
 
126
                    char szradix[5];
 
127
                    sc.GetCurrent(szradix, 4);
 
128
                    numRadix = atoi(szradix);
 
129
                    if (numRadix < 2 || numRadix > 36)
 
130
                        sc.ChangeState(SCE_PS_NAME);
 
131
                }
 
132
            } else if ((sc.ch == 'E' || sc.ch == 'e') && numRadix == 0) {
 
133
                if (numHasExponent) {
 
134
                    sc.ChangeState(SCE_PS_NAME);
 
135
                } else {
 
136
                    numHasExponent = true;
 
137
                    if (sc.chNext == '+' || sc.chNext == '-')
 
138
                        sc.Forward();
 
139
                }
 
140
            } else if (sc.ch == '.') {
 
141
                if (numHasPoint || numHasExponent || numRadix != 0) {
 
142
                    sc.ChangeState(SCE_PS_NAME);
 
143
                } else {
 
144
                    numHasPoint = true;
 
145
                }
 
146
            } else if (numRadix == 0) {
 
147
                if (!IsABaseNDigit(sc.ch, 10))
 
148
                    sc.ChangeState(SCE_PS_NAME);
 
149
            } else {
 
150
                if (!IsABaseNDigit(sc.ch, numRadix))
 
151
                    sc.ChangeState(SCE_PS_NAME);
 
152
            }
 
153
        } else if (sc.state == SCE_PS_NAME || sc.state == SCE_PS_KEYWORD) {
 
154
            if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) {
 
155
                char s[100];
 
156
                sc.GetCurrent(s, sizeof(s));
 
157
                if ((pslevel >= 1 && keywords1.InList(s)) ||
 
158
                    (pslevel >= 2 && keywords2.InList(s)) ||
 
159
                    (pslevel >= 3 && keywords3.InList(s)) ||
 
160
                    keywords4.InList(s) || keywords5.InList(s)) {
 
161
                    sc.ChangeState(SCE_PS_KEYWORD);
 
162
                }
 
163
                sc.SetState(SCE_C_DEFAULT);
 
164
            }
 
165
        } else if (sc.state == SCE_PS_LITERAL || sc.state == SCE_PS_IMMEVAL) {
 
166
            if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch))
 
167
                sc.SetState(SCE_C_DEFAULT);
 
168
        } else if (sc.state == SCE_PS_PAREN_ARRAY || sc.state == SCE_PS_PAREN_DICT ||
 
169
                   sc.state == SCE_PS_PAREN_PROC) {
 
170
            sc.SetState(SCE_C_DEFAULT);
 
171
        } else if (sc.state == SCE_PS_TEXT) {
 
172
            if (sc.ch == '(') {
 
173
                nestTextCurrent++;
 
174
            } else if (sc.ch == ')') {
 
175
                if (--nestTextCurrent == 0)
 
176
                   sc.ForwardSetState(SCE_PS_DEFAULT);
 
177
            } else if (sc.ch == '\\') {
 
178
                sc.Forward();
 
179
            }
 
180
        } else if (sc.state == SCE_PS_HEXSTRING) {
 
181
            if (sc.ch == '>') {
 
182
                sc.ForwardSetState(SCE_PS_DEFAULT);
 
183
            } else if (!IsABaseNDigit(sc.ch, 16) && !IsAWhitespaceChar(sc.ch)) {
 
184
                sc.SetState(SCE_PS_HEXSTRING);
 
185
                styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
 
186
            }
 
187
        } else if (sc.state == SCE_PS_BASE85STRING) {
 
188
            if (sc.Match('~', '>')) {
 
189
                sc.Forward();
 
190
                sc.ForwardSetState(SCE_PS_DEFAULT);
 
191
            } else if (!IsABase85Char(sc.ch) && !IsAWhitespaceChar(sc.ch)) {
 
192
                sc.SetState(SCE_PS_BASE85STRING);
 
193
                styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
 
194
            }
 
195
        }
 
196
 
 
197
        // Determine if a new state should be entered.
 
198
        if (sc.state == SCE_C_DEFAULT) {
 
199
            unsigned int tokenpos = sc.currentPos;
 
200
 
 
201
            if (sc.ch == '[' || sc.ch == ']') {
 
202
                sc.SetState(SCE_PS_PAREN_ARRAY);
 
203
            } else if (sc.ch == '{' || sc.ch == '}') {
 
204
                sc.SetState(SCE_PS_PAREN_PROC);
 
205
            } else if (sc.ch == '/') {
 
206
                if (sc.chNext == '/') {
 
207
                    sc.SetState(SCE_PS_IMMEVAL);
 
208
                    sc.Forward();
 
209
                } else {
 
210
                    sc.SetState(SCE_PS_LITERAL);
 
211
                }
 
212
            } else if (sc.ch == '<') {
 
213
                if (sc.chNext == '<') {
 
214
                    sc.SetState(SCE_PS_PAREN_DICT);
 
215
                    sc.Forward();
 
216
                } else if (sc.chNext == '~') {
 
217
                    sc.SetState(SCE_PS_BASE85STRING);
 
218
                    sc.Forward();
 
219
                } else {
 
220
                    sc.SetState(SCE_PS_HEXSTRING);
 
221
                }
 
222
            } else if (sc.ch == '>' && sc.chNext == '>') {
 
223
                    sc.SetState(SCE_PS_PAREN_DICT);
 
224
                    sc.Forward();
 
225
            } else if (sc.ch == '>' || sc.ch == ')') {
 
226
                sc.SetState(SCE_C_DEFAULT);
 
227
                styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
 
228
            } else if (sc.ch == '(') {
 
229
                sc.SetState(SCE_PS_TEXT);
 
230
                nestTextCurrent = 1;
 
231
            } else if (sc.ch == '%') {
 
232
                if (sc.chNext == '%' && sc.atLineStart) {
 
233
                    sc.SetState(SCE_PS_DSC_COMMENT);
 
234
                    sc.Forward();
 
235
                    if (sc.chNext == '+') {
 
236
                        sc.Forward();
 
237
                        sc.ForwardSetState(SCE_PS_DSC_VALUE);
 
238
                    }
 
239
                } else {
 
240
                    sc.SetState(SCE_PS_COMMENT);
 
241
                }
 
242
            } else if ((sc.ch == '+' || sc.ch == '-' || sc.ch == '.') &&
 
243
                       IsABaseNDigit(sc.chNext, 10)) {
 
244
                sc.SetState(SCE_PS_NUMBER);
 
245
                numRadix = 0;
 
246
                numHasPoint = (sc.ch == '.');
 
247
                numHasExponent = false;
 
248
                numHasSign = (sc.ch == '+' || sc.ch == '-');
 
249
            } else if ((sc.ch == '+' || sc.ch == '-') && sc.chNext == '.' &&
 
250
                       IsABaseNDigit(sc.GetRelative(2), 10)) {
 
251
                sc.SetState(SCE_PS_NUMBER);
 
252
                numRadix = 0;
 
253
                numHasPoint = false;
 
254
                numHasExponent = false;
 
255
                numHasSign = true;
 
256
            } else if (IsABaseNDigit(sc.ch, 10)) {
 
257
                sc.SetState(SCE_PS_NUMBER);
 
258
                numRadix = 0;
 
259
                numHasPoint = false;
 
260
                numHasExponent = false;
 
261
                numHasSign = false;
 
262
            } else if (!IsAWhitespaceChar(sc.ch)) {
 
263
                sc.SetState(SCE_PS_NAME);
 
264
            }
 
265
 
 
266
            // Mark the start of tokens
 
267
            if (tokenizing && sc.state != SCE_C_DEFAULT && sc.state != SCE_PS_COMMENT &&
 
268
                sc.state != SCE_PS_DSC_COMMENT && sc.state != SCE_PS_DSC_VALUE) {
 
269
                styler.Flush();
 
270
                styler.StartAt(tokenpos, static_cast<char>(INDIC2_MASK));
 
271
                styler.ColourTo(tokenpos, INDIC2_MASK);
 
272
                styler.Flush();
 
273
                styler.StartAt(tokenpos);
 
274
                styler.StartSegment(tokenpos);
 
275
            }
 
276
        }
 
277
 
 
278
        if (sc.atLineEnd)
 
279
            styler.SetLineState(lineCurrent, nestTextCurrent);
 
280
    }
 
281
 
 
282
    sc.Complete();
 
283
}
 
284
 
 
285
static void FoldPSDoc(unsigned int startPos, int length, int, WordList *[],
 
286
                       Accessor &styler) {
 
287
    bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
 
288
    bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
 
289
    unsigned int endPos = startPos + length;
 
290
    int visibleChars = 0;
 
291
    int lineCurrent = styler.GetLine(startPos);
 
292
    int levelCurrent = SC_FOLDLEVELBASE;
 
293
    if (lineCurrent > 0)
 
294
        levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
 
295
    int levelMinCurrent = levelCurrent;
 
296
    int levelNext = levelCurrent;
 
297
    char chNext = styler[startPos];
 
298
    int styleNext = styler.StyleAt(startPos);
 
299
    int style;
 
300
    for (unsigned int i = startPos; i < endPos; i++) {
 
301
        char ch = chNext;
 
302
        chNext = styler.SafeGetCharAt(i + 1);
 
303
        style = styleNext;
 
304
        styleNext = styler.StyleAt(i + 1);
 
305
        bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');  //mac??
 
306
        if ((style & 31) == SCE_PS_PAREN_PROC) {
 
307
            if (ch == '{') {
 
308
                // Measure the minimum before a '{' to allow
 
309
                // folding on "} {"
 
310
                if (levelMinCurrent > levelNext) {
 
311
                    levelMinCurrent = levelNext;
 
312
                }
 
313
                levelNext++;
 
314
            } else if (ch == '}') {
 
315
                levelNext--;
 
316
            }
 
317
        }
 
318
        if (atEOL) {
 
319
            int levelUse = levelCurrent;
 
320
            if (foldAtElse) {
 
321
                levelUse = levelMinCurrent;
 
322
            }
 
323
            int lev = levelUse | levelNext << 16;
 
324
            if (visibleChars == 0 && foldCompact)
 
325
                lev |= SC_FOLDLEVELWHITEFLAG;
 
326
            if (levelUse < levelNext)
 
327
                lev |= SC_FOLDLEVELHEADERFLAG;
 
328
            if (lev != styler.LevelAt(lineCurrent)) {
 
329
                styler.SetLevel(lineCurrent, lev);
 
330
            }
 
331
            lineCurrent++;
 
332
            levelCurrent = levelNext;
 
333
            levelMinCurrent = levelCurrent;
 
334
            visibleChars = 0;
 
335
        }
 
336
        if (!isspacechar(ch))
 
337
            visibleChars++;
 
338
    }
 
339
}
 
340
 
 
341
static const char * const psWordListDesc[] = {
 
342
    "PS Level 1 operators",
 
343
    "PS Level 2 operators",
 
344
    "PS Level 3 operators",
 
345
    "RIP-specific operators",
 
346
    "User-defined operators",
 
347
    0
 
348
};
 
349
 
 
350
LexerModule lmPS(SCLEX_PS, ColourisePSDoc, "ps", FoldPSDoc, psWordListDesc);