]> git.saurik.com Git - wxWidgets.git/blame - src/stc/scintilla/src/LexLisp.cxx
Fix wxEncodingConverter::Convert(wchar_t) documentation.
[wxWidgets.git] / src / stc / scintilla / src / LexLisp.cxx
CommitLineData
65ec6247
RD
1// Scintilla source code edit control
2/** @file LexLisp.cxx
3 ** Lexer for Lisp.
4 ** Written by Alexey Yutkin.
5 **/
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.
8
9#include <stdlib.h>
10#include <string.h>
11#include <ctype.h>
12#include <stdio.h>
13#include <stdarg.h>
14
15#include "Platform.h"
16
17#include "PropSet.h"
18#include "Accessor.h"
19#include "KeyWords.h"
20#include "Scintilla.h"
21#include "SciLexer.h"
1e9bafca 22#include "StyleContext.h"
65ec6247 23
7e0c58e9
RD
24#ifdef SCI_NAMESPACE
25using namespace Scintilla;
26#endif
27
1e9bafca
RD
28#define SCE_LISP_CHARACTER 29
29#define SCE_LISP_MACRO 30
30#define SCE_LISP_MACRO_DISPATCH 31
65ec6247 31
1a2fb4cd 32static inline bool isLispoperator(char ch) {
65ec6247
RD
33 if (isascii(ch) && isalnum(ch))
34 return false;
9e96e16f 35 if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}')
65ec6247
RD
36 return true;
37 return false;
38}
39
1a2fb4cd 40static inline bool isLispwordstart(char ch) {
65ec6247
RD
41 return isascii(ch) && ch != ';' && !isspacechar(ch) && !isLispoperator(ch) &&
42 ch != '\n' && ch != '\r' && ch != '\"';
43}
44
45
1e9bafca 46static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) {
65ec6247
RD
47 PLATFORM_ASSERT(end >= start);
48 char s[100];
49 unsigned int i;
50 bool digit_flag = true;
51 for (i = 0; (i < end - start + 1) && (i < 99); i++) {
52 s[i] = styler[start + i];
53 s[i + 1] = '\0';
54 if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false;
55 }
56 char chAttr = SCE_LISP_IDENTIFIER;
57
58 if(digit_flag) chAttr = SCE_LISP_NUMBER;
59 else {
60 if (keywords.InList(s)) {
61 chAttr = SCE_LISP_KEYWORD;
1e9bafca
RD
62 } else if (keywords_kw.InList(s)) {
63 chAttr = SCE_LISP_KEYWORD_KW;
64 } else if ((s[0] == '*' && s[i-1] == '*') ||
65 (s[0] == '+' && s[i-1] == '+')) {
66 chAttr = SCE_LISP_SPECIAL;
65ec6247
RD
67 }
68 }
69 styler.ColourTo(end, chAttr);
70 return;
71}
72
73
74static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
75 Accessor &styler) {
76
77 WordList &keywords = *keywordlists[0];
1e9bafca 78 WordList &keywords_kw = *keywordlists[1];
65ec6247
RD
79
80 styler.StartAt(startPos);
81
1e9bafca 82 int state = initStyle, radix = -1;
65ec6247
RD
83 char chNext = styler[startPos];
84 unsigned int lengthDoc = startPos + length;
85 styler.StartSegment(startPos);
86 for (unsigned int i = startPos; i < lengthDoc; i++) {
87 char ch = chNext;
88 chNext = styler.SafeGetCharAt(i + 1);
89
90 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
65ec6247
RD
91
92 if (styler.IsLeadByte(ch)) {
93 chNext = styler.SafeGetCharAt(i + 2);
65ec6247
RD
94 i += 1;
95 continue;
96 }
97
98 if (state == SCE_LISP_DEFAULT) {
1e9bafca
RD
99 if (ch == '#') {
100 styler.ColourTo(i - 1, state);
101 radix = -1;
102 state = SCE_LISP_MACRO_DISPATCH;
9e96e16f
RD
103 } else if (ch == ':' && isLispwordstart(chNext)) {
104 styler.ColourTo(i - 1, state);
105 state = SCE_LISP_SYMBOL;
1e9bafca 106 } else if (isLispwordstart(ch)) {
65ec6247
RD
107 styler.ColourTo(i - 1, state);
108 state = SCE_LISP_IDENTIFIER;
9e730a78 109 }
65ec6247
RD
110 else if (ch == ';') {
111 styler.ColourTo(i - 1, state);
112 state = SCE_LISP_COMMENT;
113 }
114 else if (isLispoperator(ch) || ch=='\'') {
115 styler.ColourTo(i - 1, state);
116 styler.ColourTo(i, SCE_LISP_OPERATOR);
1e9bafca
RD
117 if (ch=='\'' && isLispwordstart(chNext)) {
118 state = SCE_LISP_SYMBOL;
119 }
65ec6247 120 }
65ec6247 121 else if (ch == '\"') {
a33203cb
RD
122 styler.ColourTo(i - 1, state);
123 state = SCE_LISP_STRING;
65ec6247 124 }
1e9bafca 125 } else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) {
65ec6247 126 if (!isLispwordstart(ch)) {
1e9bafca
RD
127 if (state == SCE_LISP_IDENTIFIER) {
128 classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler);
129 } else {
130 styler.ColourTo(i - 1, state);
131 }
65ec6247 132 state = SCE_LISP_DEFAULT;
9e730a78 133 } /*else*/
65ec6247
RD
134 if (isLispoperator(ch) || ch=='\'') {
135 styler.ColourTo(i - 1, state);
136 styler.ColourTo(i, SCE_LISP_OPERATOR);
1e9bafca
RD
137 if (ch=='\'' && isLispwordstart(chNext)) {
138 state = SCE_LISP_SYMBOL;
139 }
140 }
141 } else if (state == SCE_LISP_MACRO_DISPATCH) {
142 if (!isdigit(ch)) {
143 if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) {
144 state = SCE_LISP_DEFAULT;
145 } else {
146 switch (ch) {
147 case '|': state = SCE_LISP_MULTI_COMMENT; break;
148 case 'o':
149 case 'O': radix = 8; state = SCE_LISP_MACRO; break;
150 case 'x':
151 case 'X': radix = 16; state = SCE_LISP_MACRO; break;
152 case 'b':
153 case 'B': radix = 2; state = SCE_LISP_MACRO; break;
154 case '\\': state = SCE_LISP_CHARACTER; break;
155 case ':':
156 case '-':
157 case '+': state = SCE_LISP_MACRO; break;
158 case '\'': if (isLispwordstart(chNext)) {
159 state = SCE_LISP_SPECIAL;
160 } else {
161 styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
162 styler.ColourTo(i, SCE_LISP_OPERATOR);
163 state = SCE_LISP_DEFAULT;
164 }
165 break;
166 default: if (isLispoperator(ch)) {
167 styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
168 styler.ColourTo(i, SCE_LISP_OPERATOR);
169 }
170 state = SCE_LISP_DEFAULT;
171 break;
172 }
173 }
174 }
175 } else if (state == SCE_LISP_MACRO) {
176 if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) {
177 state = SCE_LISP_SPECIAL;
178 } else {
179 state = SCE_LISP_DEFAULT;
180 }
181 } else if (state == SCE_LISP_CHARACTER) {
182 if (isLispoperator(ch)) {
183 styler.ColourTo(i, SCE_LISP_SPECIAL);
184 state = SCE_LISP_DEFAULT;
185 } else if (isLispwordstart(ch)) {
186 styler.ColourTo(i, SCE_LISP_SPECIAL);
187 state = SCE_LISP_SPECIAL;
188 } else {
189 state = SCE_LISP_DEFAULT;
190 }
191 } else if (state == SCE_LISP_SPECIAL) {
192 if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) {
193 styler.ColourTo(i - 1, state);
194 state = SCE_LISP_DEFAULT;
195 }
196 if (isLispoperator(ch) || ch=='\'') {
197 styler.ColourTo(i - 1, state);
198 styler.ColourTo(i, SCE_LISP_OPERATOR);
199 if (ch=='\'' && isLispwordstart(chNext)) {
200 state = SCE_LISP_SYMBOL;
201 }
65ec6247 202 }
65ec6247
RD
203 } else {
204 if (state == SCE_LISP_COMMENT) {
205 if (atEOL) {
206 styler.ColourTo(i - 1, state);
207 state = SCE_LISP_DEFAULT;
208 }
1e9bafca
RD
209 } else if (state == SCE_LISP_MULTI_COMMENT) {
210 if (ch == '|' && chNext == '#') {
211 i++;
212 chNext = styler.SafeGetCharAt(i + 1);
213 styler.ColourTo(i, state);
214 state = SCE_LISP_DEFAULT;
215 }
65ec6247
RD
216 } else if (state == SCE_LISP_STRING) {
217 if (ch == '\\') {
218 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
219 i++;
65ec6247
RD
220 chNext = styler.SafeGetCharAt(i + 1);
221 }
222 } else if (ch == '\"') {
223 styler.ColourTo(i, state);
224 state = SCE_LISP_DEFAULT;
65ec6247
RD
225 }
226 }
227 }
228
65ec6247
RD
229 }
230 styler.ColourTo(lengthDoc - 1, state);
231}
232
233static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
234 Accessor &styler) {
235 unsigned int lengthDoc = startPos + length;
236 int visibleChars = 0;
237 int lineCurrent = styler.GetLine(startPos);
238 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
239 int levelCurrent = levelPrev;
240 char chNext = styler[startPos];
241 int styleNext = styler.StyleAt(startPos);
242 for (unsigned int i = startPos; i < lengthDoc; i++) {
243 char ch = chNext;
244 chNext = styler.SafeGetCharAt(i + 1);
245 int style = styleNext;
246 styleNext = styler.StyleAt(i + 1);
247 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
248 if (style == SCE_LISP_OPERATOR) {
9e96e16f 249 if (ch == '(' || ch == '[' || ch == '{') {
65ec6247 250 levelCurrent++;
9e96e16f 251 } else if (ch == ')' || ch == ']' || ch == '}') {
65ec6247
RD
252 levelCurrent--;
253 }
254 }
255 if (atEOL) {
256 int lev = levelPrev;
257 if (visibleChars == 0)
258 lev |= SC_FOLDLEVELWHITEFLAG;
259 if ((levelCurrent > levelPrev) && (visibleChars > 0))
260 lev |= SC_FOLDLEVELHEADERFLAG;
261 if (lev != styler.LevelAt(lineCurrent)) {
262 styler.SetLevel(lineCurrent, lev);
263 }
264 lineCurrent++;
265 levelPrev = levelCurrent;
266 visibleChars = 0;
267 }
268 if (!isspacechar(ch))
269 visibleChars++;
270 }
271 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
272 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
273 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
274}
275
9e730a78 276static const char * const lispWordListDesc[] = {
1e9bafca 277 "Functions and special operators",
9e730a78
RD
278 "Keywords",
279 0
280};
281
282LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc);