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

« back to all changes in this revision

Viewing changes to src/stc/scintilla/src/LexMSSQL.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 LexMSSQL.cxx
 
3
 ** Lexer for MSSQL.
 
4
 **/
 
5
// By Filip Yaghob <fyaghob@gmail.com>
 
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 <ctype.h>
 
11
#include <stdio.h>
 
12
#include <stdarg.h>
 
13
 
 
14
#include "Platform.h"
 
15
 
 
16
#include "PropSet.h"
 
17
#include "Accessor.h"
 
18
#include "KeyWords.h"
 
19
#include "Scintilla.h"
 
20
#include "SciLexer.h"
 
21
 
 
22
#ifdef SCI_NAMESPACE
 
23
using namespace Scintilla;
 
24
#endif
 
25
 
 
26
#define KW_MSSQL_STATEMENTS         0
 
27
#define KW_MSSQL_DATA_TYPES         1
 
28
#define KW_MSSQL_SYSTEM_TABLES      2
 
29
#define KW_MSSQL_GLOBAL_VARIABLES   3
 
30
#define KW_MSSQL_FUNCTIONS          4
 
31
#define KW_MSSQL_STORED_PROCEDURES  5
 
32
#define KW_MSSQL_OPERATORS          6
 
33
 
 
34
static bool isMSSQLOperator(char ch) {
 
35
        if (isascii(ch) && isalnum(ch))
 
36
                return false;
 
37
        // '.' left out as it is used to make up numbers
 
38
        if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
 
39
        ch == '-' || ch == '+' || ch == '=' || ch == '|' ||
 
40
        ch == '<' || ch == '>' || ch == '/' ||
 
41
        ch == '!' || ch == '~' || ch == '(' || ch == ')' ||
 
42
                ch == ',')
 
43
                return true;
 
44
        return false;
 
45
}
 
46
 
 
47
static char classifyWordSQL(unsigned int start,
 
48
                            unsigned int end,
 
49
                            WordList *keywordlists[],
 
50
                            Accessor &styler,
 
51
                            unsigned int actualState,
 
52
                                                        unsigned int prevState) {
 
53
        char s[256];
 
54
        bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
 
55
 
 
56
        WordList &kwStatements          = *keywordlists[KW_MSSQL_STATEMENTS];
 
57
    WordList &kwDataTypes           = *keywordlists[KW_MSSQL_DATA_TYPES];
 
58
    WordList &kwSystemTables        = *keywordlists[KW_MSSQL_SYSTEM_TABLES];
 
59
    WordList &kwGlobalVariables     = *keywordlists[KW_MSSQL_GLOBAL_VARIABLES];
 
60
    WordList &kwFunctions           = *keywordlists[KW_MSSQL_FUNCTIONS];
 
61
    WordList &kwStoredProcedures    = *keywordlists[KW_MSSQL_STORED_PROCEDURES];
 
62
    WordList &kwOperators           = *keywordlists[KW_MSSQL_OPERATORS];
 
63
 
 
64
        for (unsigned int i = 0; i < end - start + 1 && i < 128; i++) {
 
65
                s[i] = static_cast<char>(tolower(styler[start + i]));
 
66
                s[i + 1] = '\0';
 
67
        }
 
68
        char chAttr = SCE_MSSQL_IDENTIFIER;
 
69
 
 
70
        if (actualState == SCE_MSSQL_GLOBAL_VARIABLE) {
 
71
 
 
72
        if (kwGlobalVariables.InList(&s[2]))
 
73
            chAttr = SCE_MSSQL_GLOBAL_VARIABLE;
 
74
 
 
75
        } else if (wordIsNumber) {
 
76
                chAttr = SCE_MSSQL_NUMBER;
 
77
 
 
78
        } else if (prevState == SCE_MSSQL_DEFAULT_PREF_DATATYPE) {
 
79
                // Look first in datatypes
 
80
        if (kwDataTypes.InList(s))
 
81
            chAttr = SCE_MSSQL_DATATYPE;
 
82
                else if (kwOperators.InList(s))
 
83
                        chAttr = SCE_MSSQL_OPERATOR;
 
84
                else if (kwStatements.InList(s))
 
85
                        chAttr = SCE_MSSQL_STATEMENT;
 
86
                else if (kwSystemTables.InList(s))
 
87
                        chAttr = SCE_MSSQL_SYSTABLE;
 
88
                else if (kwFunctions.InList(s))
 
89
            chAttr = SCE_MSSQL_FUNCTION;
 
90
                else if (kwStoredProcedures.InList(s))
 
91
                        chAttr = SCE_MSSQL_STORED_PROCEDURE;
 
92
 
 
93
        } else {
 
94
                if (kwOperators.InList(s))
 
95
                        chAttr = SCE_MSSQL_OPERATOR;
 
96
                else if (kwStatements.InList(s))
 
97
                        chAttr = SCE_MSSQL_STATEMENT;
 
98
                else if (kwSystemTables.InList(s))
 
99
                        chAttr = SCE_MSSQL_SYSTABLE;
 
100
                else if (kwFunctions.InList(s))
 
101
                        chAttr = SCE_MSSQL_FUNCTION;
 
102
                else if (kwStoredProcedures.InList(s))
 
103
                        chAttr = SCE_MSSQL_STORED_PROCEDURE;
 
104
                else if (kwDataTypes.InList(s))
 
105
                        chAttr = SCE_MSSQL_DATATYPE;
 
106
        }
 
107
 
 
108
        styler.ColourTo(end, chAttr);
 
109
 
 
110
        return chAttr;
 
111
}
 
