1
// Scintilla source code edit control
4
** Written by Alexey Yutkin.
6
// Copyright 1998-2001 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;
31
#define SCE_LISP_CHARACTER 29
32
#define SCE_LISP_MACRO 30
33
#define SCE_LISP_MACRO_DISPATCH 31
35
static inline bool isLispoperator(char ch) {
36
if (isascii(ch) && isalnum(ch))
38
if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}')
43
static inline bool isLispwordstart(char ch) {
44
return isascii(ch) && ch != ';' && !isspacechar(ch) && !isLispoperator(ch) &&
45
ch != '\n' && ch != '\r' && ch != '\"';
49
static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) {
53
bool digit_flag = true;
54
for (i = 0; (i < end - start + 1) && (i < 99); i++) {
55
s[i] = styler[start + i];
57
if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false;
59
char chAttr = SCE_LISP_IDENTIFIER;
61
if(digit_flag) chAttr = SCE_LISP_NUMBER;
63
if (keywords.InList(s)) {
64
chAttr = SCE_LISP_KEYWORD;
65
} else if (keywords_kw.InList(s)) {
66
chAttr = SCE_LISP_KEYWORD_KW;
67
} else if ((s[0] == '*' && s[i-1] == '*') ||
68
(s[0] == '+' && s[i-1] == '+')) {
69
chAttr = SCE_LISP_SPECIAL;
72
styler.ColourTo(end, chAttr);
77
static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
80
WordList &keywords = *keywordlists[0];
81
WordList &keywords_kw = *keywordlists[1];
83
styler.StartAt(startPos);
85
int state = initStyle, radix = -1;
86
char chNext = styler[startPos];
87
unsigned int lengthDoc = startPos + length;
88
styler.StartSegment(startPos);
89
for (unsigned int i = startPos; i < lengthDoc; i++) {
91
chNext = styler.SafeGetCharAt(i + 1);
93
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
95
if (styler.IsLeadByte(ch)) {
96
chNext = styler.SafeGetCharAt(i + 2);
101
if (state == SCE_LISP_DEFAULT) {
103
styler.ColourTo(i - 1, state);
105
state = SCE_LISP_MACRO_DISPATCH;
106
} else if (ch == ':' && isLispwordstart(chNext)) {
107
styler.ColourTo(i - 1, state);
108
state = SCE_LISP_SYMBOL;
109
} else if (isLispwordstart(ch)) {
110
styler.ColourTo(i - 1, state);
111
state = SCE_LISP_IDENTIFIER;
113
else if (ch == ';') {
114
styler.ColourTo(i - 1, state);
115
state = SCE_LISP_COMMENT;
117
else if (isLispoperator(ch) || ch=='\'') {
118
styler.ColourTo(i - 1, state);
119
styler.ColourTo(i, SCE_LISP_OPERATOR);
120
if (ch=='\'' && isLispwordstart(chNext)) {
121
state = SCE_LISP_SYMBOL;
124
else if (ch == '\"') {
125
styler.ColourTo(i - 1, state);
126
state = SCE_LISP_STRING;
128
} else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) {
129
if (!isLispwordstart(ch)) {
130
if (state == SCE_LISP_IDENTIFIER) {
131
classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler);
133
styler.ColourTo(i - 1, state);
135
state = SCE_LISP_DEFAULT;
137
if (isLispoperator(ch) || ch=='\'') {
138
styler.ColourTo(i - 1, state);
139
styler.ColourTo(i, SCE_LISP_OPERATOR);
140
if (ch=='\'' && isLispwordstart(chNext)) {
141
state = SCE_LISP_SYMBOL;
144
} else if (state == SCE_LISP_MACRO_DISPATCH) {
145
if (!(isascii(ch) && isdigit(ch))) {
146
if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) {
147
state = SCE_LISP_DEFAULT;
150
case '|': state = SCE_LISP_MULTI_COMMENT; break;
152
case 'O': radix = 8; state = SCE_LISP_MACRO; break;
154
case 'X': radix = 16; state = SCE_LISP_MACRO; break;
156
case 'B': radix = 2; state = SCE_LISP_MACRO; break;
157
case '\\': state = SCE_LISP_CHARACTER; break;
160
case '+': state = SCE_LISP_MACRO; break;
161
case '\'': if (isLispwordstart(chNext)) {
162
state = SCE_LISP_SPECIAL;
164
styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
165
styler.ColourTo(i, SCE_LISP_OPERATOR);
166
state = SCE_LISP_DEFAULT;
169
default: if (isLispoperator(ch)) {
170
styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
171
styler.ColourTo(i, SCE_LISP_OPERATOR);
173
state = SCE_LISP_DEFAULT;
178
} else if (state == SCE_LISP_MACRO) {
179
if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) {
180
state = SCE_LISP_SPECIAL;
182
state = SCE_LISP_DEFAULT;
184
} else if (state == SCE_LISP_CHARACTER) {
185
if (isLispoperator(ch)) {
186
styler.ColourTo(i, SCE_LISP_SPECIAL);
187
state = SCE_LISP_DEFAULT;
188
} else if (isLispwordstart(ch)) {
189
styler.ColourTo(i, SCE_LISP_SPECIAL);
190
state = SCE_LISP_SPECIAL;
192
state = SCE_LISP_DEFAULT;
194
} else if (state == SCE_LISP_SPECIAL) {
195
if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) {
196
styler.ColourTo(i - 1, state);
197
state = SCE_LISP_DEFAULT;
199
if (isLispoperator(ch) || ch=='\'') {
200
styler.ColourTo(i - 1, state);
201
styler.ColourTo(i, SCE_LISP_OPERATOR);
202
if (ch=='\'' && isLispwordstart(chNext)) {
203
state = SCE_LISP_SYMBOL;
207
if (state == SCE_LISP_COMMENT) {
209
styler.ColourTo(i - 1, state);
210
state = SCE_LISP_DEFAULT;
212
} else if (state == SCE_LISP_MULTI_COMMENT) {
213
if (ch == '|' && chNext == '#') {
215
chNext = styler.SafeGetCharAt(i + 1);
216
styler.ColourTo(i, state);
217
state = SCE_LISP_DEFAULT;
219
} else if (state == SCE_LISP_STRING) {
221
if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
223
chNext = styler.SafeGetCharAt(i + 1);
225
} else if (ch == '\"') {
226
styler.ColourTo(i, state);
227
state = SCE_LISP_DEFAULT;
233
styler.ColourTo(lengthDoc - 1, state);
236
static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
238
unsigned int lengthDoc = startPos + length;
239
int visibleChars = 0;
240
int lineCurrent = styler.GetLine(startPos);
241
int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
242
int levelCurrent = levelPrev;
243
char chNext = styler[startPos];
244
int styleNext = styler.StyleAt(startPos);
245
for (unsigned int i = startPos; i < lengthDoc; i++) {
247
chNext = styler.SafeGetCharAt(i + 1);
248
int style = styleNext;
249
styleNext = styler.StyleAt(i + 1);
250
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
251
if (style == SCE_LISP_OPERATOR) {
252
if (ch == '(' || ch == '[' || ch == '{') {
254
} else if (ch == ')' || ch == ']' || ch == '}') {
260
if (visibleChars == 0)
261
lev |= SC_FOLDLEVELWHITEFLAG;
262
if ((levelCurrent > levelPrev) && (visibleChars > 0))
263
lev |= SC_FOLDLEVELHEADERFLAG;
264
if (lev != styler.LevelAt(lineCurrent)) {
265
styler.SetLevel(lineCurrent, lev);
268
levelPrev = levelCurrent;
271
if (!isspacechar(ch))
274
// Fill in the real level of the next line, keeping the current flags as they will be filled in later
275
int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
276
styler.SetLevel(lineCurrent, levelPrev | flagsNext);
279
static const char * const lispWordListDesc[] = {
280
"Functions and special operators",
285
LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc);