diff options
Diffstat (limited to 'src/LexSmalltalk.cpp')
-rw-r--r-- | src/LexSmalltalk.cpp | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/src/LexSmalltalk.cpp b/src/LexSmalltalk.cpp new file mode 100644 index 0000000..6f43ec3 --- /dev/null +++ b/src/LexSmalltalk.cpp @@ -0,0 +1,317 @@ +// 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 <ctype.h> + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +/* +| 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(unsigned int startPos, int 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); |