112
 
 
113
static void ColouriseMSSQLDoc(unsigned int startPos, int length,
 
114
                              int initStyle, WordList *keywordlists[], Accessor &styler) {
 
115
 
 
116
 
 
117
        styler.StartAt(startPos);
 
118
 
 
119
        bool fold = styler.GetPropertyInt("fold") != 0;
 
120
        int lineCurrent = styler.GetLine(startPos);
 
121
        int spaceFlags = 0;
 
122
 
 
123
        int state = initStyle;
 
124
        int prevState = initStyle;
 
125
        char chPrev = ' ';
 
126
        char chNext = styler[startPos];
 
127
        styler.StartSegment(startPos);
 
128
        unsigned int lengthDoc = startPos + length;
 
129
        for (unsigned int i = startPos; i < lengthDoc; i++) {
 
130
                char ch = chNext;
 
131
                chNext = styler.SafeGetCharAt(i + 1);
 
132
 
 
133
                if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
 
134
                        int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags);
 
135
                        int lev = indentCurrent;
 
136
                        if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
 
137
                                // Only non whitespace lines can be headers
 
138
                                int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags);
 
139
                                if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) {
 
140
                                        lev |= SC_FOLDLEVELHEADERFLAG;
 
141
                                }
 
142
                        }
 
143
                        if (fold) {
 
144
                                styler.SetLevel(lineCurrent, lev);
 
145
                        }
 
146
                }
 
147
 
 
148
                if (styler.IsLeadByte(ch)) {
 
149
                        chNext = styler.SafeGetCharAt(i + 2);
 
150
                        chPrev = ' ';
 
151
                        i += 1;
 
152
                        continue;
 
153
                }
 
154
 
 
155
                // When the last char isn't part of the state (have to deal with it too)...
 
156
                if ( (state == SCE_MSSQL_IDENTIFIER) ||
 
157
                    (state == SCE_MSSQL_STORED_PROCEDURE) ||
 
158
                    (state == SCE_MSSQL_DATATYPE) ||
 
159
                    //~ (state == SCE_MSSQL_COLUMN_NAME) ||
 
160
                    (state == SCE_MSSQL_FUNCTION) ||
 
161
                    //~ (state == SCE_MSSQL_GLOBAL_VARIABLE) ||
 
162
                    (state == SCE_MSSQL_VARIABLE)) {
 
163
                        if (!iswordchar(ch)) {
 
164
                                int stateTmp;
 
165
 
 
166
                if ((state == SCE_MSSQL_VARIABLE) || (state == SCE_MSSQL_COLUMN_NAME)) {
 
167
                    styler.ColourTo(i - 1, state);
 
168
                                        stateTmp = state;
 
169
                } else
 
170
                    stateTmp = classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState);
 
171
 
 
172
                                prevState = state;
 
173
 
 
174
                                if (stateTmp == SCE_MSSQL_IDENTIFIER || stateTmp == SCE_MSSQL_VARIABLE)
 
175
                                        state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
 
176
                                else
 
177
                                        state = SCE_MSSQL_DEFAULT;
 
178
                        }
 
