]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexHaskell.cxx
1 /******************************************************************
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.
8 * Written by Tobias Engvall - tumm at dtek dot chalmers dot se
10 * Several bug fixes by Krasimir Angelov - kr.angelov at gmail.com
13 * * Implement a folder :)
14 * * Nice Character-lexing (stuff inside '\''), LexPython has
18 *****************************************************************/
28 #include "Scintilla.h"
31 #include "PropSetSimple.h"
33 #include "LexAccessor.h"
35 #include "StyleContext.h"
36 #include "CharacterSet.h"
37 #include "LexerModule.h"
40 using namespace Scintilla
;
43 #ifdef BUILD_AS_EXTERNAL_LEXER
45 #include "ExternalLexer.h"
46 #include "WindowAccessor.h"
48 #define BUILD_EXTERNAL_LEXER 0
52 #define HA_MODE_DEFAULT 0
53 #define HA_MODE_IMPORT1 1
54 #define HA_MODE_IMPORT2 2
55 #define HA_MODE_IMPORT3 3
56 #define HA_MODE_MODULE 4
58 #define HA_MODE_TYPE 6
60 static inline bool IsNewline(const int ch
) {
61 return (ch
== '\n' || ch
== '\r');
64 static inline bool IsWhitespace(const int ch
) {
70 static inline bool IsAWordStart(const int ch
) {
71 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
74 static inline bool IsAWordChar(const int ch
) {
75 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_' || ch
== '\'');
78 static void ColorizeHaskellDoc(unsigned int startPos
, int length
, int initStyle
,
79 WordList
*keywordlists
[], Accessor
&styler
) {
81 WordList
&keywords
= *keywordlists
[0];
82 WordList
&ffi
= *keywordlists
[1];
84 StyleContext
sc(startPos
, length
, initStyle
, styler
);
86 int lineCurrent
= styler
.GetLine(startPos
);
87 int state
= lineCurrent
? styler
.GetLineState(lineCurrent
-1)
89 int mode
= state
& 0xF;
90 int xmode
= state
>> 4;
93 // Check for state end
96 if (sc
.state
== SCE_HA_OPERATOR
) {
97 if (isascii(sc
.ch
) && isoperator(static_cast<char>(sc
.ch
))) {
100 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
101 sc
.ChangeState(SCE_HA_DEFAULT
);
105 else if (sc
.state
== SCE_HA_STRING
) {
108 styler
.ColourTo(sc
.currentPos
-1, sc
.state
);
109 sc
.ChangeState(SCE_HA_DEFAULT
);
110 } else if (sc
.ch
== '\\') {
112 } else if (sc
.atLineEnd
) {
113 styler
.ColourTo(sc
.currentPos
-1, sc
.state
);
114 sc
.ChangeState(SCE_HA_DEFAULT
);
120 else if (sc
.state
== SCE_HA_CHARACTER
) {
123 styler
.ColourTo(sc
.currentPos
-1, sc
.state
);
124 sc
.ChangeState(SCE_HA_DEFAULT
);
125 } else if (sc
.ch
== '\\') {
127 } else if (sc
.atLineEnd
) {
128 styler
.ColourTo(sc
.currentPos
-1, sc
.state
);
129 sc
.ChangeState(SCE_HA_DEFAULT
);
135 else if (sc
.state
== SCE_HA_NUMBER
) {
136 if (IsADigit(sc
.ch
, xmode
)) {
138 } else if ((xmode
== 10) &&
139 (sc
.ch
== 'e' || sc
.ch
== 'E') &&
140 (IsADigit(sc
.chNext
) || sc
.chNext
== '+' || sc
.chNext
== '-')) {
142 if (sc
.ch
== '+' || sc
.ch
== '-')
145 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
146 sc
.ChangeState(SCE_HA_DEFAULT
);
150 else if (sc
.state
== SCE_HA_IDENTIFIER
) {
151 if (IsAWordChar(sc
.ch
)) {
155 sc
.GetCurrent(s
, sizeof(s
));
156 int style
= sc
.state
;
158 if (keywords
.InList(s
)) {
159 style
= SCE_HA_KEYWORD
;
160 } else if (isupper(s
[0])) {
161 if (mode
>= HA_MODE_IMPORT1
&& mode
<= HA_MODE_IMPORT3
) {
162 style
= SCE_HA_MODULE
;
163 new_mode
= HA_MODE_IMPORT2
;
164 } else if (mode
== HA_MODE_MODULE
)
165 style
= SCE_HA_MODULE
;
167 style
= SCE_HA_CAPITAL
;
168 } else if (mode
== HA_MODE_IMPORT1
&&
169 strcmp(s
,"qualified") == 0) {
170 style
= SCE_HA_KEYWORD
;
171 new_mode
= HA_MODE_IMPORT1
;
172 } else if (mode
== HA_MODE_IMPORT2
) {
173 if (strcmp(s
,"as") == 0) {
174 style
= SCE_HA_KEYWORD
;
175 new_mode
= HA_MODE_IMPORT3
;
176 } else if (strcmp(s
,"hiding") == 0) {
177 style
= SCE_HA_KEYWORD
;
179 } else if (mode
== HA_MODE_FFI
) {
181 style
= SCE_HA_KEYWORD
;
182 new_mode
= HA_MODE_FFI
;
185 else if (mode
== HA_MODE_TYPE
) {
186 if (strcmp(s
,"family") == 0)
187 style
= SCE_HA_KEYWORD
;
189 styler
.ColourTo(sc
.currentPos
- 1, style
);
190 if (strcmp(s
,"import") == 0 && mode
!= HA_MODE_FFI
)
191 new_mode
= HA_MODE_IMPORT1
;
192 else if (strcmp(s
,"module") == 0)
193 new_mode
= HA_MODE_MODULE
;
194 else if (strcmp(s
,"foreign") == 0)
195 new_mode
= HA_MODE_FFI
;
196 else if (strcmp(s
,"type") == 0)
197 new_mode
= HA_MODE_TYPE
;
198 sc
.ChangeState(SCE_HA_DEFAULT
);
205 else if (sc
.state
== SCE_HA_COMMENTLINE
) {
207 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
208 sc
.ChangeState(SCE_HA_DEFAULT
);
214 else if (sc
.state
== SCE_HA_COMMENTBLOCK
) {
215 if (sc
.Match("{-")) {
219 else if (sc
.Match("-}")) {
223 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
224 sc
.ChangeState(SCE_HA_DEFAULT
);
228 // Remember the line state for future incremental lexing
229 styler
.SetLineState(lineCurrent
, (xmode
<< 4) | mode
);
236 if (sc
.state
== SCE_HA_DEFAULT
) {
238 if (IsADigit(sc
.ch
) ||
239 (sc
.ch
== '.' && IsADigit(sc
.chNext
)) ||
240 (sc
.ch
== '-' && IsADigit(sc
.chNext
))) {
241 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
242 sc
.ChangeState(SCE_HA_NUMBER
);
243 if (sc
.ch
== '0' && (sc
.chNext
== 'X' || sc
.chNext
== 'x')) {
244 // Match anything starting with "0x" or "0X", too
247 } else if (sc
.ch
== '0' && (sc
.chNext
== 'O' || sc
.chNext
== 'o')) {
248 // Match anything starting with "0x" or "0X", too
255 mode
= HA_MODE_DEFAULT
;
258 else if (sc
.Match("--")) {
259 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
261 sc
.ChangeState(SCE_HA_COMMENTLINE
);
264 else if (sc
.Match("{-")) {
265 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
267 sc
.ChangeState(SCE_HA_COMMENTBLOCK
);
271 else if (sc
.Match('\"')) {
272 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
274 sc
.ChangeState(SCE_HA_STRING
);
277 else if (sc
.Match('\'')) {
278 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
280 sc
.ChangeState(SCE_HA_CHARACTER
);
282 else if (sc
.ch
== '(' || sc
.ch
== ')' ||
283 sc
.ch
== '{' || sc
.ch
== '}' ||
284 sc
.ch
== '[' || sc
.ch
== ']') {
285 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
287 styler
.ColourTo(sc
.currentPos
- 1, SCE_HA_OPERATOR
);
288 mode
= HA_MODE_DEFAULT
;
291 else if (isascii(sc
.ch
) && isoperator(static_cast<char>(sc
.ch
))) {
292 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
294 sc
.ChangeState(SCE_HA_OPERATOR
);
295 mode
= HA_MODE_DEFAULT
;
298 else if (IsAWordStart(sc
.ch
)) {
299 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
301 sc
.ChangeState(SCE_HA_IDENTIFIER
);
304 // Remember the line state for future incremental lexing
305 styler
.SetLineState(lineCurrent
, (xmode
<< 4) | mode
);
315 // External stuff - used for dynamic-loading, not implemented in wxStyledTextCtrl yet.
316 // Inspired by the caml external lexer - Credits to Robert Roessler - http://www.rftp.com
317 #ifdef BUILD_EXTERNAL_LEXER
318 static const char* LexerName
= "haskell";
320 void EXT_LEXER_DECL
Lex(unsigned int lexer
, unsigned int startPos
, int length
, int initStyle
,
321 char *words
[], WindowID window
, char *props
)
324 ps
.SetMultiple(props
);
325 WindowAccessor
wa(window
, ps
);
328 for (; words
[nWL
]; nWL
++) ;
329 WordList
** wl
= new WordList
* [nWL
+ 1];
333 wl
[i
] = new WordList();
334 wl
[i
]->Set(words
[i
]);
338 ColorizeHaskellDoc(startPos
, length
, initStyle
, wl
, wa
);
340 for (i
=nWL
-1;i
>=0;i
--)
345 void EXT_LEXER_DECL
Fold (unsigned int lexer
, unsigned int startPos
, int length
, int initStyle
,
346 char *words
[], WindowID window
, char *props
)
351 int EXT_LEXER_DECL
GetLexerCount()
356 void EXT_LEXER_DECL
GetLexerName(unsigned int Index
, char *name
, int buflength
)
360 int n
= strlen(LexerName
);
363 memcpy(name
, LexerName
, n
), name
[n
] = '\0';
368 LexerModule
lmHaskell(SCLEX_HASKELL
, ColorizeHaskellDoc
, "haskell");