~ubuntu-branches/ubuntu/wily/tora/wily-proposed

« back to all changes in this revision

Viewing changes to src/qscintilla2/src/LexPOV.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Meskes
  • Date: 2009-11-19 15:18:19 UTC
  • mfrom: (1.2.9 upstream) (3.3.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091119151819-me89ezmxzkvl0lws
Tags: 2.1.1-1
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Scintilla source code edit control
 
2
/** @file LexPOV.cxx
 
3
 ** Lexer for POV-Ray SDL (Persistance of Vision Raytracer, Scene Description Language).
 
4
 ** Written by Philippe Lhoste but this is mostly a derivative of LexCPP...
 
5
 **/
 
6
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 
7
// The License.txt file describes the conditions under which this software may be distributed.
 
8
 
 
9
// Some points that distinguish from a simple C lexer:
 
10
// Identifiers start only by a character.
 
11
// No line continuation character.
 
12
// Strings are limited to 256 characters.
 
13
// Directives are similar to preprocessor commands,
 
14
// but we match directive keywords and colorize incorrect ones.
 
15
// Block comments can be nested (code stolen from my code in LexLua).
 
16
 
 
17
#include <stdlib.h>
 
18
#include <string.h>
 
19
#include <ctype.h>
 
20
#include <stdio.h>
 
21
#include <stdarg.h>
 
22
 
 
23
#include "Platform.h"
 
24
 
 
25
#include "PropSet.h"
 
26
#include "Accessor.h"
 
27
#include "StyleContext.h"
 
28
#include "KeyWords.h"
 
29
#include "Scintilla.h"
 
30
#include "SciLexer.h"
 
31
 
 
32
#ifdef SCI_NAMESPACE
 
33
using namespace Scintilla;
 
34
#endif
 
35
 
 
36
static inline bool IsAWordChar(int ch) {
 
37
        return ch < 0x80 && (isalnum(ch) || ch == '_');
 
38
}
 
39
 
 
40
static inline bool IsAWordStart(int ch) {
 
41
        return ch < 0x80 && isalpha(ch);
 
42
}
 
43
 
 
44
static inline bool IsANumberChar(int ch) {
 
45
        // Not exactly following number definition (several dots are seen as OK, etc.)
 
46
        // but probably enough in most cases.
 
47
        return (ch < 0x80) &&
 
48
                (isdigit(ch) || toupper(ch) == 'E' ||
 
49
             ch == '.' || ch == '-' || ch == '+');
 
50
}
 
51
 
 
52
static void ColourisePovDoc(
 
53
        unsigned int startPos,
 
54
        int length,
 
55
        int initStyle,
 
56
        WordList *keywordlists[],
 
57
    Accessor &styler) {
 
58
 
 
59
        WordList &keywords1 = *keywordlists[0];
 
60
        WordList &keywords2 = *keywordlists[1];
 
61
        WordList &keywords3 = *keywordlists[2];
 
62
        WordList &keywords4 = *keywordlists[3];
 
63
        WordList &keywords5 = *keywordlists[4];
 
64
        WordList &keywords6 = *keywordlists[5];
 
65
        WordList &keywords7 = *keywordlists[6];
 
66
        WordList &keywords8 = *keywordlists[7];
 
67
 
 
68
        int currentLine = styler.GetLine(startPos);
 
69
        // Initialize the block comment /* */ nesting level, if we are inside such a comment.
 
70
        int blockCommentLevel = 0;
 
71
        if (initStyle == SCE_POV_COMMENT) {
 
72
                blockCommentLevel = styler.GetLineState(currentLine - 1);
 
73
        }
 
74
 
 
75
        // Do not leak onto next line
 
76
        if (initStyle == SCE_POV_STRINGEOL || initStyle == SCE_POV_COMMENTLINE) {
 
77
                initStyle = SCE_POV_DEFAULT;
 
78
        }
 
79
 
 
80
        short stringLen = 0;
 
81
 
 
82
        StyleContext sc(startPos, length, initStyle, styler);
 
83
 
 
84
        for (; sc.More(); sc.Forward()) {
 
85
                if (sc.atLineEnd) {
 
86
                        // Update the line state, so it can be seen by next line
 
87
                        currentLine = styler.GetLine(sc.currentPos);
 
88
                        if (sc.state == SCE_POV_COMMENT) {
 
89
                                // Inside a block comment, we set the line state
 
90
                                styler.SetLineState(currentLine, blockCommentLevel);
 
91
                        } else {
 
92
                                // Reset the line state
 
93
                                styler.SetLineState(currentLine, 0);
 
94
                        }
 
95
                }
 
96
 
 
97
                if (sc.atLineStart && (sc.state == SCE_POV_STRING)) {
 
98
                        // Prevent SCE_POV_STRINGEOL from leaking back to previous line
 
99
                        sc.SetState(SCE_POV_STRING);
 
100
                }
 
101
 
 
102
                // Determine if the current state should terminate.
 
103
                if (sc.state == SCE_POV_OPERATOR) {
 
104
                        sc.SetState(SCE_POV_DEFAULT);
 
105
                } else if (sc.state == SCE_POV_NUMBER) {
 
106
                        // We stop the number definition on non-numerical non-dot non-eE non-sign char
 
107
                        if (!IsANumberChar(sc.ch)) {
 
108
                                sc.SetState(SCE_POV_DEFAULT);
 
109
                        }
 
110
                } else if (sc.state == SCE_POV_IDENTIFIER) {
 
111
                        if (!IsAWordChar(sc.ch)) {
 
112
                                char s[100];
 
113
                                sc.GetCurrent(s, sizeof(s));
 
114
                                if (keywords2.InList(s)) {
 
115
                                        sc.ChangeState(SCE_POV_WORD2);
 
116
                                } else if (keywords3.InList(s)) {
 
117
                                        sc.ChangeState(SCE_POV_WORD3);
 
118
                                } else if (keywords4.InList(s)) {
 
119
                                        sc.ChangeState(SCE_POV_WORD4);
 
120
                                } else if (keywords5.InList(s)) {
 
121
                                        sc.ChangeState(SCE_POV_WORD5);
 
122
                                } else if (keywords6.InList(s)) {
 
123
                                        sc.ChangeState(SCE_POV_WORD6);
 
124
                                } else if (keywords7.InList(s)) {
 
125
                                        sc.ChangeState(SCE_POV_WORD7);
 
126
                                } else if (keywords8.InList(s)) {
 
127
                                        sc.ChangeState(SCE_POV_WORD8);
 
128
                                }
 
129
                                sc.SetState(SCE_POV_DEFAULT);
 
130
                        }
 
131
                } else if (sc.state == SCE_POV_DIRECTIVE) {
 
132
                        if (!IsAWordChar(sc.ch)) {
 
133
                                char s[100];
 
134
                                char *p;
 
135
                                sc.GetCurrent(s, sizeof(s));
 
136
                                p = s;
 
137
                                // Skip # and whitespace between # and directive word
 
138
                                do {
 
139
                                        p++;
 
140
                                } while ((*p == ' ' || *p == '\t') && *p != '\0');
 
141
                                if (!keywords1.InList(p)) {
 
142
                                        sc.ChangeState(SCE_POV_BADDIRECTIVE);
 
143
                                }
 
144
                                sc.SetState(SCE_POV_DEFAULT);
 
145
                        }
 
146
                } else if (sc.state == SCE_POV_COMMENT) {
 
147
                        if (sc.Match('/', '*')) {
 
148
                                blockCommentLevel++;
 
149
                                sc.Forward();
 
150
                        } else if (sc.Match('*', '/') && blockCommentLevel > 0) {
 
151
                                blockCommentLevel--;
 
152
                                sc.Forward();
 
153
                                if (blockCommentLevel == 0) {
 
154
                                        sc.ForwardSetState(SCE_POV_DEFAULT);
 
155
                                }
 
156
                        }
 
157
                } else if (sc.state == SCE_POV_COMMENTLINE) {
 
158
                        if (sc.atLineEnd) {
 
159
                                sc.ForwardSetState(SCE_POV_DEFAULT);
 
160
                        }
 
161
                } else if (sc.state == SCE_POV_STRING) {
 
162
                        if (sc.ch == '\\') {
 
163
                                stringLen++;
 
164
                                if (strchr("abfnrtuv0'\"", sc.chNext)) {
 
165
                                        // Compound characters are counted as one.
 
166
                                        // Note: for Unicode chars \u, we shouldn't count the next 4 digits...
 
167
                                        sc.Forward();
 
168
                                }
 
169
                        } else if (sc.ch == '\"') {
 
170
                                sc.ForwardSetState(SCE_POV_DEFAULT);
 
171
                        } else if (sc.atLineEnd) {
 
172
                                sc.ChangeState(SCE_POV_STRINGEOL);
 
173
                                sc.ForwardSetState(SCE_POV_DEFAULT);
 
174
                        } else {
 
175
                                stringLen++;
 
176
                        }
 
177
                        if (stringLen > 256) {
 
178
                                // Strings are limited to 256 chars
 
179
                                sc.SetState(SCE_POV_STRINGEOL);
 
180
                        }
 
181
                } else if (sc.state == SCE_POV_STRINGEOL) {
 
182
                        if (sc.ch == '\\') {
 
183
                                if (sc.chNext == '\"' || sc.chNext == '\\') {
 
184
                                        sc.Forward();
 
185
                                }
 
186
                        } else if (sc.ch == '\"') {
 
187
                                sc.ForwardSetState(SCE_C_DEFAULT);
 
188
                        } else if (sc.atLineEnd) {
 
189
                                sc.ForwardSetState(SCE_POV_DEFAULT);
 
190
                        }
 
191
                }
 
192
 
 
193
                // Determine if a new state should be entered.
 
194
                if (sc.state == SCE_POV_DEFAULT) {
 
195
                        if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
 
196
                                sc.SetState(SCE_POV_NUMBER);
 
197
                        } else if (IsAWordStart(sc.ch)) {
 
198
                                sc.SetState(SCE_POV_IDENTIFIER);
 
199
                        } else if (sc.Match('/', '*')) {
 
200
                                blockCommentLevel = 1;
 
201
                                sc.SetState(SCE_POV_COMMENT);
 
202
                                sc.Forward();   // Eat the * so it isn't used for the end of the comment
 
203
                        } else if (sc.Match('/', '/')) {
 
204
                                sc.SetState(SCE_POV_COMMENTLINE);
 
205
                        } else if (sc.ch == '\"') {
 
206
                                sc.SetState(SCE_POV_STRING);
 
207
                                stringLen = 0;
 
208
                        } else if (sc.ch == '#') {
 
209
                                sc.SetState(SCE_POV_DIRECTIVE);
 
210
                                // Skip whitespace between # and directive word
 
211
                                do {
 
212
                                        sc.Forward();
 
213
                                } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
 
214
                                if (sc.atLineEnd) {
 
215
                                        sc.SetState(SCE_POV_DEFAULT);
 
216
                                }
 
217
                        } else if (isoperator(static_cast<char>(sc.ch))) {
 
218
                                sc.SetState(SCE_POV_OPERATOR);
 
219
                        }
 
220
                }
 
221
        }
 
222
        sc.Complete();
 
223
}
 
