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