]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/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
12 * * Implement a folder :)
13 * * Nice Character-lexing (stuff inside '\''), LexPython has
17 *****************************************************************/
29 #include "StyleContext.h"
31 #include "Scintilla.h"
34 #ifdef BUILD_AS_EXTERNAL_LEXER
36 #include "ExternalLexer.h"
37 #include "WindowAccessor.h"
39 #define BUILD_EXTERNAL_LEXER 0
43 // Max level of nested comments
44 #define SCE_HA_COMMENTMAX SCE_HA_COMMENTBLOCK3
47 enum kwType
{ kwOther
, kwClass
, kwData
, kwInstance
, kwImport
, kwModule
, kwType
};
49 static inline bool IsNewline(const int ch
) {
50 return (ch
== '\n' || ch
== '\r');
53 static inline bool IsWhitespace(const int ch
) {
59 static inline bool IsAWordStart(const int ch
) {
60 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
63 static inline bool IsAWordChar(const int ch
) {
64 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_' || ch
== '\'');
67 static void ColorizeHaskellDoc(unsigned int startPos
, int length
, int initStyle
,
68 WordList
*keywordlists
[], Accessor
&styler
) {
70 WordList
&keywords
= *keywordlists
[0];
74 StyleContext
sc(startPos
, length
, initStyle
, styler
);
76 for (; sc
.More(); sc
.Forward()) {
78 // Check for state end
80 if (sc
.state
== SCE_HA_OPERATOR
) {
82 sc
.SetState(SCE_HA_DEFAULT
);
85 else if (sc
.state
== SCE_HA_STRING
) {
87 sc
.ForwardSetState(SCE_HA_DEFAULT
);
91 else if (sc
.state
== SCE_HA_CHARACTER
) {
93 sc
.ForwardSetState(SCE_HA_DEFAULT
);
97 else if (sc
.state
== SCE_HA_NUMBER
) {
98 if (!IsADigit(sc
.ch
)) {
99 sc
.SetState(SCE_HA_DEFAULT
);
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
);
109 else if (sc
.state
== SCE_HA_IDENTIFIER
) {
110 if (!IsAWordChar(sc
.ch
)) {
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
) {
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
;
127 sc
.ChangeState(style
);
128 sc
.SetState(SCE_HA_DEFAULT
);
129 if (style
== SCE_HA_KEYWORD
) {
130 if (0 == strcmp(s
, "class"))
132 else if (0 == strcmp(s
, "data"))
134 else if (0 == strcmp(s
, "instance"))
136 else if (0 == strcmp(s
, "import"))
138 else if (0 == strcmp(s
, "module"))
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
) {
151 else if (sc
.state
== SCE_HA_COMMENTLINE
) {
152 if (IsNewline(sc
.ch
))
153 sc
.SetState(SCE_HA_DEFAULT
);
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);
161 else if (sc
.Match("-}")) {
163 if (sc
.state
== SCE_HA_COMMENTBLOCK
)
164 sc
.ForwardSetState(SCE_HA_DEFAULT
);
166 sc
.ForwardSetState(sc
.state
- 1);
170 if (sc
.state
== SCE_HA_DEFAULT
) {
172 if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {
173 sc
.SetState(SCE_HA_NUMBER
);
176 else if (sc
.Match("--")) {
177 sc
.SetState(SCE_HA_COMMENTLINE
);
180 else if (sc
.Match("{-")) {
181 sc
.SetState(SCE_HA_COMMENTBLOCK
);
184 else if (sc
.Match('\"')) {
185 sc
.SetState(SCE_HA_STRING
);
188 else if (sc
.Match('\'') && IsWhitespace(sc
.GetRelative(-1)) ) {
189 sc
.SetState(SCE_HA_CHARACTER
);
192 else if (sc
.Match('\"')) {
193 sc
.SetState(SCE_HA_STRING
);
196 else if (isascii(sc
.ch
) && isoperator(static_cast<char>(sc
.ch
))) {
197 sc
.SetState(SCE_HA_OPERATOR
);
200 else if (IsAWordStart(sc
.ch
)) {
201 sc
.SetState(SCE_HA_IDENTIFIER
);
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";
214 void EXT_LEXER_DECL
Lex(unsigned int lexer
, unsigned int startPos
, int length
, int initStyle
,
215 char *words
[], WindowID window
, char *props
)
218 ps
.SetMultiple(props
);
219 WindowAccessor
wa(window
, ps
);
222 for (; words
[nWL
]; nWL
++) ;
223 WordList
** wl
= new WordList
* [nWL
+ 1];
227 wl
[i
] = new WordList();
228 wl
[i
]->Set(words
[i
]);
232 ColorizeHaskellDoc(startPos
, length
, initStyle
, wl
, wa
);
234 for (i
=nWL
-1;i
>=0;i
--)
239 void EXT_LEXER_DECL
Fold (unsigned int lexer
, unsigned int startPos
, int length
, int initStyle
,
240 char *words
[], WindowID window
, char *props
)
245 int EXT_LEXER_DECL
GetLexerCount()
250 void EXT_LEXER_DECL
GetLexerName(unsigned int Index
, char *name
, int buflength
)
254 int n
= strlen(LexerName
);
257 memcpy(name
, LexerName
, n
), name
[n
] = '\0';
262 LexerModule
lmHaskell(SCLEX_HASKELL
, ColorizeHaskellDoc
, "haskell");