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