2 * Copyright (c) 2003, Peter Strand <peter@zarquon.se>
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License version 2 or (at your opinion) any later version.
7 * This module contains functions for generating tags for Haskell language
8 * files (https://en.wikipedia.org/wiki/Haskell_(programming_language)).
10 * Does not handle operators or infix definitions like:
20 #include "general.h" /* must always come first */
34 K_TYPE
, K_CONSTRUCTOR
, K_FUNCTION
, K_MODULE
37 static kindDefinition HaskellKinds
[] = {
38 { true, 't', "type", "types" },
39 { true, 'c', "constructor", "type constructors" },
40 { true, 'f', "function", "functions" },
41 { true, 'm', "module", "modules"}
45 typedef const unsigned char *custr
;
48 * FUNCTION DEFINITIONS
52 static void skip_rest_of_line(void)
56 c
= getcFromInputFile();
57 } while (c
!= EOF
&& c
!= '\n');
60 static int get_line(char *buf
)
65 c
= getcFromInputFile();
67 } while (c
!= EOF
&& c
!= '\n' && i
< 1000);
72 static int get_next_char(void)
75 c
= getcFromInputFile();
78 nxt
= getcFromInputFile();
81 ungetcToInputFile(nxt
);
83 if (c
== '-' && nxt
== '-') {
85 return get_next_char();
87 if (c
== '{' && nxt
== '-') {
92 } while (! (c
== EOF
|| (last
== '-' && c
== '}')));
93 return get_next_char();
98 static void add_tag(const char *token
, haskellKind kind
, vString
*name
)
101 for (i
= 0; token
[i
] != '\0'; ++i
)
102 vStringPut(name
, token
[i
]);
104 makeSimpleTag(name
, kind
);
108 static int isident(char c
)
110 return isalnum(c
) || c
== '_' || c
== '\'' || c
== '$';
113 static int get_token(char *token
, int n
)
115 int c
= getcFromInputFile();
117 while (c
!= EOF
&& isident(c
) && i
< 1000) {
120 c
= getcFromInputFile();
126 ungetcToInputFile(c
);
133 enum Find_State
{ Find_Eq
, Find_Constr
, Get_Extr
, Find_Extr
, Find_Bar
};
135 static int inside_datatype(vString
*name
)
137 enum Find_State st
= Find_Eq
;
148 if (! (c
== ' ' || c
== '\t')) {
152 } while (c
!= EOF
&& c
!= '=');
155 else if (st
== Find_Constr
)
159 } while (isspace(c
));
165 if (!get_token(token
, 1))
167 add_tag(token
, K_CONSTRUCTOR
, name
);
170 else if (st
== Find_Extr
)
177 else if (c
== '\n') {
179 if (! (c
== ' ' || c
== '\t')) {
183 else if (!isspace(c
))
186 else if (st
== Get_Extr
)
190 } while (isspace(c
));
195 add_tag(token
, K_FUNCTION
, name
);
202 } while (c
!= EOF
&& c
!= ',');
204 else if (st
== Find_Bar
)
210 if (! (c
== ' ' || c
== '\t')) {
214 } while (c
!= EOF
&& c
!= '|');
221 static void findHaskellTags (int is_literate
)
223 vString
*name
= vStringNew ();
224 char token
[1001], arg
[1001];
226 int in_tex_lit_code
= 0;
241 if (is_literate
&& !in_tex_lit_code
) {
243 c
= getcFromInputFile();
256 } else if (c
== '\\') {
257 int n
= get_line(token
);
258 if (strncmp(token
, "begin{code}", 11) == 0) {
263 if (n
> 0 && token
[n
-1] != '\n')
275 if (is_literate
&& in_tex_lit_code
&& c
== '\\') {
277 if (strncmp(token
, "end{code}", 9) == 0) {
289 if (!get_token(token
, 1)) {
294 if ((c
= getcFromInputFile()) == EOF
)
296 } while (c
== ' ' || c
== '\t');
299 if (strcmp(token
, "data") == 0 || strcmp(token
, "newtype") == 0) {
300 add_tag(arg
, K_TYPE
, name
);
301 c
= inside_datatype(name
);
304 if (strcmp(token
, "type") == 0)
305 add_tag(arg
, K_TYPE
, name
);
306 else if (strcmp(token
, "module") == 0)
307 add_tag(arg
, K_MODULE
, name
);
308 else if (strcmp(token
, "instance") == 0 ||
309 strcmp(token
, "foreign") == 0 ||
310 strcmp(token
, "import") == 0)
314 add_tag(token
, K_FUNCTION
, name
);
322 static void findNormalHaskellTags (void)
327 static void findLiterateHaskellTags (void)
332 extern parserDefinition
* HaskellParser (void)
334 static const char *const extensions
[] = { "hs", NULL
};
335 parserDefinition
* def
= parserNew ("Haskell");
337 def
->kindTable
= HaskellKinds
;
338 def
->kindCount
= ARRAY_SIZE(HaskellKinds
);
339 def
->extensions
= extensions
;
340 def
->parser
= findNormalHaskellTags
;
344 extern parserDefinition
* LiterateHaskellParser (void)
346 static const char *const extensions
[] = { "lhs", NULL
};
347 parserDefinition
* def
= parserNew ("LiterateHaskell");
348 def
->kindTable
= HaskellKinds
;
349 def
->kindCount
= ARRAY_SIZE(HaskellKinds
);
350 def
->extensions
= extensions
;
351 def
->parser
= findLiterateHaskellTags
;