~ubuntu-branches/ubuntu/wily/geany/wily

« back to all changes in this revision

Viewing changes to scintilla/LexAda.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
 
// Scintilla source code edit control
2
 
/** @file LexAda.cxx
3
 
 ** Lexer for Ada 95
4
 
 **/
5
 
// Copyright 2002 by Sergey Koshcheyev <sergey.k@seznam.cz>
6
 
// The License.txt file describes the conditions under which this software may be distributed.
7
 
 
8
 
#include <stdlib.h>
9
 
#include <ctype.h>
10
 
#include <string.h>
11
 
#include <stdio.h>
12
 
 
13
 
#include <string>
14
 
 
15
 
#include "Platform.h"
16
 
 
17
 
#include "Accessor.h"
18
 
#include "StyleContext.h"
19
 
#include "PropSet.h"
20
 
#include "KeyWords.h"
21
 
#include "SciLexer.h"
22
 
 
23
 
#ifdef SCI_NAMESPACE
24
 
using namespace Scintilla;
25
 
#endif
26
 
 
27
 
/*
28
 
 * Interface
29
 
 */
30
 
 
31
 
static void ColouriseDocument(
32
 
    unsigned int startPos,
33
 
    int length,
34
 
    int initStyle,
35
 
    WordList *keywordlists[],
36
 
    Accessor &styler);
37
 
 
38
 
static const char * const adaWordListDesc[] = {
39
 
        "Keywords",
40
 
        0
41
 
};
42
 
 
43
 
LexerModule lmAda(SCLEX_ADA, ColouriseDocument, "ada", NULL, adaWordListDesc);
44
 
 
45
 
/*
46
 
 * Implementation
47
 
 */
48
 
 
49
 
// Functions that have apostropheStartsAttribute as a parameter set it according to whether
50
 
// an apostrophe encountered after processing the current token will start an attribute or
51
 
// a character literal.
52
 
static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute);
53
 
static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute);
54
 
static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL);
55
 
static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute);
56
 
static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute);
57
 
static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute);
58
 
static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute);
59
 
static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute);
60
 
static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute);
61
 
 
62
 
static inline bool IsDelimiterCharacter(int ch);
63
 
static inline bool IsNumberStartCharacter(int ch);
64
 
static inline bool IsNumberCharacter(int ch);
65
 
static inline bool IsSeparatorOrDelimiterCharacter(int ch);
66
 
static bool IsValidIdentifier(const std::string& identifier);
67
 
static bool IsValidNumber(const std::string& number);
68
 
static inline bool IsWordStartCharacter(int ch);
69
 
static inline bool IsWordCharacter(int ch);
70
 
 
71
 
static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute) {
72
 
        apostropheStartsAttribute = true;
73
 
 
74
 
        sc.SetState(SCE_ADA_CHARACTER);
75
 
 
76
 
        // Skip the apostrophe and one more character (so that '' is shown as non-terminated and '''
77
 
        // is handled correctly)
78
 
        sc.Forward();
79
 
        sc.Forward();
80
 
 
81
 
        ColouriseContext(sc, '\'', SCE_ADA_CHARACTEREOL);
82
 
}
83
 
 
84
 
static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL) {
85
 
        while (!sc.atLineEnd && !sc.Match(chEnd)) {
86
 
                sc.Forward();
87
 
        }
88
 
 
89
 
        if (!sc.atLineEnd) {
90
 
                sc.ForwardSetState(SCE_ADA_DEFAULT);
91
 
        } else {
92
 
                sc.ChangeState(stateEOL);
93
 
        }
94
 
}
95
 
 
96
 
static void ColouriseComment(StyleContext& sc, bool& /*apostropheStartsAttribute*/) {
97
 
        // Apostrophe meaning is not changed, but the parameter is present for uniformity
98
 
 
99
 
        sc.SetState(SCE_ADA_COMMENTLINE);
100
 
 
101
 
        while (!sc.atLineEnd) {
102
 
                sc.Forward();
103
 
        }
104
 
}
105
 
 
106
 
static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) {
107
 
        apostropheStartsAttribute = sc.Match (')');
108
 
        sc.SetState(SCE_ADA_DELIMITER);
109
 
        sc.ForwardSetState(SCE_ADA_DEFAULT);
110
 
}
111
 
 
112
 
