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

« back to all changes in this revision

Viewing changes to scintilla/LexD.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
 
/** @file LexD.cxx
2
 
 ** Lexer for D.
3
 
 **
4
 
 ** Copyright (c) 2006 by Waldemar Augustyn <waldemar@wdmsys.com>
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
 
#include <stdlib.h>
10
 
#include <string.h>
11
 
#include <ctype.h>
12
 
#include <stdio.h>
13
 
#include <stdarg.h>
14
 
 
15
 
#include "Platform.h"
16
 
 
17
 
#include "PropSet.h"
18
 
#include "Accessor.h"
19
 
#include "StyleContext.h"
20
 
#include "KeyWords.h"
21
 
#include "Scintilla.h"
22
 
#include "SciLexer.h"
23
 
 
24
 
#ifdef SCI_NAMESPACE
25
 
using namespace Scintilla;
26
 
#endif
27
 
 
28
 
/* Nested comments require keeping the value of the nesting level for every
29
 
   position in the document.  But since scintilla always styles line by line,
30
 
   we only need to store one value per line. The non-negative number indicates
31
 
   nesting level at the end of the line.
32
 
*/
33
 
 
34
 
// Underscore, letter, digit and universal alphas from C99 Appendix D.
35
 
 
36
 
static bool IsWordStart(int ch) {
37
 
        return (isascii(ch) && (isalpha(ch) || ch == '_')) || !isascii(ch);
38
 
}
39
 
 
40
 
static bool IsWord(int ch) {
41
 
        return (isascii(ch) && (isalnum(ch) || ch == '_')) || !isascii(ch);
42
 
}
43
 
 
44
 
static bool IsDoxygen(int ch) {
45
 
        if (isascii(ch) && islower(ch))
46
 
                return true;
47
 
        if (ch == '$' || ch == '@' || ch == '\\' ||
48
 
                ch == '&' || ch == '#' || ch == '<' || ch == '>' ||
49
 
                ch == '{' || ch == '}' || ch == '[' || ch == ']')
50
 
                return true;
51
 
        return false;
52
 
}
53
 
 
54
 
static bool IsStringSuffix(int ch) {
55
 
        return ch == 'c' || ch == 'w' || ch == 'd';
56
 
}
57
 
 
58
 
 
59
 