224
 
 
225
static void FoldPovDoc(
 
226
        unsigned int startPos,
 
227
        int length,
 
228
        int initStyle,
 
229
        WordList *[],
 
230
        Accessor &styler) {
 
231
 
 
232
        bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
 
233
        bool foldDirective = styler.GetPropertyInt("fold.directive") != 0;
 
234
        bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
 
235
        unsigned int endPos = startPos + length;
 
236
        int visibleChars = 0;
 
237
        int lineCurrent = styler.GetLine(startPos);
 
238
        int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
 
239
        int levelCurrent = levelPrev;
 
240
        char chNext = styler[startPos];
 
241
        int styleNext = styler.StyleAt(startPos);
 
242
        int style = initStyle;
 
243
        for (unsigned int i = startPos; i < endPos; i++) {
 
244
                char ch = chNext;
 
245
                chNext = styler.SafeGetCharAt(i + 1);
 
246
                int stylePrev = style;
 
247
                style = styleNext;
 
248
                styleNext = styler.StyleAt(i + 1);
 
249
                bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
 
250
                if (foldComment && (style == SCE_POV_COMMENT)) {
 
251
                        if (stylePrev != SCE_POV_COMMENT) {
 
252
                                levelCurrent++;
 
253
                        } else if ((styleNext != SCE_POV_COMMENT) && !atEOL) {
 
254
                                // Comments don't end at end of line and the next character may be unstyled.
 
255
                                levelCurrent--;
 
256
                        }
 
257
                }
 
258
                if (foldComment && (style == SCE_POV_COMMENTLINE)) {
 
259
                        if ((ch == '/') && (chNext == '/')) {
 
260
                                char chNext2 = styler.SafeGetCharAt(i + 2);
 
261
                                if (chNext2 == '{') {
 
262
                                        levelCurrent++;
 
263
                                } else if (chNext2 == '}') {
 
264
                                        levelCurrent--;
 
265
                                }
 
266
                        }
 
267
                }
 
268
                if (foldDirective && (style == SCE_POV_DIRECTIVE)) {
 
269
                        if (ch == '#') {
 
270
                                unsigned int j=i+1;
 
271
                                while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
 
272
                                        j++;
 
273
                                }
 
274
                        }
 
275
                }
 
276
                if (style == SCE_POV_OPERATOR) {
 
277
                        if (ch == '{') {
 
278
                                levelCurrent++;
 
279
                        } else if (ch == '}') {
 
280
                                levelCurrent--;
 
281
                        }
 
282
                }
 
283
                if (atEOL) {
 
284
                        int lev = levelPrev;
 
285
                        if (visibleChars == 0 && foldCompact)
 
286
                                lev |= SC_FOLDLEVELWHITEFLAG;
 
287
                        if ((levelCurrent > levelPrev) && (visibleChars > 0))
 
288
                                lev |= SC_FOLDLEVELHEADERFLAG;
 
289
                        if (lev != styler.LevelAt(lineCurrent)) {
 
290
                                styler.SetLevel(lineCurrent, lev);
 
291
                        }
 
292
                        lineCurrent++;
 
293
                        levelPrev = levelCurrent;
 
294
                        visibleChars = 0;
 
295
                }
 
296
                if (!isspacechar(ch))
 
297
                        visibleChars++;
 
298
        }
 
299
        // Fill in the real level of the next line, keeping the current flags as they will be filled in later
 
300
        int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
 
301
        styler.SetLevel(lineCurrent, levelPrev | flagsNext);
 
302
}
 
303
 
 
304
static const char * const povWordLists[] = {
 
305
        "Language directives",
 
306
        "Objects & CSG & Appearance",
 
307
        "Types & Modifiers & Items",
 
308
        "Predefined Identifiers",
 
309
        "Predefined Functions",
 
310
        "User defined 1",
 
311
        "User defined 2",
 
312
        "User defined 3",
 
313
        0,
 
314
};
 
315
 
 
316
LexerModule lmPOV(SCLEX_POV, ColourisePovDoc, "pov", FoldPovDoc, povWordLists);