static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) {
113
 
        apostropheStartsAttribute = false;
114
 
 
115
 
        sc.SetState(SCE_ADA_LABEL);
116
 
 
117
 
        // Skip "<<"
118
 
        sc.Forward();
119
 
        sc.Forward();
120
 
 
121
 
        std::string identifier;
122
 
 
123
 
        while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {
124
 
                identifier += static_cast<char>(tolower(sc.ch));
125
 
                sc.Forward();
126
 
        }
127
 
 
128
 
        // Skip ">>"
129
 
        if (sc.Match('>', '>')) {
130
 
                sc.Forward();
131
 
                sc.Forward();
132
 
        } else {
133
 
                sc.ChangeState(SCE_ADA_ILLEGAL);
134
 
        }
135
 
 
136
 
        // If the name is an invalid identifier or a keyword, then make it invalid label
137
 
        if (!IsValidIdentifier(identifier) || keywords.InList(identifier.c_str())) {
138
 
                sc.ChangeState(SCE_ADA_ILLEGAL);
139
 
        }
140
 
 
141
 
        sc.SetState(SCE_ADA_DEFAULT);
142
 
 
143
 
}
144
 
 
145
 
static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) {
146
 
        apostropheStartsAttribute = true;
147
 
 
148
 
        std::string number;
149
 
        sc.SetState(SCE_ADA_NUMBER);
150
 
 
151
 
        // Get all characters up to a delimiter or a separator, including points, but excluding
152
 
        // double points (ranges).
153
 
        while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) {
154
 
                number += static_cast<char>(sc.ch);
155
 
                sc.Forward();
156
 
        }
157
 
 
158
 
        // Special case: exponent with sign
159
 
        if ((sc.chPrev == 'e' || sc.chPrev == 'E') &&
160
 
                (sc.ch == '+' || sc.ch == '-')) {
161
 
                number += static_cast<char>(sc.ch);
162
 
                sc.Forward ();
163
 
 
164
 
                while (!IsSeparatorOrDelimiterCharacter(sc.ch)) {
165
 
                        number += static_cast<char>(sc.ch);
166
 
                        sc.Forward();
167
 
                }
168
 
        }
169
 
 
170
 
        if (!IsValidNumber(number)) {
171
 
                sc.ChangeState(SCE_ADA_ILLEGAL);
172
 
        }
173
 
 
174
 
        sc.SetState(SCE_ADA_DEFAULT);
175
 
}
176
 
 
177
 
static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute) {
178
 
        apostropheStartsAttribute = true;
179
 
 
180
 
        sc.SetState(SCE_ADA_STRING);
181
 
        sc.Forward();
182
 
 
183
 
        ColouriseContext(sc, '"', SCE_ADA_STRINGEOL);
184
 
}
185
 
 
186
 
static void ColouriseWhiteSpace(StyleContext& sc, bool& /*apostropheStartsAttribute*/) {
187
 
        // Apostrophe meaning is not changed, but the parameter is present for uniformity
188
 
        sc.SetState(SCE_ADA_DEFAULT);
189
 
        sc.ForwardSetState(SCE_ADA_DEFAULT);
190
 
}
191
 
 
192
 
static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) {
193
 
        apostropheStartsAttribute = true;
194
 
        sc.SetState(SCE_ADA_IDENTIFIER);
195
 
 
196
 
        std::string word;
197
 
 
198
 
        while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {
199
 
                word += static_cast<char>(tolower(sc.ch));
200
 
                sc.Forward();
201
 
        }
202
 
 
203
 
        if (!IsValidIdentifier(word)) {
204
 
                sc.ChangeState(SCE_ADA_ILLEGAL);
205
 
 
206
 
        } else if (keywords.InList(word.c_str())) {
207
 
                sc.ChangeState(SCE_ADA_WORD);
208
 
 
209
 
                if (word != "all") {
210
 
                        apostropheStartsAttribute = false;
211
 
                }
212
 
        }
213
 
 
214
 
        sc.SetState(SCE_ADA_DEFAULT);
215
 
}
216
 
 
217
 
//
218
 
// ColouriseDocument
219
 
//
220
 
 
221
 
static void ColouriseDocument(
222
 
    unsigned int startPos,
223
 
    int length,
224
 
    int initStyle,
225
 
    WordList *keywordlists[],
226
 
    Accessor &styler) {
227
 
        WordList &keywords = *keywordlists[0];
228
 
 
229
 
        StyleContext sc(startPos, length, initStyle, styler);
230
 
 
231
 
        int lineCurrent = styler.GetLine(startPos);
232
 
        bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0;
233
 
 
234
 
        while (sc.More()) {
235
 
                if (sc.atLineEnd) {
236
 
                        // Go to the next line
237
 
                        sc.Forward();
238
 
                        lineCurrent++;
239
 
 
240
 
                        // Remember the line state for future incremental lexing
241
 
                        styler.SetLineState(lineCurrent, apostropheStartsAttribute);
242
 
 
243
 
                        // Don't continue any styles on the next line
244
 
                        sc.SetState(SCE_ADA_DEFAULT);
245
 
                }
246
 
 
247
 
                // Comments
248
 
                if (sc.Match('-', '-')) {
249
 
                        ColouriseComment(sc, apostropheStartsAttribute);
250
 
 
251
 
                // Strings
252
 
                } else if (sc.Match('"')) {
253
 
                        ColouriseString(sc, apostropheStartsAttribute);
254
 
 
255
 
                // Characters
256
 
                } else if (sc.Match('\'') && !apostropheStartsAttribute) {
257
 
                        ColouriseCharacter(sc, apostropheStartsAttribute);
258
 
 
259
 
                // Labels
260
 
                } else if (sc.Match('<', '<')) {
261
 
                        ColouriseLabel(sc, keywords, apostropheStartsAttribute);
262
 
 
263
 
                // Whitespace
264
 
                } else if (IsASpace(sc.ch)) {
265
 
                        ColouriseWhiteSpace(sc, apostropheStartsAttribute);
266
 
 
267
 
                // Delimiters
268
 
                } else if (IsDelimiterCharacter(sc.ch)) {
269
 
                        ColouriseDelimiter(sc, apostropheStartsAttribute);
270
 
 
271
 
                // Numbers
272
 
                } else if (IsADigit(sc.ch) || sc.ch == '#') {
273
 
                        ColouriseNumber(sc, apostropheStartsAttribute);
274
 
 
275
 
                // Keywords or identifiers
276
 
                } else {
277
 
                        ColouriseWord(sc, keywords, apostropheStartsAttribute);
278
 
                }
279
 
        }
280
 
 
281
 
        sc.Complete();
282
 
}
283
 
 
284
 
static inline bool IsDelimiterCharacter(int ch) {
285
 
        switch (ch) {
286
 
        case '&':
287
 
        case '\'':
288
 
        case '(':
289
 
        case ')':
290
 
        case '*':
291
 
        case '+':
292
 
        case ',':
293
 
        case '-':
294
 
        case '.':
295
 
        case '/':
296
 
        case ':':
297
 
        case ';':
298
 
        case '<':
299
 
        case '=':
300
 
        case '>':
301
 
        case '|':
302
 
                return true;
303
 
        default:
304
 
                return false;
305
 
        }
306
 
}
307
 
 
308
 
static inline bool IsNumberCharacter(int ch) {
309
 
        return IsNumberStartCharacter(ch) ||
310
 
               ch == '_' ||
311
 
               ch == '.' ||
312
 
               ch == '#' ||
313
 
               (ch >= 'a' && ch <= 'f') ||
314
 
               (ch >= 'A' && ch <= 'F');
315
 
}
316
 
 
317
 
static inline bool IsNumberStartCharacter(int ch) {
318
 
        return IsADigit(ch);
319
 
}
320
 
 
321
 
static inline bool IsSeparatorOrDelimiterCharacter(int ch) {
322
 
        return IsASpace(ch) || IsDelimiterCharacter(ch);
323
 
}
324
 
 
325
 
static bool IsValidIdentifier(const std::string& identifier) {
326
 
        // First character can't be '_', so initialize the flag to true
327
 
        bool lastWasUnderscore = true;
328
 
 
329
 
        size_t length = identifier.length();
330
 
 
331
 
        // Zero-length identifiers are not valid (these can occur inside labels)
332
 
        if (length == 0) {
333
 
                return false;
334
 
        }
335
 
 
336
 
        // Check for valid character at the start
337
 
        if (!IsWordStartCharacter(identifier[0])) {
338
 
                return false;
339
 
        }
340
 
 
341
 
        // Check for only valid characters and no double underscores
342
 
        for (size_t i = 0; i < length; i++) {
343
 
                if (!IsWordCharacter(identifier[i]) ||
344
 
                        (identifier[i] == '_' && lastWasUnderscore)) {
345
 
                        return false;
346
 
                }
347
 
                lastWasUnderscore = identifier[i] == '_';
348
 
        }
349
 
 
350
 
        // Check for underscore at the end
351
 
        if (lastWasUnderscore == true) {
352
 
                return false;
353
 
        }
354
 
 
355
 
        // All checks passed
356
 
        return true;
357
 
}
358
 
 
359
 