static void ColouriseDoc(unsigned int startPos, int length, int initStyle,
60
 
        WordList *keywordlists[], Accessor &styler, bool caseSensitive) {
61
 
 
62
 
        WordList &keywords  = *keywordlists[0];
63
 
        WordList &keywords2 = *keywordlists[1];
64
 
        WordList &keywords3 = *keywordlists[2]; //doxygen
65
 
        WordList &keywords4 = *keywordlists[3];
66
 
        WordList &keywords5 = *keywordlists[4];
67
 
        WordList &keywords6 = *keywordlists[5];
68
 
        WordList &keywords7 = *keywordlists[6];
69
 
 
70
 
        int styleBeforeDCKeyword = SCE_D_DEFAULT;
71
 
 
72
 
        StyleContext sc(startPos, length, initStyle, styler);
73
 
 
74
 
        int curLine = styler.GetLine(startPos);
75
 
        int curNcLevel = curLine > 0? styler.GetLineState(curLine-1): 0;
76
 
        bool numFloat = false; // Float literals have '+' and '-' signs
77
 
        bool numHex = false;
78
 
 
79
 
        for (; sc.More(); sc.Forward()) {
80
 
 
81
 
                if (sc.atLineStart) {
82
 
                        curLine = styler.GetLine(sc.currentPos);
83
 
                        styler.SetLineState(curLine, curNcLevel);
84
 
                }
85
 
 
86
 
                // Determine if the current state should terminate.
87
 
                switch (sc.state) {
88
 
                        case SCE_D_OPERATOR:
89
 
                                sc.SetState(SCE_D_DEFAULT);
90
 
                                break;
91
 
                        case SCE_D_NUMBER:
92
 
                                // We accept almost anything because of hex. and number suffixes
93
 
                                if (isascii(sc.ch) && (isalnum(sc.ch) || sc.ch == '_')) {
94
 
                                        continue;
95
 
                                } else if (sc.ch == '.' && sc.chNext != '.' && !numFloat) {
96
 
                                        // Don't parse 0..2 as number.
97
 
                                        numFloat=true;
98
 
                                        continue;
99
 
                                } else if ( ( sc.ch == '-' || sc.ch == '+' ) && (               /*sign and*/
100
 
                                        ( !numHex && ( sc.chPrev == 'e' || sc.chPrev == 'E' ) ) || /*decimal or*/
101
 
                                        ( sc.chPrev == 'p' || sc.chPrev == 'P' ) ) ) {          /*hex*/
102
 
                                        // Parse exponent sign in float literals: 2e+10 0x2e+10
103
 
                                        continue;
104
 
                                } else {
105
 
                                        sc.SetState(SCE_D_DEFAULT);
106
 
                                }
107
 
                                break;
108
 
                        case SCE_D_IDENTIFIER:
109
 
                                if (!IsWord(sc.ch)) {
110
 
                                        char s[1000];
111
 
                                        if (caseSensitive) {
112
 
                                                sc.GetCurrent(s, sizeof(s));
113
 
                                        } else {
114
 
                                                sc.GetCurrentLowered(s, sizeof(s));
115
 
                                        }
116
 
                                        if (keywords.InList(s)) {
117
 
                                                sc.ChangeState(SCE_D_WORD);
118
 
                                        } else if (keywords2.InList(s)) {
119
 
                                                sc.ChangeState(SCE_D_WORD2);
120
 
                                        } else if (keywords4.InList(s)) {
121
 
                                                sc.ChangeState(SCE_D_TYPEDEF);
122
 
                                        } else if (keywords5.InList(s)) {
123
 
                                                sc.ChangeState(SCE_D_WORD5);
124
 
                                        } else if (keywords6.InList(s)) {
125
 
                                                sc.ChangeState(SCE_D_WORD6);
126
 
                                        } else if (keywords7.InList(s)) {
127
 
                                                sc.ChangeState(SCE_D_WORD7);
128
 
                                        }
129
 
                                        sc.SetState(SCE_D_DEFAULT);
130
 
                                }
131
 
                                break;
132
 
                        case SCE_D_COMMENT:
133
 
                                if (sc.Match('*', '/')) {
134
 
                                        sc.Forward();
135
 
                                        sc.ForwardSetState(SCE_D_DEFAULT);
136
 
                                }
137
 
                                break;
138
 
                        case SCE_D_COMMENTDOC:
139
 
                                if (sc.Match('*', '/')) {
140
 
                                        sc.Forward();
141
 
                                        sc.ForwardSetState(SCE_D_DEFAULT);
142
 
                                } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
143
 
                                        // Verify that we have the conditions to mark a comment-doc-keyword
144
 
                                        if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) {
145
 
                                                styleBeforeDCKeyword = SCE_D_COMMENTDOC;
146
 
                                                sc.SetState(SCE_D_COMMENTDOCKEYWORD);
147
 
                                        }
148
 
                                }
149
 
                                break;
150
 
                        case SCE_D_COMMENTLINE:
151
 
                                if (sc.atLineStart) {
152
 
                                        sc.SetState(SCE_D_DEFAULT);
153
 
                                }
154
 
                                break;
155
 
                        case SCE_D_COMMENTLINEDOC:
156
 
                                if (sc.atLineStart) {
157
 
                                        sc.SetState(SCE_D_DEFAULT);
158
 
                                } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
159
 
                                        // Verify that we have the conditions to mark a comment-doc-keyword
160
 
                                        if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) {
161
 
                                                styleBeforeDCKeyword = SCE_D_COMMENTLINEDOC;
162
 
                                                sc.SetState(SCE_D_COMMENTDOCKEYWORD);
163
 
                                        }