179
                } else if (state == SCE_MSSQL_LINE_COMMENT) {
 
180
                        if (ch == '\r' || ch == '\n') {
 
181
                                styler.ColourTo(i - 1, state);
 
182
                                prevState = state;
 
183
                                state = SCE_MSSQL_DEFAULT;
 
184
                        }
 
185
                } else if (state == SCE_MSSQL_GLOBAL_VARIABLE) {
 
186
                        if ((ch != '@') && !iswordchar(ch)) {
 
187
                                classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState);
 
188
                                prevState = state;
 
189
                                state = SCE_MSSQL_DEFAULT;
 
190
                        }
 
191
                }
 
192
 
 
193
                // If is the default or one of the above succeeded
 
194
                if (state == SCE_MSSQL_DEFAULT || state == SCE_MSSQL_DEFAULT_PREF_DATATYPE) {
 
195
                        if (iswordstart(ch)) {
 
196
                                styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
 
197
                                prevState = state;
 
198
                                state = SCE_MSSQL_IDENTIFIER;
 
199
                        } else if (ch == '/' && chNext == '*') {
 
200
                                styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
 
201
                                prevState = state;
 
202
                                state = SCE_MSSQL_COMMENT;
 
203
                        } else if (ch == '-' && chNext == '-') {
 
204
                                styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
 
205
                                prevState = state;
 
206
                                state = SCE_MSSQL_LINE_COMMENT;
 
207
                        } else if (ch == '\'') {
 
208
                                styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
 
209
                                prevState = state;
 
210
                                state = SCE_MSSQL_STRING;
 
211
                        } else if (ch == '"') {
 
212
                                styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
 
213
                                prevState = state;
 
214
                                state = SCE_MSSQL_COLUMN_NAME;
 
215
                        } else if (ch == '[') {
 
216
                                styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
 
217
                                prevState = state;
 
218
                                state = SCE_MSSQL_COLUMN_NAME_2;
 
219
                        } else if (isMSSQLOperator(ch)) {
 
220
                                styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
 
221
                                styler.ColourTo(i, SCE_MSSQL_OPERATOR);
 
222
                //~ style = SCE_MSSQL_DEFAULT;
 
223
                                prevState = state;
 
224
                                state = SCE_MSSQL_DEFAULT;
 
225
                        } else if (ch == '@') {
 
226
                styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
 
227
                                prevState = state;
 
228
                if (chNext == '@') {
 
229
                    state = SCE_MSSQL_GLOBAL_VARIABLE;
 
230
//                    i += 2;
 
231
                } else
 
232
                    state = SCE_MSSQL_VARIABLE;
 
233
            }
 
234
 
 
235
 
 
236
                // When the last char is part of the state...
 
237
                } else if (state == SCE_MSSQL_COMMENT) {
 
238
                                if (ch == '/' && chPrev == '*') {
 
239
                                        if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_MSSQL_COMMENT) &&
 
240
                                            (styler.GetStartSegment() == startPos)))) {
 
241
                                                styler.ColourTo(i, state);
 
242
                                                //~ state = SCE_MSSQL_COMMENT;
 
243
                                        prevState = state;
 
244
                        state = SCE_MSSQL_DEFAULT;
 
245
                                        }
 
246
                                }
 
247
                        } else if (state == SCE_MSSQL_STRING) {
 
248
                                if (ch == '\'') {
 
249
                                        if ( chNext == '\'' ) {
 
250
                                                i++;
 
251
                                        ch = chNext;
 
252
                                        chNext = styler.SafeGetCharAt(i + 1);
 
253
                                        } else {
 
254
                                                styler.ColourTo(i, state);
 
255
                                        prevState = state;
 
256
                                                state = SCE_MSSQL_DEFAULT;
 
257
                                        //i++;
 
258
                                        }
 
259
                                //ch = chNext;
 
260
                                //chNext = styler.SafeGetCharAt(i + 1);
 
261
                                }
 
262
                        } else if (state == SCE_MSSQL_COLUMN_NAME) {
 
263
                                if (ch == '"') {
 
264
                                        if (chNext == '"') {
 
265
                                                i++;
 
266
                                        ch = chNext;
 
267
                                        chNext = styler.SafeGetCharAt(i + 1);
 
268
                                } else {
 
269
                    styler.ColourTo(i, state);
 
270
                                        prevState = state;
 
271
                                        state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
 
272
                                        //i++;
 
273
                }
 
274
                }
 
275
                } else if (state == SCE_MSSQL_COLUMN_NAME_2) {
 
276
                        if (ch == ']') {
 
277
                styler.ColourTo(i, state);
 
278
                                prevState = state;
 
279
                state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
 
280
                //i++;
 
281
                        }
 
282
                }
 