static bool IsValidNumber(const std::string& number) {
360
 
        size_t hashPos = number.find("#");
361
 
        bool seenDot = false;
362
 
 
363
 
        size_t i = 0;
364
 
        size_t length = number.length();
365
 
 
366
 
        if (length == 0)
367
 
                return false; // Just in case
368
 
 
369
 
        // Decimal number
370
 
        if (hashPos == std::string::npos) {
371
 
                bool canBeSpecial = false;
372
 
 
373
 
                for (; i < length; i++) {
374
 
                        if (number[i] == '_') {
375
 
                                if (!canBeSpecial) {
376
 
                                        return false;
377
 
                                }
378
 
                                canBeSpecial = false;
379
 
                        } else if (number[i] == '.') {
380
 
                                if (!canBeSpecial || seenDot) {
381
 
                                        return false;
382
 
                                }
383
 
                                canBeSpecial = false;
384
 
                                seenDot = true;
385
 
                        } else if (IsADigit(number[i])) {
386
 
                                canBeSpecial = true;
387
 
                        } else {
388
 
                                break;
389
 
                        }
390
 
                }
391
 
 
392
 
                if (!canBeSpecial)
393
 
                        return false;
394
 
        } else {
395
 
                // Based number
396
 
                bool canBeSpecial = false;
397
 
                int base = 0;
398
 
 
399
 
                // Parse base
400
 
                for (; i < length; i++) {
401
 
                        int ch = number[i];
402
 
                        if (ch == '_') {
403
 
                                if (!canBeSpecial)
404
 
                                        return false;
405
 
                                canBeSpecial = false;
406
 
                        } else if (IsADigit(ch)) {
407
 
                                base = base * 10 + (ch - '0');
408
 
                                if (base > 16)
409
 
                                        return false;
410
 
                                canBeSpecial = true;
411
 
                        } else if (ch == '#' && canBeSpecial) {
412
 
                                break;
413
 
                        } else {
414
 
                                return false;
415
 
                        }
416
 
                }
417
 
 
418
 
                if (base < 2)
419
 
                        return false;
420
 
                if (i == length)
421
 
                        return false;
422
 
 
423
 
                i++; // Skip over '#'
424
 
 
425
 
                // Parse number
426
 
                canBeSpecial = false;
427
 
 
428
 
                for (; i < length; i++) {
429
 
                        int ch = tolower(number[i]);
430
 
 
431
 
                        if (ch == '_') {
432
 
                                if (!canBeSpecial) {
433
 
                                        return false;
434
 
                                }
435
 
                                canBeSpecial = false;
436
 
 
437
 
                        } else if (ch == '.') {
438
 
                                if (!canBeSpecial || seenDot) {
439
 
                                        return false;
440
 
                                }
441
 
                                canBeSpecial = false;
442
 
                                seenDot = true;
443
 
 
444
 
                        } else if (IsADigit(ch)) {
445
 
                                if (ch - '0' >= base) {
446
 
                                        return false;
447
 
                                }
448
 
                                canBeSpecial = true;
449
 
 
450
 
                        } else if (ch >= 'a' && ch <= 'f') {
451
 
                                if (ch - 'a' + 10 >= base) {
452
 
                                        return false;
453
 
                                }
454
 
                                canBeSpecial = true;
455
 
 
456
 
                        } else if (ch == '#' && canBeSpecial) {
457
 
                                break;
458
 
 
459
 
                        } else {
460
 
                                return false;
461
 
                        }
462
 
                }
463
 
 
464
 
                if (i == length) {
465
 
                        return false;
466
 
                }
467
 
 
468
 
                i++;
469
 
        }
470
 
 
471
 
        // Exponent (optional)
472
 
        if (i < length) {
473
 
                if (number[i] != 'e' && number[i] != 'E')
474
 
                        return false;
475
 
 
476
 
                i++; // Move past 'E'
477
 
 
478
 
                if (i == length) {
479
 
                        return false;
480
 
                }
481
 
 
482
 
                if (number[i] == '+')
483
 
                        i++;
484
 
                else if (number[i] == '-') {
485
 
                        if (seenDot) {
486
 
                                i++;
487
 
                        } else {
488
 
                                return false; // Integer literals should not have negative exponents
489
 
                        }
490
 
                }
491
 
 
492
 
                if (i == length) {
493
 
                        return false;
494
 
                }
495
 
 
496
 
                bool canBeSpecial = false;
497
 
 
498
 
                for (; i < length; i++) {
499
 
                        if (number[i] == '_') {
500
 
                                if (!canBeSpecial) {
501
 
                                        return false;
502
 
                                }
503
 
                                canBeSpecial = false;
504
 
                        } else if (IsADigit(number[i])) {
505
 
                                canBeSpecial = true;
506
 
                        } else {
507
 
                                return false;
508
 
                        }
509
 
                }
510
 
 
511
 
                if (!canBeSpecial)
512
 
                        return false;
513
 
        }
514
 
 
515
 
        // if i == length, number was parsed successfully.
516
 
        return i == length;
517
 
}
518
 
 
519
 
static inline bool IsWordCharacter(int ch) {
520
 
        return IsWordStartCharacter(ch) || IsADigit(ch);
521
 
}
522
 
 
523
 
static inline bool IsWordStartCharacter(int ch) {
524
 
        return (isascii(ch) && isalpha(ch)) || ch == '_';
525
 
}