]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexHaskell.cxx
b528f3f0e3d2da50090fb3db1992e1e08956d805
[wxWidgets.git] / src / stc / scintilla / src / LexHaskell.cxx
1 /******************************************************************
2 * LexHaskell.cxx
3 *
4 * A haskell lexer for the scintilla code control.
5 * Some stuff "lended" from LexPython.cxx and LexCPP.cxx.
6 * External lexer stuff inspired from the caml external lexer.
7 *
8 * Written by Tobias Engvall - tumm at dtek dot chalmers dot se
9 *
10 *
11 * TODO:
12 * * Implement a folder :)
13 * * Nice Character-lexing (stuff inside '\''), LexPython has
14 * this.
15 *
16 *
17 *****************************************************************/
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24
25 #include "Platform.h"
26
27 #include "PropSet.h"
28 #include "PropSetSimple.h"
29 #include "Accessor.h"
30 #include "StyleContext.h"
31 #include "KeyWords.h"
32 #include "Scintilla.h"
33 #include "SciLexer.h"
34
35 #ifdef SCI_NAMESPACE
36 using namespace Scintilla;
37 #endif
38
39 #ifdef BUILD_AS_EXTERNAL_LEXER
40
41 #include "ExternalLexer.h"
42 #include "WindowAccessor.h"
43
44 #define BUILD_EXTERNAL_LEXER 0
45
46 #endif
47
48 // Max level of nested comments
49 #define SCE_HA_COMMENTMAX SCE_HA_COMMENTBLOCK3
50
51
52 enum kwType { kwOther, kwClass, kwData, kwInstance, kwImport, kwModule, kwType};
53
54 static inline bool IsNewline(const int ch) {
55 return (ch == '\n' || ch == '\r');
56 }
57
58 static inline bool IsWhitespace(const int ch) {
59 return ( ch == ' '
60 || ch == '\t'
61 || IsNewline(ch) );
62 }
63
64 static inline bool IsAWordStart(const int ch) {
65 return (ch < 0x80) && (isalnum(ch) || ch == '_');
66 }
67
68 static inline bool IsAWordChar(const int ch) {
69 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\'');
70 }
71
72 static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
73 WordList *keywordlists[], Accessor &styler) {
74
75 WordList &keywords = *keywordlists[0];
76
77 int kwLast = kwOther;
78
79 StyleContext sc(startPos, length, initStyle, styler);
80
81 for (; sc.More(); sc.Forward()) {
82
83 // Check for state end
84 // Operator
85 if (sc.state == SCE_HA_OPERATOR) {
86 kwLast = kwOther;
87 sc.SetState(SCE_HA_DEFAULT);
88 }
89 // String
90 else if (sc.state == SCE_HA_STRING) {
91 if (sc.ch == '\"') {
92 sc.ForwardSetState(SCE_HA_DEFAULT);
93 } else if (sc.ch == '\\') {
94 sc.Forward();
95 }
96 }
97 // Char
98 else if (sc.state == SCE_HA_CHARACTER) {
99 if (sc.ch == '\'') {
100 sc.ForwardSetState(SCE_HA_DEFAULT);
101 } else if (sc.ch == '\\') {
102 sc.Forward();
103 }
104 }
105 // Number
106 else if (sc.state == SCE_HA_NUMBER) {
107 if (!IsADigit(sc.ch)) {
108 sc.SetState(SCE_HA_DEFAULT);
109 }
110 }
111 // Types, constructors, etc.
112 else if (sc.state == SCE_HA_CAPITAL) {
113 if (!IsAWordChar(sc.ch) || sc.ch == '.') {
114 sc.SetState(SCE_HA_DEFAULT);
115 }
116 }
117 // Identifier
118 else if (sc.state == SCE_HA_IDENTIFIER) {
119 if (!IsAWordChar(sc.ch)) {
120 char s[100];
121 sc.GetCurrent(s, sizeof(s));
122 int style = SCE_HA_IDENTIFIER;
123 if ((kwLast == kwImport) || (strcmp(s,"qualified") == 0) || (strcmp(s,"as") == 0)) {
124 style = SCE_HA_IMPORT;
125 } else if (keywords.InList(s)) {
126 style = SCE_HA_KEYWORD;
127 } else if (kwLast == kwData) {
128 style = SCE_HA_DATA;
129 } else if (kwLast == kwClass) {
130 style = SCE_HA_CLASS;
131 } else if (kwLast == kwModule) {
132 style = SCE_HA_MODULE;
133 } else if (isupper(s[0])) {
134 style = SCE_HA_CAPITAL;
135 }
136 sc.ChangeState(style);
137 sc.SetState(SCE_HA_DEFAULT);
138 if (style == SCE_HA_KEYWORD) {
139 if (0 == strcmp(s, "class"))
140 kwLast = kwClass;
141 else if (0 == strcmp(s, "data"))
142 kwLast = kwData;
143 else if (0 == strcmp(s, "instance"))
144 kwLast = kwInstance;
145 else if (0 == strcmp(s, "import"))
146 kwLast = kwImport;
147 else if (0 == strcmp(s, "module"))
148 kwLast = kwModule;
149 else
150 kwLast = kwOther;
151 } else if (style == SCE_HA_CLASS || style == SCE_HA_IMPORT ||
152 style == SCE_HA_MODULE || style == SCE_HA_CAPITAL ||
153 style == SCE_HA_DATA || style == SCE_HA_INSTANCE) {
154 kwLast = kwOther;
155 }
156 }
157 }
158 // Comments
159 // Oneliner
160 else if (sc.state == SCE_HA_COMMENTLINE) {
161 if (IsNewline(sc.ch))
162 sc.SetState(SCE_HA_DEFAULT);
163 }
164 // Nested
165 else if (sc.state >= SCE_HA_COMMENTBLOCK) {
166 if (sc.Match("{-")) {
167 if (sc.state < SCE_HA_COMMENTMAX)
168 sc.SetState(sc.state + 1);
169 }
170 else if (sc.Match("-}")) {
171 sc.Forward();
172 if (sc.state == SCE_HA_COMMENTBLOCK)
173 sc.ForwardSetState(SCE_HA_DEFAULT);
174 else
175 sc.ForwardSetState(sc.state - 1);
176 }
177 }
178 // New state?
179 if (sc.state == SCE_HA_DEFAULT) {
180 // Digit
181 if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
182 sc.SetState(SCE_HA_NUMBER);
183 if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) { // Match anything starting with "0x" or "0X", too
184 sc.Forward(1);
185 }
186 }
187 // Comment line
188 else if (sc.Match("--")) {
189 sc.SetState(SCE_HA_COMMENTLINE);
190 // Comment block
191 }
192 else if (sc.Match("{-")) {
193 sc.SetState(SCE_HA_COMMENTBLOCK);
194 }
195 // String
196 else if (sc.Match('\"')) {
197 sc.SetState(SCE_HA_STRING);
198 }
199 // Character
200 else if (sc.Match('\'')) {
201 sc.SetState(SCE_HA_CHARACTER);
202 }
203 // Stringstart
204 else if (sc.Match('\"')) {
205 sc.SetState(SCE_HA_STRING);
206 }
207 // Operator
208 else if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) {
209 sc.SetState(SCE_HA_OPERATOR);
210 }
211 // Keyword
212 else if (IsAWordStart(sc.ch)) {
213 sc.SetState(SCE_HA_IDENTIFIER);
214 }
215
216 }
217 }
218 sc.Complete();
219 }
220
221 // External stuff - used for dynamic-loading, not implemented in wxStyledTextCtrl yet.
222 // Inspired by the caml external lexer - Credits to Robert Roessler - http://www.rftp.com
223 #ifdef BUILD_EXTERNAL_LEXER
224 static const char* LexerName = "haskell";
225
226 void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, int initStyle,
227 char *words[], WindowID window, char *props)
228 {
229 PropSetSimple ps;
230 ps.SetMultiple(props);
231 WindowAccessor wa(window, ps);
232
233 int nWL = 0;
234 for (; words[nWL]; nWL++) ;
235 WordList** wl = new WordList* [nWL + 1];
236 int i = 0;
237 for (; i<nWL; i++)
238 {
239 wl[i] = new WordList();
240 wl[i]->Set(words[i]);
241 }
242 wl[i] = 0;
243
244 ColorizeHaskellDoc(startPos, length, initStyle, wl, wa);
245 wa.Flush();
246 for (i=nWL-1;i>=0;i--)
247 delete wl[i];
248 delete [] wl;
249 }
250
251 void EXT_LEXER_DECL Fold (unsigned int lexer, unsigned int startPos, int length, int initStyle,
252 char *words[], WindowID window, char *props)
253 {
254
255 }
256
257 int EXT_LEXER_DECL GetLexerCount()
258 {
259 return 1;
260 }
261
262 void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength)
263 {
264 if (buflength > 0) {
265 buflength--;
266 int n = strlen(LexerName);
267 if (n > buflength)
268 n = buflength;
269 memcpy(name, LexerName, n), name[n] = '\0';
270 }
271 }
272 #endif
273
274 LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell");
275