164
 
                                }
165
 
                                break;
166
 
                        case SCE_D_COMMENTDOCKEYWORD:
167
 
                                if ((styleBeforeDCKeyword == SCE_D_COMMENTDOC) && sc.Match('*', '/')) {
168
 
                                        sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR);
169
 
                                        sc.Forward();
170
 
                                        sc.ForwardSetState(SCE_D_DEFAULT);
171
 
                                } else if (!IsDoxygen(sc.ch)) {
172
 
                                        char s[100];
173
 
                                        if (caseSensitive) {
174
 
                                                sc.GetCurrent(s, sizeof(s));
175
 
                                        } else {
176
 
                                                sc.GetCurrentLowered(s, sizeof(s));
177
 
                                        }
178
 
                                        if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) {
179
 
                                                sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR);
180
 
                                        }
181
 
                                        sc.SetState(styleBeforeDCKeyword);
182
 
                                }
183
 
                                break;
184
 
                        case SCE_D_COMMENTNESTED:
185
 
                                if (sc.Match('+', '/')) {
186
 
                                        if (curNcLevel > 0)
187
 
                                                curNcLevel -= 1;
188
 
                                        curLine = styler.GetLine(sc.currentPos);
189
 
                                        styler.SetLineState(curLine, curNcLevel);
190
 
                                        sc.Forward();
191
 
                                        if (curNcLevel == 0) {
192
 
                                                sc.ForwardSetState(SCE_D_DEFAULT);
193
 
                                        }
194
 
                                } else if (sc.Match('/','+')) {
195
 
                                        curNcLevel += 1;
196
 
                                        curLine = styler.GetLine(sc.currentPos);
197
 
                                        styler.SetLineState(curLine, curNcLevel);
198
 
                                        sc.Forward();
199
 
                                }
200
 
                                break;
201
 
                        case SCE_D_STRING:
202
 
                                if (sc.ch == '\\') {
203
 
                                        if (sc.chNext == '"' || sc.chNext == '\\') {
204
 
                                                sc.Forward();
205
 
                                        }
206
 
                                } else if (sc.ch == '"') {
207
 
                                        if(IsStringSuffix(sc.chNext))
208
 
                                                sc.Forward();
209
 
                                        sc.ForwardSetState(SCE_D_DEFAULT);
210
 
                                }
211
 
                                break;
212
 
                        case SCE_D_CHARACTER:
213
 
                                if (sc.atLineEnd) {
214
 
                                        sc.ChangeState(SCE_D_STRINGEOL);
215
 
                                } else if (sc.ch == '\\') {
216
 
                                        if (sc.chNext == '\'' || sc.chNext == '\\') {
217
 
                                                sc.Forward();
218
 
                                        }
219
 
                                } else if (sc.ch == '\'') {
220
 
                                        // Char has no suffixes
221
 
                                        sc.ForwardSetState(SCE_D_DEFAULT);
222
 
                                }
223
 
                                break;
224
 
                        case SCE_D_STRINGEOL:
225
 
                                if (sc.atLineStart) {
226
 
                                        sc.SetState(SCE_D_DEFAULT);
227
 
                                }
228
 
                                break;
229
 
                        case SCE_D_STRINGB:
230
 
                                if (sc.ch == '`') {
231
 
                                        if(IsStringSuffix(sc.chNext))
232
 
                                                sc.Forward();
233
 
                                        sc.ForwardSetState(SCE_D_DEFAULT);
234
 
                                }
235
 
                                break;
236
 
                        case SCE_D_STRINGR:
237
 
                                if (sc.ch == '"') {
238
 
                                        if(IsStringSuffix(sc.chNext))
239
 
                                                sc.Forward();
240
 
                                        sc.ForwardSetState(SCE_D_DEFAULT);
241
 
                                }
242
 
                                break;
243
 
                }
244
 
 
245
 
                // Determine if a new state should be entered.
246
 
                if (sc.state == SCE_D_DEFAULT) {
247
 
                        if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
248
 
                                sc.SetState(SCE_D_NUMBER);
249
 
                                numFloat = sc.ch == '.';
250
 
                                // Remember hex literal
251
 
                                numHex = sc.ch == '0' && ( sc.chNext == 'x' || sc.chNext == 'X' );
252
 
                        } else if ( (sc.ch == 'r' || sc.ch == 'x' || sc.ch == 'q')
253
 
                                && sc.chNext == '"' ) {
254
 
                                // Limited support for hex and delimited strings: parse as r""
255
 
                                sc.SetState(SCE_D_STRINGR);
256
 
                                sc.Forward();
257
 
                        } else if (IsWordStart(sc.ch) || sc.ch == '$') {
258
 
                                sc.SetState(SCE_D_IDENTIFIER);
259
 
                        } else if (sc.Match('/','+')) {
260
 
                                curNcLevel += 1;
261
 
                                curLine = styler.GetLine(sc.currentPos);
262
 
                                styler.SetLineState(curLine, curNcLevel);
263
 
                                sc.SetState(SCE_D_COMMENTNESTED);
264
 
                                sc.Forward();
265
 
                        } else if (sc.Match('/', '*')) {
266
 
                                if (sc.Match("/**") || sc.Match("/*!")) {   // Support of Qt/Doxygen doc. style
267
 
                                        sc.SetState(SCE_D_COMMENTDOC);
268
 
                                } else {
269
 
                                        sc.SetState(SCE_D_COMMENT);
270
 
                                }
271
 
                                sc.Forward();   // Eat the * so it isn't used for the end of the comment
272
 
                        } else if (sc.Match('/', '/')) {
273
 
                                if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!"))
274
 
                                        // Support of Qt/Doxygen doc. style
275
 
                                        sc.SetState(SCE_D_COMMENTLINEDOC);
276
 
                                else
277
 
                                        sc.SetState(SCE_D_COMMENTLINE);
278
 
                        } else if (sc.ch == '"') {
279
 
                                sc.SetState(SCE_D_STRING);
280
 
                        } else if (sc.ch == '\'') {
281
 
                                sc.SetState(SCE_D_CHARACTER);
282
 
                        } else if (sc.ch == '`') {
283
 
                                sc.SetState(SCE_D_STRINGB);
284
 
                        } else if (isoperator(static_cast<char>(sc.ch))) {
285
 
                                sc.SetState(SCE_D_OPERATOR);
286
 
                                if (sc.ch == '.' && sc.chNext == '.') sc.Forward(); // Range operator
287
 
                        }
288
 
                }
289
 
        }
290
 
        sc.Complete();
291
 
}
292
 
 
293
 
static bool IsStreamCommentStyle(int style) {
294
 
        return style == SCE_D_COMMENT ||
295
 
                style == SCE_D_COMMENTDOC ||
296
 
                style == SCE_D_COMMENTDOCKEYWORD ||
297
 
                style == SCE_D_COMMENTDOCKEYWORDERROR;
298
 
}
299
 
 
300
 
// Store both the current line's fold level and the next lines in the
301
 
// level store to make it easy to pick up with each increment
302
 
// and to make it possible to fiddle the current level for "} else {".
303
 
