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