notepad-plus-plus/lexilla/lexers/LexSmalltalk.cxx
Christian Grasser ad79718fc8 Update to scintilla 5.5.2 & Lexilla 5.4.0
Release 5.5.2 ( https://www.scintilla.org/scintilla552.zip )

    Released 21 August 2024.
    Add SCI_SETCOPYSEPARATOR for separator between parts of a multiple selection when copied to the clipboard. Feature #1530.
    Add SCI_GETUNDOSEQUENCE to determine whether an undo sequence is active and its nesting depth.
    Add SCI_STYLESETSTRETCH to support condensed and expanded text styles.
    Add SCI_LINEINDENT and SCI_LINEDEDENT. Feature #1524.
    Fix bug on Cocoa where double-click stopped working when system had been running for a long time.
    On Cocoa implement more values of font weight and stretch.

Release 5.4.0 ( https://www.scintilla.org/lexilla540.zip )

    Released 21 August 2024.
    Inside Lexilla, LexerModule instances are now const. This will require changes to applications that modify Lexilla.cxx, which may be done to add custom lexers.
    Lexer added for TOML "toml".
    Bash: Handle backslash in heredoc delimiter. Issue #257.
    Progress: Fix lexing of nested comments. Pull request #258.
    Force lower-casing of case-insensitive keyword lists so keywords match in some lexers. Issue #259.

Close #15564
2024-08-23 02:59:58 +02:00

328 lines
8.8 KiB
C++

// 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
};
extern const LexerModule lmSmalltalk(SCLEX_SMALLTALK, colorizeSmalltalkDoc, "smalltalk", NULL, smalltalkWordListDesc);