]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexHaskell.cxx
b528f3f0e3d2da50090fb3db1992e1e08956d805
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
12 * * Implement a folder :)
13 * * Nice Character-lexing (stuff inside '\''), LexPython has
17 *****************************************************************/
28 #include "PropSetSimple.h"
30 #include "StyleContext.h"
32 #include "Scintilla.h"
36 using namespace Scintilla
;
39 #ifdef BUILD_AS_EXTERNAL_LEXER
41 #include "ExternalLexer.h"
42 #include "WindowAccessor.h"
44 #define BUILD_EXTERNAL_LEXER 0
48 // Max level of nested comments
49 #define SCE_HA_COMMENTMAX SCE_HA_COMMENTBLOCK3
52 enum kwType
{ kwOther
, kwClass
, kwData
, kwInstance
, kwImport
, kwModule
, kwType
};
54 static inline bool IsNewline(const int ch
) {
55 return (ch
== '\n' || ch
== '\r');
58 static inline bool IsWhitespace(const int ch
) {
64 static inline bool IsAWordStart(const int ch
) {
65 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
68 static inline bool IsAWordChar(const int ch
) {
69 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_' || ch
== '\'');
72 static void ColorizeHaskellDoc(unsigned int startPos
, int length
, int initStyle
,
73 WordList
*keywordlists
[], Accessor
&styler
) {
75 WordList
&keywords
= *keywordlists
[0];
79 StyleContext
sc(startPos
, length
, initStyle
, styler
);
81 for (; sc
.More(); sc
.Forward()) {
83 // Check for state end
85 if (sc
.state
== SCE_HA_OPERATOR
) {
87 sc
.SetState(SCE_HA_DEFAULT
);
90 else if (sc
.state
== SCE_HA_STRING
) {
92 sc
.ForwardSetState(SCE_HA_DEFAULT
);
93 } else if (sc
.ch
== '\\') {
98 else if (sc
.state
== SCE_HA_CHARACTER
) {
100 sc
.ForwardSetState(SCE_HA_DEFAULT
);
101 } else if (sc
.ch
== '\\') {
106 else if (sc
.state
== SCE_HA_NUMBER
) {
107 if (!IsADigit(sc
.ch
)) {
108 sc
.SetState(SCE_HA_DEFAULT
);
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
);
118 else if (sc
.state
== SCE_HA_IDENTIFIER
) {
119 if (!IsAWordChar(sc
.ch
)) {
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
) {
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
;
136 sc
.ChangeState(style
);
137 sc
.SetState(SCE_HA_DEFAULT
);
138 if (style
== SCE_HA_KEYWORD
) {
139 if (0 == strcmp(s
, "class"))
141 else if (0 == strcmp(s
, "data"))
143 else if (0 == strcmp(s
, "instance"))
145 else if (0 == strcmp(s
, "import"))
147 else if (0 == strcmp(s
, "module"))
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
) {
160 else if (sc
.state
== SCE_HA_COMMENTLINE
) {
161 if (IsNewline(sc
.ch
))
162 sc
.SetState(SCE_HA_DEFAULT
);
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);
170 else if (sc
.Match("-}")) {
172 if (sc
.state
== SCE_HA_COMMENTBLOCK
)
173 sc
.ForwardSetState(SCE_HA_DEFAULT
);
175 sc
.ForwardSetState(sc
.state
- 1);
179 if (sc
.state
== SCE_HA_DEFAULT
) {
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
188 else if (sc
.Match("--")) {
189 sc
.SetState(SCE_HA_COMMENTLINE
);
192 else if (sc
.Match("{-")) {
193 sc
.SetState(SCE_HA_COMMENTBLOCK
);
196 else if (sc
.Match('\"')) {
197 sc
.SetState(SCE_HA_STRING
);
200 else if (sc
.Match('\'')) {
201 sc
.SetState(SCE_HA_CHARACTER
);
204 else if (sc
.Match('\"')) {
205 sc
.SetState(SCE_HA_STRING
);
208 else if (isascii(sc
.ch
) && isoperator(static_cast<char>(sc
.ch
))) {
209 sc
.SetState(SCE_HA_OPERATOR
);
212 else if (IsAWordStart(sc
.ch
)) {
213 sc
.SetState(SCE_HA_IDENTIFIER
);
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";
226 void EXT_LEXER_DECL
Lex(unsigned int lexer
, unsigned int startPos
, int length
, int initStyle
,
227 char *words
[], WindowID window
, char *props
)
230 ps
.SetMultiple(props
);
231 WindowAccessor
wa(window
, ps
);
234 for (; words
[nWL
]; nWL
++) ;
235 WordList
** wl
= new WordList
* [nWL
+ 1];
239 wl
[i
] = new WordList();
240 wl
[i
]->Set(words
[i
]);
244 ColorizeHaskellDoc(startPos
, length
, initStyle
, wl
, wa
);
246 for (i
=nWL
-1;i
>=0;i
--)
251 void EXT_LEXER_DECL
Fold (unsigned int lexer
, unsigned int startPos
, int length
, int initStyle
,
252 char *words
[], WindowID window
, char *props
)
257 int EXT_LEXER_DECL
GetLexerCount()
262 void EXT_LEXER_DECL
GetLexerName(unsigned int Index
, char *name
, int buflength
)
266 int n
= strlen(LexerName
);
269 memcpy(name
, LexerName
, n
), name
[n
] = '\0';
274 LexerModule
lmHaskell(SCLEX_HASKELL
, ColorizeHaskellDoc
, "haskell");