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