xref: /Universal-ctags/peg/elm_pre.h (revision fa5642e4dd4866485c417ba4997bf6e2646e8441)
1 /*
2  *   Copyright (c) 2022 Nik Silver
3  *
4  *   This source code is released for free distribution under the terms of the
5  *   GNU General Public License version 2 or (at your option) any later version.
6  *
7  *   This module contains macros, data decls and prototypes to generate tags for Elm.
8  */
9 
10 /*
11  *   INCLUDE FILES
12  */
13 
14 #include "kind.h"
15 #include "peg_common.h"
16 
17 /*
18  * This allows us to save and restore the module scope.
19  * We want to do this because it's unhelpful to say that an imported item
20  * is the scope of the importing module.
21  */
22 
23 // Remember the scope of the module tag. But at first there is none (CORK_NIL).
24 static int elm_module_scope_index;
25 
26 #define ELM_INIT_MODULE_SCOPE \
27 	elm_module_scope_index = CORK_NIL
28 #define ELM_SAVE_MODULE_SCOPE \
29 	if (elm_module_scope_index != CORK_NIL) { \
30 		POP_SCOPE (auxil); \
31 	}
32 #define ELM_RESTORE_MODULE_SCOPE \
33 	if (elm_module_scope_index != CORK_NIL) { \
34 		SET_SCOPE (auxil, elm_module_scope_index); \
35 	} else { \
36 		POP_SCOPE (auxil); \
37 	}
38 
39 /*
40  *   DATA DECLARATIONS
41  */
42 typedef enum {
43 	K_MODULE,
44 	K_NAMESPACE,
45 	K_TYPE,
46 	K_CONSTRUCTOR,
47 	K_ALIAS,
48 	K_PORT,
49 	K_FUNCTION,
50 	COUNT_KINDS,
51 } ElmKind;
52 
53 /* We only define roles which aren't def(ined)
54  */
55 typedef enum {
56 	ELM_MODULE_IMPORTED,
57 } elmModuleRoles;
58 
59 static roleDefinition ElmModuleRoles [] = {
60 	{ true, "imported", "module imported" },
61 };
62 
63 #define define_elm_role(NAME,Name)							\
64 	typedef enum {											\
65 		ELM_##NAME##_EXPOSED,								\
66 	} elm##Name##Roleds;									\
67 	static roleDefinition Elm##Name##Roles [] = {			\
68 		{ true, "exposed", "item exposed from a module" },	\
69 	}
70 define_elm_role(TYPE,Type);
71 define_elm_role(CONSTRUCTOR,Constructor);
72 define_elm_role(FUNCTION,Function);
73 
74 typedef enum {
75 	F_MODULENAME,
76 	COUNT_FIELDS,
77 } ElmField;
78 
79 static fieldDefinition ElmFields [COUNT_FIELDS] = {
80 	{ .name        = "moduleName",
81 	  .description = "actual name of renamed module",
82 	  .enabled     = true },
83 };
84 
85 /* Use referenceOnly = true when a tag must always appear
86  * as role that's not def(ined).
87  */
88 static kindDefinition ElmKinds [COUNT_KINDS] = {
89 	{ true, 'm', "module", "modules",
90 	  .referenceOnly = false, ATTACH_ROLES (ElmModuleRoles) },
91 	{ true, 'n', "namespace", "modules renamed", },
92 	{ true, 't', "type", "types",
93 	  .referenceOnly = false, ATTACH_ROLES (ElmTypeRoles) },
94 	{ true, 'c', "constructor", "constructors",
95 	  .referenceOnly = false, ATTACH_ROLES (ElmConstructorRoles) },
96 	{ true, 'a', "alias", "aliases", },
97 	{ true, 'p', "port", "ports", },
98 	{ true, 'f', "function", "functions",
99 	  .referenceOnly = false, ATTACH_ROLES (ElmFunctionRoles) },
100 };
101 
102 struct parserCtx {
103 	struct parserBaseCtx base;
104 	vString *customType;
105 	vString *consSubtype;
106 };
107 
108 /*
109 *   FUNCTION PROTOTYPES
110 */
111 #define USE_KIND_STACK KIND_GHOST_INDEX
112 static int makeElmTag (struct parserCtx *auxil, const char *name, long offset, int kind, int role);
113 static int makeElmTagSettingScope (struct parserCtx *auxil, const char *name, long offset, int kind, int role);
114 static void addElmSignature(int scope_index, const char *sig);
115 static void addElmTypeRef(int scope_index, const char *str);
116 static void initElmConstructorFields (struct parserCtx *auxil, const char *name);
117 static void initElmConstructorSubtypeFields (struct parserCtx *auxil);
118 static void addElmConstructorSubtype (struct parserCtx *auxil, const char *name);
119 static void addElmConstructorTypeRef (struct parserCtx *auxil, int tag_index);
120 static void tidyElmConstructorFields (struct parserCtx *auxil);
121 static vString *collapseWhitespace (const char *sig);
122