static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor &styler) {
304
 
        bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
305
 
        bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
306
 
 
307
 
        // property lexer.d.fold.at.else
308
 
        //  This option enables D folding on a "} else {" line of an if statement.
309
 
        bool foldAtElse = styler.GetPropertyInt("lexer.d.fold.at.else",
310
 
                styler.GetPropertyInt("fold.at.else", 0)) != 0;
311
 
        unsigned int endPos = startPos + length;
312
 
        int visibleChars = 0;
313
 
        int lineCurrent = styler.GetLine(startPos);
314
 
        int levelCurrent = SC_FOLDLEVELBASE;
315
 
        if (lineCurrent > 0)
316
 
                levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
317
 
        int levelMinCurrent = levelCurrent;
318
 
        int levelNext = levelCurrent;
319
 
        char chNext = styler[startPos];
320
 
        int styleNext = styler.StyleAt(startPos);
321
 
        int style = initStyle;
322
 
        for (unsigned int i = startPos; i < endPos; i++) {
323
 
                char ch = chNext;
324
 
                chNext = styler.SafeGetCharAt(i + 1);
325
 
                int stylePrev = style;
326
 
                style = styleNext;
327
 
                styleNext = styler.StyleAt(i + 1);
328
 
                bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
329
 
                if (foldComment && IsStreamCommentStyle(style)) {
330
 
                        if (!IsStreamCommentStyle(stylePrev)) {
331
 
                                levelNext++;
332
 
                        } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
333
 
                                // Comments don't end at end of line and the next character may be unstyled.
334
 
                                levelNext--;
335
 
                        }
336
 
                }
337
 
                if (style == SCE_D_OPERATOR) {
338
 
                        if (ch == '{') {
339
 
                                // Measure the minimum before a '{' to allow
340
 
                                // folding on "} else {"
341
 
                                if (levelMinCurrent > levelNext) {
342
 
                                        levelMinCurrent = levelNext;
343
 
                                }
344
 
                                levelNext++;
345
 
                        } else if (ch == '}') {
346
 
                                levelNext--;
347
 
                        }
348
 
                }
349
 
                if (atEOL) {
350
 
                        if (foldComment) {  // Handle nested comments
351
 
                                int nc;
352
 
                                nc =  styler.GetLineState(lineCurrent);
353
 
                                nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0;
354
 
                                levelNext += nc;
355
 
                        }
356
 
                        int levelUse = levelCurrent;
357
 
                        if (foldAtElse) {
358
 
                                levelUse = levelMinCurrent;
359
 
                        }
360
 
                        int lev = levelUse | levelNext << 16;
361
 
                        if (visibleChars == 0 && foldCompact)
362
 
                                lev |= SC_FOLDLEVELWHITEFLAG;
363
 
                        if (levelUse < levelNext)
364
 
                                lev |= SC_FOLDLEVELHEADERFLAG;
365
 
                        if (lev != styler.LevelAt(lineCurrent)) {
366
 
                                styler.SetLevel(lineCurrent, lev);
367
 
                        }
368
 
                        lineCurrent++;
369
 
                        levelCurrent = levelNext;
370
 
                        levelMinCurrent = levelCurrent;
371
 
                        visibleChars = 0;
372
 
                }
373
 
                if (!IsASpace(ch))
374
 
                        visibleChars++;
375
 
        }
376
 
}
377
 
 
378
 
static void FoldDDoc(unsigned int startPos, int length, int initStyle,
379
 
        WordList *[], Accessor &styler) {
380
 
                FoldDoc(startPos, length, initStyle, styler);
381
 
}
382
 
 
383
 
static const char * const dWordLists[] = {
384
 
                        "Primary keywords and identifiers",
385
 
                        "Secondary keywords and identifiers",
386
 
                        "Documentation comment keywords",
387
 
                        "Type definitions and aliases",
388
 
                        "Keywords 5",
389
 
                        "Keywords 6",
390
 
                        "Keywords 7",
391
 
                        0,
392
 
                };
393
 
 
394
 
static void ColouriseDDoc(unsigned int startPos, int length,
395
 
        int initStyle, WordList *keywordlists[], Accessor &styler) {
396
 
                ColouriseDoc(startPos, length, initStyle, keywordlists, styler, true);
397
 
}
398
 
 
399
 
LexerModule lmD(SCLEX_D, ColouriseDDoc, "d", FoldDDoc, dWordLists);