OSDN Git Service

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