]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexLisp.cxx
9cd5433c89630299cb796c5b1c9b464464483b62
[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
23
24 static inline bool isLispoperator(char ch) {
25 if (isascii(ch) && isalnum(ch))
26 return false;
27 if (ch == '\'' || ch == '(' || ch == ')' )
28 return true;
29 return false;
30 }
31
32 static inline bool isLispwordstart(char ch) {
33 return isascii(ch) && ch != ';' && !isspacechar(ch) && !isLispoperator(ch) &&
34 ch != '\n' && ch != '\r' && ch != '\"';
35 }
36
37
38 static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
39 PLATFORM_ASSERT(end >= start);
40 char s[100];
41 unsigned int i;
42 bool digit_flag = true;
43 for (i = 0; (i < end - start + 1) && (i < 99); i++) {
44 s[i] = styler[start + i];
45 s[i + 1] = '\0';
46 if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false;
47 }
48 char chAttr = SCE_LISP_IDENTIFIER;
49
50 if(digit_flag) chAttr = SCE_LISP_NUMBER;
51 else {
52 if (keywords.InList(s)) {
53 chAttr = SCE_LISP_KEYWORD;
54 }
55 }
56 styler.ColourTo(end, chAttr);
57 return;
58 }
59
60
61 static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
62 Accessor &styler) {
63
64 WordList &keywords = *keywordlists[0];
65
66 styler.StartAt(startPos);
67
68 int state = initStyle;
69 if (state == SCE_LISP_STRINGEOL) // Does not leak onto next line
70 state = SCE_LISP_DEFAULT;
71 char chPrev = ' ';
72 char chNext = styler[startPos];
73 unsigned int lengthDoc = startPos + length;
74 styler.StartSegment(startPos);
75 for (unsigned int i = startPos; i < lengthDoc; i++) {
76 char ch = chNext;
77 chNext = styler.SafeGetCharAt(i + 1);
78
79 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
80 if (atEOL) {
81 // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
82 // Avoid triggering two times on Dos/Win
83 // End of line
84 if (state == SCE_LISP_STRINGEOL) {
85 styler.ColourTo(i, state);
86 state = SCE_LISP_DEFAULT;
87 }
88 }
89
90 if (styler.IsLeadByte(ch)) {
91 chNext = styler.SafeGetCharAt(i + 2);
92 chPrev = ' ';
93 i += 1;
94 continue;
95 }
96
97 if (state == SCE_LISP_DEFAULT) {
98 if (isLispwordstart(ch)) {
99 styler.ColourTo(i - 1, state);
100 state = SCE_LISP_IDENTIFIER;
101 }
102 else if (ch == ';') {
103 styler.ColourTo(i - 1, state);
104 state = SCE_LISP_COMMENT;
105 }
106 else if (isLispoperator(ch) || ch=='\'') {
107 styler.ColourTo(i - 1, state);
108 styler.ColourTo(i, SCE_LISP_OPERATOR);
109 }
110
111 else if (ch == '\"') {
112 state = SCE_LISP_STRING;
113 }
114 } else if (state == SCE_LISP_IDENTIFIER) {
115 if (!isLispwordstart(ch)) {
116 classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, styler);
117 state = SCE_LISP_DEFAULT;
118 } /*else*/
119 if (isLispoperator(ch) || ch=='\'') {
120 styler.ColourTo(i - 1, state);
121 styler.ColourTo(i, SCE_LISP_OPERATOR);
122 }
123
124 } else {
125 if (state == SCE_LISP_COMMENT) {
126 if (atEOL) {
127 styler.ColourTo(i - 1, state);
128 state = SCE_LISP_DEFAULT;
129 }
130 } else if (state == SCE_LISP_STRING) {
131 if (ch == '\\') {
132 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
133 i++;
134 ch = chNext;
135 chNext = styler.SafeGetCharAt(i + 1);
136 }
137 } else if (ch == '\"') {
138 styler.ColourTo(i, state);
139 state = SCE_LISP_DEFAULT;
140 } else if ((chNext == '\r' || chNext == '\n') && (chPrev != '\\')) {
141 styler.ColourTo(i - 1, SCE_LISP_STRINGEOL);
142 state = SCE_LISP_STRINGEOL;
143 }
144 }
145 }
146
147 chPrev = ch;
148 }
149 styler.ColourTo(lengthDoc - 1, state);
150 }
151
152 static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
153 Accessor &styler) {
154 unsigned int lengthDoc = startPos + length;
155 int visibleChars = 0;
156 int lineCurrent = styler.GetLine(startPos);
157 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
158 int levelCurrent = levelPrev;
159 char chNext = styler[startPos];
160 int styleNext = styler.StyleAt(startPos);
161 for (unsigned int i = startPos; i < lengthDoc; i++) {
162 char ch = chNext;
163 chNext = styler.SafeGetCharAt(i + 1);
164 int style = styleNext;
165 styleNext = styler.StyleAt(i + 1);
166 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
167 if (style == SCE_LISP_OPERATOR) {
168 if (ch == '(') {
169 levelCurrent++;
170 } else if (ch == ')') {
171 levelCurrent--;
172 }
173 }
174 if (atEOL) {
175 int lev = levelPrev;
176 if (visibleChars == 0)
177 lev |= SC_FOLDLEVELWHITEFLAG;
178 if ((levelCurrent > levelPrev) && (visibleChars > 0))
179 lev |= SC_FOLDLEVELHEADERFLAG;
180 if (lev != styler.LevelAt(lineCurrent)) {
181 styler.SetLevel(lineCurrent, lev);
182 }
183 lineCurrent++;
184 levelPrev = levelCurrent;
185 visibleChars = 0;
186 }
187 if (!isspacechar(ch))
188 visibleChars++;
189 }
190 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
191 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
192 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
193 }
194
195 static const char * const lispWordListDesc[] = {
196 "Keywords",
197 0
198 };
199
200 LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc);