2 * tm_parser.c - this file is part of Geany, a fast and lightweight IDE
4 * Copyright 2016 Jiri Techet <techet(at)gmail(dot)com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "tm_parser.h"
22 #include "tm_ctags_wrappers.h"
34 static TMParserMapEntry map_C
[] = {
35 {'c', tm_tag_class_t
},
36 {'d', tm_tag_macro_t
},
37 {'e', tm_tag_enumerator_t
},
38 {'f', tm_tag_function_t
},
40 {'m', tm_tag_member_t
},
41 {'n', tm_tag_namespace_t
},
42 {'p', tm_tag_prototype_t
},
43 {'s', tm_tag_struct_t
},
44 {'t', tm_tag_typedef_t
},
45 {'u', tm_tag_union_t
},
46 {'v', tm_tag_variable_t
},
47 {'x', tm_tag_externvar_t
},
53 static TMParserMapEntry map_JAVA
[] = {
54 {'c', tm_tag_class_t
},
55 {'f', tm_tag_field_t
},
56 {'i', tm_tag_interface_t
},
57 {'m', tm_tag_method_t
},
58 {'p', tm_tag_package_t
},
59 {'e', tm_tag_enumerator_t
},
63 static TMParserMapEntry map_MAKEFILE
[] = {
64 {'m', tm_tag_macro_t
},
65 {'t', tm_tag_function_t
},
68 static TMParserMapEntry map_PASCAL
[] = {
69 {'f', tm_tag_function_t
},
70 {'p', tm_tag_function_t
},
73 static TMParserMapEntry map_PERL
[] = {
75 {'f', tm_tag_other_t
},
76 {'l', tm_tag_macro_t
},
77 {'p', tm_tag_package_t
},
78 {'s', tm_tag_function_t
},
79 {'d', tm_tag_prototype_t
},
82 static TMParserMapEntry map_PHP
[] = {
83 {'c', tm_tag_class_t
},
84 {'d', tm_tag_macro_t
},
85 {'f', tm_tag_function_t
},
86 {'i', tm_tag_interface_t
},
87 {'l', tm_tag_undef_t
},
88 {'n', tm_tag_namespace_t
},
89 {'t', tm_tag_struct_t
},
90 {'v', tm_tag_variable_t
},
93 static TMParserMapEntry map_PYTHON
[] = {
94 {'c', tm_tag_class_t
},
95 {'f', tm_tag_function_t
},
96 {'m', tm_tag_method_t
},
97 {'v', tm_tag_variable_t
},
98 /* defined as externvar to get those excluded as forward type in symbols.c:goto_tag()
99 * so we can jump to the real implementation (if known) instead of to the import statement */
100 {'x', tm_tag_externvar_t
},
103 /* different parser than tex.c from universal-ctags */
104 static TMParserMapEntry map_LATEX
[] = {
105 {'f', tm_tag_function_t
},
106 {'c', tm_tag_class_t
},
107 {'m', tm_tag_member_t
},
108 {'d', tm_tag_macro_t
},
109 {'v', tm_tag_variable_t
},
110 {'n', tm_tag_namespace_t
},
111 {'s', tm_tag_struct_t
},
114 static TMParserMapEntry map_ASM
[] = {
115 {'d', tm_tag_macro_t
},
116 {'l', tm_tag_namespace_t
},
117 {'m', tm_tag_function_t
},
118 {'t', tm_tag_struct_t
},
121 /* not in universal-ctags */
122 static TMParserMapEntry map_CONF
[] = {
123 {'n', tm_tag_namespace_t
},
124 {'m', tm_tag_macro_t
},
127 static TMParserMapEntry map_SQL
[] = {
128 {'c', tm_tag_undef_t
},
129 {'d', tm_tag_prototype_t
},
130 {'f', tm_tag_function_t
},
131 {'F', tm_tag_field_t
},
132 {'l', tm_tag_undef_t
},
133 {'L', tm_tag_undef_t
},
134 {'P', tm_tag_package_t
},
135 {'p', tm_tag_namespace_t
},
136 {'r', tm_tag_undef_t
},
137 {'s', tm_tag_undef_t
},
138 {'t', tm_tag_class_t
},
139 {'T', tm_tag_macro_t
},
140 {'v', tm_tag_variable_t
},
141 {'i', tm_tag_struct_t
},
142 {'e', tm_tag_undef_t
},
143 {'U', tm_tag_undef_t
},
144 {'R', tm_tag_undef_t
},
145 {'D', tm_tag_undef_t
},
146 {'V', tm_tag_member_t
},
147 {'n', tm_tag_undef_t
},
148 {'x', tm_tag_undef_t
},
149 {'y', tm_tag_undef_t
},
150 {'z', tm_tag_undef_t
},
153 /* not in universal-ctags */
154 static TMParserMapEntry map_DOCBOOK
[] = {
155 {'f', tm_tag_function_t
},
156 {'c', tm_tag_class_t
},
157 {'m', tm_tag_member_t
},
158 {'d', tm_tag_macro_t
},
159 {'v', tm_tag_variable_t
},
160 {'s', tm_tag_struct_t
},
163 static TMParserMapEntry map_ERLANG
[] = {
164 {'d', tm_tag_macro_t
},
165 {'f', tm_tag_function_t
},
166 {'m', tm_tag_undef_t
},
167 {'r', tm_tag_struct_t
},
168 {'t', tm_tag_typedef_t
},
171 static TMParserMapEntry map_CSS
[] = {
172 {'c', tm_tag_class_t
},
173 {'s', tm_tag_struct_t
},
174 {'i', tm_tag_variable_t
},
177 static TMParserMapEntry map_RUBY
[] = {
178 {'c', tm_tag_class_t
},
179 {'f', tm_tag_method_t
},
180 {'m', tm_tag_namespace_t
},
181 {'F', tm_tag_member_t
},
184 static TMParserMapEntry map_TCL
[] = {
185 {'c', tm_tag_class_t
},
186 {'m', tm_tag_member_t
},
187 {'p', tm_tag_function_t
},
188 {'n', tm_tag_namespace_t
},
191 static TMParserMapEntry map_SH
[] = {
192 {'f', tm_tag_function_t
},
195 static TMParserMapEntry map_D
[] = {
196 {'c', tm_tag_class_t
},
197 {'e', tm_tag_enumerator_t
},
198 {'f', tm_tag_function_t
},
199 {'g', tm_tag_enum_t
},
200 {'i', tm_tag_interface_t
},
201 {'m', tm_tag_member_t
},
202 {'n', tm_tag_namespace_t
},
203 {'p', tm_tag_prototype_t
},
204 {'s', tm_tag_struct_t
},
205 {'t', tm_tag_typedef_t
},
206 {'u', tm_tag_union_t
},
207 {'v', tm_tag_variable_t
},
208 {'x', tm_tag_externvar_t
},
211 static TMParserMapEntry map_DIFF
[] = {
212 {'f', tm_tag_function_t
},
215 /* different parser than in universal-ctags */
216 static TMParserMapEntry map_VHDL
[] = {
217 {'c', tm_tag_variable_t
},
218 {'t', tm_tag_typedef_t
},
219 {'v', tm_tag_variable_t
},
220 {'a', tm_tag_undef_t
},
221 {'s', tm_tag_variable_t
},
222 {'f', tm_tag_function_t
},
223 {'p', tm_tag_function_t
},
224 {'k', tm_tag_member_t
},
225 {'l', tm_tag_namespace_t
},
226 {'m', tm_tag_member_t
},
227 {'n', tm_tag_class_t
},
228 {'o', tm_tag_struct_t
},
229 {'u', tm_tag_undef_t
},
230 {'b', tm_tag_member_t
},
231 {'A', tm_tag_typedef_t
},
234 static TMParserMapEntry map_LUA
[] = {
235 {'f', tm_tag_function_t
},
238 static TMParserMapEntry map_JAVASCRIPT
[] = {
239 {'f', tm_tag_function_t
},
240 {'c', tm_tag_class_t
},
241 {'m', tm_tag_method_t
},
242 {'p', tm_tag_member_t
},
243 {'C', tm_tag_macro_t
},
244 {'v', tm_tag_variable_t
},
247 /* not in universal-ctags */
248 static TMParserMapEntry map_HASKELL
[] = {
249 {'t', tm_tag_typedef_t
},
250 {'c', tm_tag_macro_t
},
251 {'f', tm_tag_function_t
},
252 {'m', tm_tag_namespace_t
},
255 static TMParserMapEntry map_CSHARP
[] = {
256 {'c', tm_tag_class_t
},
257 {'d', tm_tag_macro_t
},
258 {'e', tm_tag_enumerator_t
},
259 {'E', tm_tag_undef_t
},
260 {'f', tm_tag_field_t
},
261 {'g', tm_tag_enum_t
},
262 {'i', tm_tag_interface_t
},
263 {'l', tm_tag_undef_t
},
264 {'m', tm_tag_method_t
},
265 {'n', tm_tag_namespace_t
},
266 {'p', tm_tag_undef_t
},
267 {'s', tm_tag_struct_t
},
268 {'t', tm_tag_typedef_t
},
271 static TMParserMapEntry map_FREEBASIC
[] = {
272 {'c', tm_tag_macro_t
},
273 {'f', tm_tag_function_t
},
274 {'l', tm_tag_namespace_t
},
275 {'t', tm_tag_struct_t
},
276 {'v', tm_tag_variable_t
},
277 {'g', tm_tag_externvar_t
},
280 /* not in universal-ctags */
281 static TMParserMapEntry map_HAXE
[] = {
282 {'m', tm_tag_method_t
},
283 {'c', tm_tag_class_t
},
284 {'e', tm_tag_enum_t
},
285 {'v', tm_tag_variable_t
},
286 {'i', tm_tag_interface_t
},
287 {'t', tm_tag_typedef_t
},
290 /* not in universal-ctags */
291 static TMParserMapEntry map_REST
[] = {
292 {'n', tm_tag_namespace_t
},
293 {'m', tm_tag_member_t
},
294 {'d', tm_tag_macro_t
},
295 {'v', tm_tag_variable_t
},
298 static TMParserMapEntry map_HTML
[] = {
299 {'a', tm_tag_member_t
},
300 {'f', tm_tag_function_t
},
301 {'n', tm_tag_namespace_t
},
302 {'c', tm_tag_class_t
},
303 {'v', tm_tag_variable_t
},
306 static TMParserMapEntry map_F77
[] = {
307 {'b', tm_tag_undef_t
},
308 {'c', tm_tag_macro_t
},
309 {'e', tm_tag_undef_t
},
310 {'f', tm_tag_function_t
},
311 {'i', tm_tag_interface_t
},
312 {'k', tm_tag_member_t
},
313 {'l', tm_tag_undef_t
},
314 {'L', tm_tag_undef_t
},
315 {'m', tm_tag_namespace_t
},
316 {'n', tm_tag_undef_t
},
317 {'p', tm_tag_struct_t
},
318 {'s', tm_tag_method_t
},
319 {'t', tm_tag_class_t
},
320 {'v', tm_tag_variable_t
},
321 {'E', tm_tag_enum_t
},
322 {'N', tm_tag_enumerator_t
},
325 #define map_FORTRAN map_F77
327 #define map_FERITE map_C
329 /* different parser than in universal-ctags */
330 static TMParserMapEntry map_MATLAB
[] = {
331 {'f', tm_tag_function_t
},
332 {'s', tm_tag_struct_t
},
335 #define map_GLSL map_C
337 /* not in universal-ctags */
338 static TMParserMapEntry map_VALA
[] = {
339 {'c', tm_tag_class_t
},
340 {'d', tm_tag_macro_t
},
341 {'e', tm_tag_enumerator_t
},
342 {'f', tm_tag_field_t
},
343 {'g', tm_tag_enum_t
},
344 {'i', tm_tag_interface_t
},
345 {'l', tm_tag_undef_t
},
346 {'m', tm_tag_method_t
},
347 {'n', tm_tag_namespace_t
},
348 {'p', tm_tag_undef_t
},
349 {'S', tm_tag_undef_t
},
350 {'s', tm_tag_struct_t
},
353 /* not in universal-ctags */
354 static TMParserMapEntry map_ACTIONSCRIPT
[] = {
355 {'f', tm_tag_function_t
},
356 {'l', tm_tag_field_t
},
357 {'v', tm_tag_variable_t
},
358 {'m', tm_tag_macro_t
},
359 {'c', tm_tag_class_t
},
360 {'i', tm_tag_interface_t
},
361 {'p', tm_tag_package_t
},
362 {'o', tm_tag_other_t
},
363 {'r', tm_tag_prototype_t
},
366 /* not in universal-ctags */
367 static TMParserMapEntry map_NSIS
[] = {
368 {'n', tm_tag_namespace_t
},
369 {'f', tm_tag_function_t
},
370 {'v', tm_tag_variable_t
},
373 /* not in universal-ctags */
374 static TMParserMapEntry map_MARKDOWN
[] = {
375 {'v', tm_tag_variable_t
},
378 /* not in universal-ctags */
379 static TMParserMapEntry map_TXT2TAGS
[] = {
380 {'m', tm_tag_member_t
},
383 /* not in universal-ctags */
384 static TMParserMapEntry map_ABC
[] = {
385 {'m', tm_tag_member_t
},
386 {'s', tm_tag_struct_t
},
389 static TMParserMapEntry map_VERILOG
[] = {
390 {'c', tm_tag_variable_t
},
391 {'e', tm_tag_typedef_t
},
392 {'f', tm_tag_function_t
},
393 {'m', tm_tag_class_t
},
394 {'n', tm_tag_variable_t
},
395 {'p', tm_tag_variable_t
},
396 {'r', tm_tag_variable_t
},
397 {'t', tm_tag_function_t
},
400 static TMParserMapEntry map_R
[] = {
401 {'f', tm_tag_function_t
},
402 {'l', tm_tag_other_t
},
403 {'s', tm_tag_other_t
},
406 static TMParserMapEntry map_COBOL
[] = {
407 {'d', tm_tag_variable_t
},
408 {'f', tm_tag_function_t
},
409 {'g', tm_tag_struct_t
},
410 {'p', tm_tag_macro_t
},
411 {'P', tm_tag_class_t
},
412 {'s', tm_tag_namespace_t
},
415 static TMParserMapEntry map_OBJC
[] = {
416 {'i', tm_tag_interface_t
},
417 {'I', tm_tag_undef_t
},
418 {'P', tm_tag_undef_t
},
419 {'m', tm_tag_method_t
},
420 {'c', tm_tag_class_t
},
421 {'v', tm_tag_variable_t
},
422 {'F', tm_tag_field_t
},
423 {'f', tm_tag_function_t
},
424 {'p', tm_tag_undef_t
},
425 {'t', tm_tag_typedef_t
},
426 {'s', tm_tag_struct_t
},
427 {'e', tm_tag_enum_t
},
428 {'M', tm_tag_macro_t
},
431 /* not in universal-ctags */
432 static TMParserMapEntry map_ASCIIDOC
[] = {
433 {'n', tm_tag_namespace_t
},
434 {'m', tm_tag_member_t
},
435 {'d', tm_tag_macro_t
},
436 {'v', tm_tag_variable_t
},
437 {'s', tm_tag_struct_t
},
440 /* not in universal-ctags */
441 static TMParserMapEntry map_ABAQUS
[] = {
442 {'c', tm_tag_class_t
},
443 {'m', tm_tag_member_t
},
444 {'n', tm_tag_interface_t
},
447 static TMParserMapEntry map_RUST
[] = {
448 {'n', tm_tag_namespace_t
},
449 {'s', tm_tag_struct_t
},
450 {'i', tm_tag_interface_t
},
451 {'c', tm_tag_class_t
},
452 {'f', tm_tag_function_t
},
453 {'g', tm_tag_enum_t
},
454 {'t', tm_tag_typedef_t
},
455 {'v', tm_tag_variable_t
},
456 {'M', tm_tag_macro_t
},
457 {'m', tm_tag_field_t
},
458 {'e', tm_tag_enumerator_t
},
459 {'F', tm_tag_method_t
},
462 static TMParserMapEntry map_GO
[] = {
463 {'p', tm_tag_namespace_t
},
464 {'f', tm_tag_function_t
},
465 {'c', tm_tag_macro_t
},
466 {'t', tm_tag_typedef_t
},
467 {'v', tm_tag_variable_t
},
468 {'s', tm_tag_struct_t
},
469 {'i', tm_tag_interface_t
},
470 {'m', tm_tag_member_t
},
473 static TMParserMapEntry map_JSON
[] = {
474 {'o', tm_tag_member_t
},
475 {'a', tm_tag_member_t
},
476 {'n', tm_tag_member_t
},
477 {'s', tm_tag_member_t
},
478 {'b', tm_tag_member_t
},
479 {'z', tm_tag_member_t
},
482 /* Zephir, same as PHP */
483 #define map_ZEPHIR map_PHP
485 /* not in universal-ctags */
486 static TMParserMapEntry map_POWERSHELL
[] = {
487 {'f', tm_tag_function_t
},
488 {'v', tm_tag_variable_t
},
494 TMParserMapEntry
*entries
;
498 #define MAP_ENTRY(lang) [TM_PARSER_##lang] = {map_##lang, G_N_ELEMENTS(map_##lang)}
500 /* keep in sync with TM_PARSER_* definitions in the header */
501 static TMParserMap parser_map
[] = {
526 MAP_ENTRY(JAVASCRIPT
),
529 MAP_ENTRY(FREEBASIC
),
537 MAP_ENTRY(ACTIONSCRIPT
),
552 MAP_ENTRY(POWERSHELL
),
554 /* make sure the parser map is consistent and complete */
555 G_STATIC_ASSERT(G_N_ELEMENTS(parser_map
) == TM_PARSER_COUNT
);
558 TMTagType
tm_parser_get_tag_type(gchar kind
, TMParserType lang
)
560 TMParserMap
*map
= &parser_map
[lang
];
563 for (i
= 0; i
< map
->size
; i
++)
565 TMParserMapEntry
*entry
= &map
->entries
[i
];
567 if (entry
->kind
== kind
)
570 return tm_tag_undef_t
;
574 gchar
tm_parser_get_tag_kind(TMTagType type
, TMParserType lang
)
576 TMParserMap
*map
= &parser_map
[lang
];
579 for (i
= 0; i
< map
->size
; i
++)
581 TMParserMapEntry
*entry
= &map
->entries
[i
];
583 if (entry
->type
== type
)
590 void tm_parser_verify_type_mappings(void)
594 if (TM_PARSER_COUNT
> tm_ctags_get_lang_count())
595 g_error("More parsers defined in Geany than in ctags");
597 for (lang
= 0; lang
< TM_PARSER_COUNT
; lang
++)
599 const gchar
*kinds
= tm_ctags_get_lang_kinds(lang
);
600 TMParserMap
*map
= &parser_map
[lang
];
601 gchar presence_map
[256];
604 if (! map
->entries
|| map
->size
< 1)
605 g_error("No tag types in TM for %s, is the language listed in parser_map?",
606 tm_ctags_get_lang_name(lang
));
608 /* TODO: check also regex parser mappings. At the moment there's no way
609 * to access regex parser definitions in ctags */
610 if (tm_ctags_is_using_regex_parser(lang
))
613 if (map
->size
!= strlen(kinds
))
614 g_error("Different number of tag types in TM (%d) and ctags (%d) for %s",
615 map
->size
, (int)strlen(kinds
), tm_ctags_get_lang_name(lang
));
617 memset(presence_map
, 0, sizeof(presence_map
));
618 for (i
= 0; i
< map
->size
; i
++)
620 gboolean ctags_found
= FALSE
;
621 gboolean tm_found
= FALSE
;
624 for (j
= 0; j
< map
->size
; j
++)
626 /* check that for every type in TM there's a type in ctags */
627 if (map
->entries
[i
].kind
== kinds
[j
])
629 /* check that for every type in ctags there's a type in TM */
630 if (map
->entries
[j
].kind
== kinds
[i
])
632 if (ctags_found
&& tm_found
)
636 g_error("Tag type '%c' found in TM but not in ctags for %s",
637 map
->entries
[i
].kind
, tm_ctags_get_lang_name(lang
));
639 g_error("Tag type '%c' found in ctags but not in TM for %s",
640 kinds
[i
], tm_ctags_get_lang_name(lang
));
642 presence_map
[(unsigned char) map
->entries
[i
].kind
]++;
645 for (i
= 0; i
< sizeof(presence_map
); i
++)
647 if (presence_map
[i
] > 1)
648 g_error("Duplicate tag type '%c' found for %s",
649 (gchar
)i
, tm_ctags_get_lang_name(lang
));