1 // Scintilla source code edit control
\r
2 /** @file LexSmalltalk.cxx
\r
3 ** Lexer for Smalltalk language.
\r
4 ** Written by Sergey Philippov, sphilippov-at-gmail-dot-com
\r
6 // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
\r
7 // The License.txt file describes the conditions under which this software may be distributed.
\r
13 #include "Platform.h"
\r
15 #include "PropSet.h"
\r
16 #include "Accessor.h"
\r
17 #include "StyleContext.h"
\r
18 #include "KeyWords.h"
\r
19 #include "Scintilla.h"
\r
20 #include "SciLexer.h"
\r
22 #ifdef SCI_NAMESPACE
\r
23 using namespace Scintilla;
\r
27 | lexTable classificationBlock charClasses |
\r
28 charClasses := #(#DecDigit #Letter #Special #Upper #BinSel).
\r
29 lexTable := ByteArray new: 128.
\r
30 classificationBlock := [ :charClass :chars |
\r
32 flag := 1 bitShift: (charClasses indexOf: charClass) - 1.
\r
33 chars do: [ :char | lexTable at: char codePoint + 1 put: ((lexTable at: char codePoint + 1) bitOr: flag)]].
\r
36 value: #DecDigit value: '0123456789';
\r
37 value: #Letter value: '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
\r
38 value: #Special value: '()[]{};.^:';
\r
39 value: #BinSel value: '~@%&*-+=|\/,<>?!';
\r
40 value: #Upper value: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
\r
42 ((String new: 500) streamContents: [ :stream |
\r
43 stream crLf; nextPutAll: 'static int ClassificationTable[256] = {'.
\r
44 lexTable keysAndValuesDo: [ :index :value |
\r
45 ((index - 1) rem: 16) == 0 ifTrue: [
\r
49 stream print: value.
\r
50 index ~= 256 ifTrue: [
\r
51 stream nextPut: $,]].
\r
52 stream crLf; nextPutAll: '};'; crLf.
\r
54 charClasses keysAndValuesDo: [ :index :name |
\r
58 ('static inline bool is<1s>(int ch) {return (ch > 0) && (ch %< 0x80) && ((ClassificationTable[ch] & <2p>) != 0);}')
\r
59 expandMacrosWith: name with: (1 bitShift: (index - 1)))
\r
63 // autogenerated {{{{
\r
65 static int ClassificationTable[256] = {
\r
66 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
\r
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
\r
68 0, 16, 0, 0, 0, 16, 16, 0, 4, 4, 16, 16, 16, 16, 4, 16,
\r
69 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 16, 16, 16, 16,
\r
70 16, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
\r
71 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 16, 4, 4, 2,
\r
72 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
\r
73 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 16, 4, 16, 0,
\r
76 static inline bool isDecDigit(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 1) != 0);}
\r
77 static inline bool isLetter(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 2) != 0);}
\r
78 static inline bool isSpecial(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 4) != 0);}
\r
79 static inline bool isUpper(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 8) != 0);}
\r
80 static inline bool isBinSel(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 16) != 0);}
\r
81 // autogenerated }}}}
\r
83 static inline bool isAlphaNumeric(int ch) {
\r
84 return isDecDigit(ch) || isLetter(ch);
\r
87 static inline bool isDigitOfRadix(int ch, int radix)
\r
90 return (ch - '0') < radix;
\r
91 else if (!isUpper(ch))
\r
94 return (ch - 'A' + 10) < radix;
\r
97 static inline void skipComment(StyleContext& sc)
\r
99 while (sc.More() && sc.ch != '\"')
\r
103 static inline void skipString(StyleContext& sc)
\r
105 while (sc.More()) {
\r
106 if (sc.ch == '\'') {
\r
107 if (sc.chNext != '\'')
\r
115 static void handleHash(StyleContext& sc)
\r
117 if (isSpecial(sc.chNext)) {
\r
118 sc.SetState(SCE_ST_SPECIAL);
\r
122 sc.SetState(SCE_ST_SYMBOL);
\r
124 if (sc.ch == '\'') {
\r
129 if (isLetter(sc.ch)) {
\r
130 while (isAlphaNumeric(sc.chNext) || sc.chNext == ':')
\r
133 else if (isBinSel(sc.ch)) {
\r
134 while (isBinSel(sc.chNext))
\r
140 static inline void handleSpecial(StyleContext& sc)
\r
142 if (sc.ch == ':' && sc.chNext == '=') {
\r
143 sc.SetState(SCE_ST_ASSIGN);
\r
148 sc.SetState(SCE_ST_RETURN);
\r
150 sc.SetState(SCE_ST_SPECIAL);
\r
154 static inline void skipInt(StyleContext& sc, int radix)
\r
156 while (isDigitOfRadix(sc.chNext, radix))
\r
160 static void handleNumeric(StyleContext& sc)
\r
166 sc.SetState(SCE_ST_NUMBER);
\r
167 num[0] = static_cast<char>(sc.ch);
\r
169 while (isDecDigit(sc.chNext)) {
\r
170 num[nl++] = static_cast<char>(sc.chNext);
\r
172 if (nl+1 == sizeof(num)/sizeof(num[0])) // overrun check
\r
175 if (sc.chNext == 'r') {
\r
178 radix = atoi(num + 1);
\r
182 if (sc.chNext == '-')
\r
184 skipInt(sc, radix);
\r
188 if (sc.chNext != '.' || !isDigitOfRadix(sc.GetRelative(2), radix))
\r
191 skipInt(sc, radix);
\r
192 if (sc.chNext == 's') {
\r
195 while (isDecDigit(sc.chNext))
\r
199 else if (sc.chNext != 'e' && sc.chNext != 'd' && sc.chNext != 'q')
\r
202 if (sc.chNext == '+' || sc.chNext == '-')
\r
204 skipInt(sc, radix);
\r
207 static inline void handleBinSel(StyleContext& sc)
\r
209 sc.SetState(SCE_ST_BINARY);
\r
210 while (isBinSel(sc.chNext))
\r
214 static void handleLetter(StyleContext& sc, WordList* specialSelectorList)
\r
219 bool doubleColonPresent;
\r
221 sc.SetState(SCE_ST_DEFAULT);
\r
223 ident[0] = static_cast<char>(sc.ch);
\r
225 while (isAlphaNumeric(sc.chNext)) {
\r
226 ident[il++] = static_cast<char>(sc.chNext);
\r
228 if (il+2 == sizeof(ident)/sizeof(ident[0])) // overrun check
\r
232 if (sc.chNext == ':') {
\r
233 doubleColonPresent = true;
\r
238 doubleColonPresent = false;
\r
241 if (specialSelectorList->InList(ident))
\r
242 state = SCE_ST_SPEC_SEL;
\r
243 else if (doubleColonPresent)
\r
244 state = SCE_ST_KWSEND;
\r
245 else if (isUpper(ident[0]))
\r
246 state = SCE_ST_GLOBAL;
\r
248 if (!strcmp(ident, "self"))
\r
249 state = SCE_ST_SELF;
\r
250 else if (!strcmp(ident, "super"))
\r
251 state = SCE_ST_SUPER;
\r
252 else if (!strcmp(ident, "nil"))
\r
253 state = SCE_ST_NIL;
\r
254 else if (!strcmp(ident, "true") || !strcmp(ident, "false"))
\r
255 state = SCE_ST_BOOL;
\r
257 state = SCE_ST_DEFAULT;
\r
260 sc.ChangeState(state);
\r
263 static void colorizeSmalltalkDoc(unsigned int startPos, int length, int initStyle, WordList *wordLists[], Accessor &styler)
\r
265 StyleContext sc(startPos, length, initStyle, styler);
\r
267 if (initStyle == SCE_ST_COMMENT) {
\r
272 else if (initStyle == SCE_ST_STRING) {
\r
278 for (; sc.More(); sc.Forward()) {
\r
283 sc.SetState(SCE_ST_COMMENT);
\r
287 else if (ch == '\'') {
\r
288 sc.SetState(SCE_ST_STRING);
\r
292 else if (ch == '#')
\r
294 else if (ch == '$') {
\r
295 sc.SetState(SCE_ST_CHARACTER);
\r
298 else if (isSpecial(ch))
\r
300 else if (isDecDigit(ch))
\r
302 else if (isLetter(ch))
\r
303 handleLetter(sc, wordLists[0]);
\r
304 else if (isBinSel(ch)) {
\r
305 if (ch == '-' && isDecDigit(sc.chNext))
\r
311 sc.SetState(SCE_ST_DEFAULT);
\r
316 static const char* const smalltalkWordListDesc[] = {
\r
317 "Special selectors",
\r
321 LexerModule lmSmalltalk(SCLEX_SMALLTALK, colorizeSmalltalkDoc, "smalltalk", NULL, smalltalkWordListDesc);
\r