283
 
 
284
                chPrev = ch;
 
285
        }
 
286
        styler.ColourTo(lengthDoc - 1, state);
 
287
}
 
288
 
 
289
static void FoldMSSQLDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
 
290
        bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
 
291
        bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
 
292
        unsigned int endPos = startPos + length;
 
293
        int visibleChars = 0;
 
294
        int lineCurrent = styler.GetLine(startPos);
 
295
        int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
 
296
        int levelCurrent = levelPrev;
 
297
        char chNext = styler[startPos];
 
298
        bool inComment = (styler.StyleAt(startPos-1) == SCE_MSSQL_COMMENT);
 
299
    char s[10];
 
300
        for (unsigned int i = startPos; i < endPos; i++) {
 
301
                char ch = chNext;
 
302
                chNext = styler.SafeGetCharAt(i + 1);
 
303
                int style = styler.StyleAt(i);
 
304
                bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
 
305
        // Comment folding
 
306
                if (foldComment) {
 
307
                        if (!inComment && (style == SCE_MSSQL_COMMENT))
 
308
                                levelCurrent++;
 
309
                        else if (inComment && (style != SCE_MSSQL_COMMENT))
 
310
                                levelCurrent--;
 
311
                        inComment = (style == SCE_MSSQL_COMMENT);
 
312
                }
 
313
        if (style == SCE_MSSQL_STATEMENT) {
 
314
            // Folding between begin or case and end
 
315
            if (ch == 'b' || ch == 'B' || ch == 'c' || ch == 'C' || ch == 'e' || ch == 'E') {
 
316
                for (unsigned int j = 0; j < 5; j++) {
 
317
                                        if (!iswordchar(styler[i + j])) {
 
318
                                                break;
 
319
                                        }
 
320
                                        s[j] = static_cast<char>(tolower(styler[i + j]));
 
321
                                        s[j + 1] = '\0';
 
322
                }
 
323
                                if ((strcmp(s, "begin") == 0) || (strcmp(s, "case") == 0)) {
 
324
                                        levelCurrent++;
 
325
                                }
 
326
                                if (strcmp(s, "end") == 0) {
 
327
                                        levelCurrent--;
 
328
                                }
 
329
            }
 
330
        }
 
331
                if (atEOL) {
 
332
                        int lev = levelPrev;
 
333
                        if (visibleChars == 0 && foldCompact)
 
334
                                lev |= SC_FOLDLEVELWHITEFLAG;
 
335
                        if ((levelCurrent > levelPrev) && (visibleChars > 0))
 
336
                                lev |= SC_FOLDLEVELHEADERFLAG;
 
337
                        if (lev != styler.LevelAt(lineCurrent)) {
 
338
                                styler.SetLevel(lineCurrent, lev);
 
339
                        }
 
340
                        lineCurrent++;
 
341
                        levelPrev = levelCurrent;
 
342
                        visibleChars = 0;
 
343
                }
 
344
                if (!isspacechar(ch))
 
345
                        visibleChars++;
 
346
        }
 
347
        // Fill in the real level of the next line, keeping the current flags as they will be filled in later
 
348
        int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
 
349
        styler.SetLevel(lineCurrent, levelPrev | flagsNext);
 
350
}
 
351
 
 
352
static const char * const sqlWordListDesc[] = {
 
353
        "Statements",
 
354
    "Data Types",
 
355
    "System tables",
 
356
    "Global variables",
 
357
    "Functions",
 
358
    "System Stored Procedures",
 
359
    "Operators",
 
360
        0,
 
361
};
 
362
 
 
363
LexerModule lmMSSQL(SCLEX_MSSQL, ColouriseMSSQLDoc, "mssql", FoldMSSQLDoc, sqlWordListDesc);