You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
327 lines
8.8 KiB
327 lines
8.8 KiB
// Scintilla source code edit control |
|
/** @file LexSmalltalk.cxx |
|
** Lexer for Smalltalk language. |
|
** Written by Sergey Philippov, sphilippov-at-gmail-dot-com |
|
**/ |
|
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org> |
|
// The License.txt file describes the conditions under which this software may be distributed. |
|
|
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <stdio.h> |
|
#include <stdarg.h> |
|
#include <assert.h> |
|
#include <ctype.h> |
|
|
|
#include <string> |
|
#include <string_view> |
|
|
|
#include "ILexer.h" |
|
#include "Scintilla.h" |
|
#include "SciLexer.h" |
|
|
|
#include "WordList.h" |
|
#include "LexAccessor.h" |
|
#include "Accessor.h" |
|
#include "StyleContext.h" |
|
#include "CharacterSet.h" |
|
#include "LexerModule.h" |
|
|
|
using namespace Lexilla; |
|
|
|
/* |
|
| lexTable classificationBlock charClasses | |
|
charClasses := #(#DecDigit #Letter #Special #Upper #BinSel). |
|
lexTable := ByteArray new: 128. |
|
classificationBlock := [ :charClass :chars | |
|
| flag | |
|
flag := 1 bitShift: (charClasses indexOf: charClass) - 1. |
|
chars do: [ :char | lexTable at: char codePoint + 1 put: ((lexTable at: char codePoint + 1) bitOr: flag)]]. |
|
|
|
classificationBlock |
|
value: #DecDigit value: '0123456789'; |
|
value: #Letter value: '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; |
|
value: #Special value: '()[]{};.^:'; |
|
value: #BinSel value: '~@%&*-+=|\/,<>?!'; |
|
value: #Upper value: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. |
|
|
|
((String new: 500) streamContents: [ :stream | |
|
stream crLf; nextPutAll: 'static int ClassificationTable[256] = {'. |
|
lexTable keysAndValuesDo: [ :index :value | |
|
((index - 1) rem: 16) == 0 ifTrue: [ |
|
stream crLf; tab] |
|
ifFalse: [ |
|
stream space]. |
|
stream print: value. |
|
index ~= 256 ifTrue: [ |
|
stream nextPut: $,]]. |
|
stream crLf; nextPutAll: '};'; crLf. |
|
|
|
charClasses keysAndValuesDo: [ :index :name | |
|
stream |
|
crLf; |
|
nextPutAll: ( |
|
('static inline bool is<1s>(int ch) {return (ch > 0) && (ch %< 0x80) && ((ClassificationTable[ch] & <2p>) != 0);}') |
|
expandMacrosWith: name with: (1 bitShift: (index - 1))) |
|
]]) edit |
|
*/ |
|
|
|
// autogenerated {{{{ |
|
|
|
static int ClassificationTable[256] = { |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
0, 16, 0, 0, 0, 16, 16, 0, 4, 4, 16, 16, 16, 16, 4, 16, |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 16, 16, 16, 16, |
|
16, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, |
|
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 16, 4, 4, 2, |
|
0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 16, 4, 16, 0, |
|
}; |
|
|
|
static inline bool isDecDigit(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 1) != 0);} |
|
static inline bool isLetter(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 2) != 0);} |
|
static inline bool isSpecial(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 4) != 0);} |
|
static inline bool isUpper(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 8) != 0);} |
|
static inline bool isBinSel(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 16) != 0);} |
|
// autogenerated }}}} |
|
|
|
static inline bool isAlphaNumeric(int ch) { |
|
return isDecDigit(ch) || isLetter(ch); |
|
} |
|
|
|
static inline bool isDigitOfRadix(int ch, int radix) |
|
{ |
|
if (isDecDigit(ch)) |
|
return (ch - '0') < radix; |
|
else if (!isUpper(ch)) |
|
return false; |
|
else |
|
return (ch - 'A' + 10) < radix; |
|
} |
|
|
|
static inline void skipComment(StyleContext& sc) |
|
{ |
|
while (sc.More() && sc.ch != '\"') |
|
sc.Forward(); |
|
} |
|
|
|
static inline void skipString(StyleContext& sc) |
|
{ |
|
while (sc.More()) { |
|
if (sc.ch == '\'') { |
|
if (sc.chNext != '\'') |
|
return; |
|
sc.Forward(); |
|
} |
|
sc.Forward(); |
|
} |
|
} |
|
|
|
static void handleHash(StyleContext& sc) |
|
{ |
|
if (isSpecial(sc.chNext)) { |
|
sc.SetState(SCE_ST_SPECIAL); |
|
return; |
|
} |
|
|
|
sc.SetState(SCE_ST_SYMBOL); |
|
sc.Forward(); |
|
if (sc.ch == '\'') { |
|
sc.Forward(); |
|
skipString(sc); |
|
} |
|
else { |
|
if (isLetter(sc.ch)) { |
|
while (isAlphaNumeric(sc.chNext) || sc.chNext == ':') |
|
sc.Forward(); |
|
} |
|
else if (isBinSel(sc.ch)) { |
|
while (isBinSel(sc.chNext)) |
|
sc.Forward(); |
|
} |
|
} |
|
} |
|
|
|
static inline void handleSpecial(StyleContext& sc) |
|
{ |
|
if (sc.ch == ':' && sc.chNext == '=') { |
|
sc.SetState(SCE_ST_ASSIGN); |
|
sc.Forward(); |
|
} |
|
else { |
|
if (sc.ch == '^') |
|
sc.SetState(SCE_ST_RETURN); |
|
else |
|
sc.SetState(SCE_ST_SPECIAL); |
|
} |
|
} |
|
|
|
static inline void skipInt(StyleContext& sc, int radix) |
|
{ |
|
while (isDigitOfRadix(sc.chNext, radix)) |
|
sc.Forward(); |
|
} |
|
|
|
static void handleNumeric(StyleContext& sc) |
|
{ |
|
char num[256]; |
|
int nl; |
|
int radix; |
|
|
|
sc.SetState(SCE_ST_NUMBER); |
|
num[0] = static_cast<char>(sc.ch); |
|
nl = 1; |
|
while (isDecDigit(sc.chNext)) { |
|
num[nl++] = static_cast<char>(sc.chNext); |
|
sc.Forward(); |
|
if (nl+1 == sizeof(num)/sizeof(num[0])) // overrun check |
|
break; |
|
} |
|
if (sc.chNext == 'r') { |
|
num[nl] = 0; |
|
if (num[0] == '-') |
|
radix = atoi(num + 1); |
|
else |
|
radix = atoi(num); |
|
sc.Forward(); |
|
if (sc.chNext == '-') |
|
sc.Forward(); |
|
skipInt(sc, radix); |
|
} |
|
else |
|
radix = 10; |
|
if (sc.chNext != '.' || !isDigitOfRadix(sc.GetRelative(2), radix)) |
|
return; |
|
sc.Forward(); |
|
skipInt(sc, radix); |
|
if (sc.chNext == 's') { |
|
// ScaledDecimal |
|
sc.Forward(); |
|
while (isDecDigit(sc.chNext)) |
|
sc.Forward(); |
|
return; |
|
} |
|
else if (sc.chNext != 'e' && sc.chNext != 'd' && sc.chNext != 'q') |
|
return; |
|
sc.Forward(); |
|
if (sc.chNext == '+' || sc.chNext == '-') |
|
sc.Forward(); |
|
skipInt(sc, radix); |
|
} |
|
|
|
static inline void handleBinSel(StyleContext& sc) |
|
{ |
|
sc.SetState(SCE_ST_BINARY); |
|
while (isBinSel(sc.chNext)) |
|
sc.Forward(); |
|
} |
|
|
|
static void handleLetter(StyleContext& sc, WordList* specialSelectorList) |
|
{ |
|
char ident[256]; |
|
int il; |
|
int state; |
|
bool doubleColonPresent; |
|
|
|
sc.SetState(SCE_ST_DEFAULT); |
|
|
|
ident[0] = static_cast<char>(sc.ch); |
|
il = 1; |
|
while (isAlphaNumeric(sc.chNext)) { |
|
ident[il++] = static_cast<char>(sc.chNext); |
|
sc.Forward(); |
|
if (il+2 == sizeof(ident)/sizeof(ident[0])) // overrun check |
|
break; |
|
} |
|
|
|
if (sc.chNext == ':') { |
|
doubleColonPresent = true; |
|
ident[il++] = ':'; |
|
sc.Forward(); |
|
} |
|
else |
|
doubleColonPresent = false; |
|
ident[il] = 0; |
|
|
|
if (specialSelectorList->InList(ident)) |
|
state = SCE_ST_SPEC_SEL; |
|
else if (doubleColonPresent) |
|
state = SCE_ST_KWSEND; |
|
else if (isUpper(ident[0])) |
|
state = SCE_ST_GLOBAL; |
|
else { |
|
if (!strcmp(ident, "self")) |
|
state = SCE_ST_SELF; |
|
else if (!strcmp(ident, "super")) |
|
state = SCE_ST_SUPER; |
|
else if (!strcmp(ident, "nil")) |
|
state = SCE_ST_NIL; |
|
else if (!strcmp(ident, "true") || !strcmp(ident, "false")) |
|
state = SCE_ST_BOOL; |
|
else |
|
state = SCE_ST_DEFAULT; |
|
} |
|
|
|
sc.ChangeState(state); |
|
} |
|
|
|
static void colorizeSmalltalkDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *wordLists[], Accessor &styler) |
|
{ |
|
StyleContext sc(startPos, length, initStyle, styler); |
|
|
|
if (initStyle == SCE_ST_COMMENT) { |
|
skipComment(sc); |
|
if (sc.More()) |
|
sc.Forward(); |
|
} |
|
else if (initStyle == SCE_ST_STRING) { |
|
skipString(sc); |
|
if (sc.More()) |
|
sc.Forward(); |
|
} |
|
|
|
for (; sc.More(); sc.Forward()) { |
|
int ch; |
|
|
|
ch = sc.ch; |
|
if (ch == '\"') { |
|
sc.SetState(SCE_ST_COMMENT); |
|
sc.Forward(); |
|
skipComment(sc); |
|
} |
|
else if (ch == '\'') { |
|
sc.SetState(SCE_ST_STRING); |
|
sc.Forward(); |
|
skipString(sc); |
|
} |
|
else if (ch == '#') |
|
handleHash(sc); |
|
else if (ch == '$') { |
|
sc.SetState(SCE_ST_CHARACTER); |
|
sc.Forward(); |
|
} |
|
else if (isSpecial(ch)) |
|
handleSpecial(sc); |
|
else if (isDecDigit(ch)) |
|
handleNumeric(sc); |
|
else if (isLetter(ch)) |
|
handleLetter(sc, wordLists[0]); |
|
else if (isBinSel(ch)) { |
|
if (ch == '-' && isDecDigit(sc.chNext)) |
|
handleNumeric(sc); |
|
else |
|
handleBinSel(sc); |
|
} |
|
else |
|
sc.SetState(SCE_ST_DEFAULT); |
|
} |
|
sc.Complete(); |
|
} |
|
|
|
static const char* const smalltalkWordListDesc[] = { |
|
"Special selectors", |
|
0 |
|
}; |
|
|
|
LexerModule lmSmalltalk(SCLEX_SMALLTALK, colorizeSmalltalkDoc, "smalltalk", NULL, smalltalkWordListDesc);
|
|
|