1
// Scintilla source code edit control
2
/** @file LexSmalltalk.cxx
3
** Lexer for Smalltalk language.
4
** Written by Sergey Philippov, sphilippov-at-gmail-dot-com
6
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
7
// The License.txt file describes the conditions under which this software may be distributed.
17
#include "Scintilla.h"
21
#include "LexAccessor.h"
23
#include "StyleContext.h"
24
#include "CharacterSet.h"
25
#include "LexerModule.h"
28
using namespace Scintilla;
32
| lexTable classificationBlock charClasses |
33
charClasses := #(#DecDigit #Letter #Special #Upper #BinSel).
34
lexTable := ByteArray new: 128.
35
classificationBlock := [ :charClass :chars |
37
flag := 1 bitShift: (charClasses indexOf: charClass) - 1.
38
chars do: [ :char | lexTable at: char codePoint + 1 put: ((lexTable at: char codePoint + 1) bitOr: flag)]].
41
value: #DecDigit value: '0123456789';
42
value: #Letter value: '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
43
value: #Special value: '()[]{};.^:';
44
value: #BinSel value: '~@%&*-+=|\/,<>?!';
45
value: #Upper value: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
47
((String new: 500) streamContents: [ :stream |
48
stream crLf; nextPutAll: 'static int ClassificationTable[256] = {'.
49
lexTable keysAndValuesDo: [ :index :value |
50
((index - 1) rem: 16) == 0 ifTrue: [
55
index ~= 256 ifTrue: [
57
stream crLf; nextPutAll: '};'; crLf.
59
charClasses keysAndValuesDo: [ :index :name |
63
('static inline bool is<1s>(int ch) {return (ch > 0) && (ch %< 0x80) && ((ClassificationTable[ch] & <2p>) != 0);}')
64
expandMacrosWith: name with: (1 bitShift: (index - 1)))
70
static int ClassificationTable[256] = {
71
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73
0, 16, 0, 0, 0, 16, 16, 0, 4, 4, 16, 16, 16, 16, 4, 16,
74
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 16, 16, 16, 16,
75
16, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
76
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 16, 4, 4, 2,
77
0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
78
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 16, 4, 16, 0,
81
static inline bool isDecDigit(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 1) != 0);}
82
static inline bool isLetter(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 2) != 0);}
83
static inline bool isSpecial(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 4) != 0);}
84
static inline bool isUpper(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 8) != 0);}
85
static inline bool isBinSel(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 16) != 0);}
88
static inline bool isAlphaNumeric(int ch) {
89
return isDecDigit(ch) || isLetter(ch);
92
static inline bool isDigitOfRadix(int ch, int radix)
95
return (ch - '0') < radix;
96
else if (!isUpper(ch))
99
return (ch - 'A' + 10) < radix;
102
static inline void skipComment(StyleContext& sc)
104
while (sc.More() && sc.ch != '\"')
108
static inline void skipString(StyleContext& sc)
112
if (sc.chNext != '\'')
120
static void handleHash(StyleContext& sc)
122
if (isSpecial(sc.chNext)) {
123
sc.SetState(SCE_ST_SPECIAL);
127
sc.SetState(SCE_ST_SYMBOL);
134
if (isLetter(sc.ch)) {
135
while (isAlphaNumeric(sc.chNext) || sc.chNext == ':')
138
else if (isBinSel(sc.ch)) {
139
while (isBinSel(sc.chNext))
145
static inline void handleSpecial(StyleContext& sc)
147
if (sc.ch == ':' && sc.chNext == '=') {
148
sc.SetState(SCE_ST_ASSIGN);
153
sc.SetState(SCE_ST_RETURN);
155
sc.SetState(SCE_ST_SPECIAL);
159
static inline void skipInt(StyleContext& sc, int radix)
161
while (isDigitOfRadix(sc.chNext, radix))
165
static void handleNumeric(StyleContext& sc)
171
sc.SetState(SCE_ST_NUMBER);
172
num[0] = static_cast<char>(sc.ch);
174
while (isDecDigit(sc.chNext)) {
175
num[nl++] = static_cast<char>(sc.chNext);
177
if (nl+1 == sizeof(num)/sizeof(num[0])) // overrun check
180
if (sc.chNext == 'r') {
183
radix = atoi(num + 1);
187
if (sc.chNext == '-')
193
if (sc.chNext != '.' || !isDigitOfRadix(sc.GetRelative(2), radix))
197
if (sc.chNext == 's') {
200
while (isDecDigit(sc.chNext))
204
else if (sc.chNext != 'e' && sc.chNext != 'd' && sc.chNext != 'q')
207
if (sc.chNext == '+' || sc.chNext == '-')
212
static inline void handleBinSel(StyleContext& sc)
214
sc.SetState(SCE_ST_BINARY);
215
while (isBinSel(sc.chNext))
219
static void handleLetter(StyleContext& sc, WordList* specialSelectorList)
224
bool doubleColonPresent;
226
sc.SetState(SCE_ST_DEFAULT);
228
ident[0] = static_cast<char>(sc.ch);
230
while (isAlphaNumeric(sc.chNext)) {
231
ident[il++] = static_cast<char>(sc.chNext);
233
if (il+2 == sizeof(ident)/sizeof(ident[0])) // overrun check
237
if (sc.chNext == ':') {
238
doubleColonPresent = true;
243
doubleColonPresent = false;
246
if (specialSelectorList->InList(ident))
247
state = SCE_ST_SPEC_SEL;
248
else if (doubleColonPresent)
249
state = SCE_ST_KWSEND;
250
else if (isUpper(ident[0]))
251
state = SCE_ST_GLOBAL;
253
if (!strcmp(ident, "self"))
255
else if (!strcmp(ident, "super"))
256
state = SCE_ST_SUPER;
257
else if (!strcmp(ident, "nil"))
259
else if (!strcmp(ident, "true") || !strcmp(ident, "false"))
262
state = SCE_ST_DEFAULT;
265
sc.ChangeState(state);
268
static void colorizeSmalltalkDoc(unsigned int startPos, int length, int initStyle, WordList *wordLists[], Accessor &styler)
270
StyleContext sc(startPos, length, initStyle, styler);
272
if (initStyle == SCE_ST_COMMENT) {
277
else if (initStyle == SCE_ST_STRING) {
283
for (; sc.More(); sc.Forward()) {
288
sc.SetState(SCE_ST_COMMENT);
292
else if (ch == '\'') {
293
sc.SetState(SCE_ST_STRING);
299
else if (ch == '$') {
300
sc.SetState(SCE_ST_CHARACTER);
303
else if (isSpecial(ch))
305
else if (isDecDigit(ch))
307
else if (isLetter(ch))
308
handleLetter(sc, wordLists[0]);
309
else if (isBinSel(ch)) {
310
if (ch == '-' && isDecDigit(sc.chNext))
316
sc.SetState(SCE_ST_DEFAULT);
321
static const char* const smalltalkWordListDesc[] = {
326
LexerModule lmSmalltalk(SCLEX_SMALLTALK, colorizeSmalltalkDoc, "smalltalk", NULL, smalltalkWordListDesc);