Fix file names of generated tags files for C, PHP and Python
[geany-mirror.git] / src / tagmanager / tm_parser.c
blob0359df4a00ef6d836c21078424a0c8733f94eda6
1 /*
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"
24 #include <string.h>
27 typedef struct
29 const gchar kind;
30 TMTagType type;
31 } TMParserMapEntry;
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},
39 {'g', tm_tag_enum_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},
50 /* C++, same as C */
51 #define map_CPP map_C
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},
60 {'g', tm_tag_enum_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[] = {
74 {'c', tm_tag_enum_t},
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},
492 typedef struct
494 TMParserMapEntry *entries;
495 guint size;
496 } TMParserMap;
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[] = {
502 MAP_ENTRY(C),
503 MAP_ENTRY(CPP),
504 MAP_ENTRY(JAVA),
505 MAP_ENTRY(MAKEFILE),
506 MAP_ENTRY(PASCAL),
507 MAP_ENTRY(PERL),
508 MAP_ENTRY(PHP),
509 MAP_ENTRY(PYTHON),
510 MAP_ENTRY(LATEX),
511 MAP_ENTRY(ASM),
512 MAP_ENTRY(CONF),
513 MAP_ENTRY(SQL),
514 MAP_ENTRY(DOCBOOK),
515 MAP_ENTRY(ERLANG),
516 MAP_ENTRY(CSS),
517 MAP_ENTRY(RUBY),
518 MAP_ENTRY(TCL),
519 MAP_ENTRY(SH),
520 MAP_ENTRY(D),
521 MAP_ENTRY(FORTRAN),
522 MAP_ENTRY(FERITE),
523 MAP_ENTRY(DIFF),
524 MAP_ENTRY(VHDL),
525 MAP_ENTRY(LUA),
526 MAP_ENTRY(JAVASCRIPT),
527 MAP_ENTRY(HASKELL),
528 MAP_ENTRY(CSHARP),
529 MAP_ENTRY(FREEBASIC),
530 MAP_ENTRY(HAXE),
531 MAP_ENTRY(REST),
532 MAP_ENTRY(HTML),
533 MAP_ENTRY(F77),
534 MAP_ENTRY(GLSL),
535 MAP_ENTRY(MATLAB),
536 MAP_ENTRY(VALA),
537 MAP_ENTRY(ACTIONSCRIPT),
538 MAP_ENTRY(NSIS),
539 MAP_ENTRY(MARKDOWN),
540 MAP_ENTRY(TXT2TAGS),
541 MAP_ENTRY(ABC),
542 MAP_ENTRY(VERILOG),
543 MAP_ENTRY(R),
544 MAP_ENTRY(COBOL),
545 MAP_ENTRY(OBJC),
546 MAP_ENTRY(ASCIIDOC),
547 MAP_ENTRY(ABAQUS),
548 MAP_ENTRY(RUST),
549 MAP_ENTRY(GO),
550 MAP_ENTRY(JSON),
551 MAP_ENTRY(ZEPHIR),
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];
561 guint i;
563 for (i = 0; i < map->size; i++)
565 TMParserMapEntry *entry = &map->entries[i];
567 if (entry->kind == kind)
568 return entry->type;
570 return tm_tag_undef_t;
574 gchar tm_parser_get_tag_kind(TMTagType type, TMParserType lang)
576 TMParserMap *map = &parser_map[lang];
577 guint i;
579 for (i = 0; i < map->size; i++)
581 TMParserMapEntry *entry = &map->entries[i];
583 if (entry->type == type)
584 return entry->kind;
586 return '\0';
590 void tm_parser_verify_type_mappings(void)
592 TMParserType lang;
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];
602 guint i;
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))
611 continue;
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;
622 guint j;
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])
628 ctags_found = TRUE;
629 /* check that for every type in ctags there's a type in TM */
630 if (map->entries[j].kind == kinds[i])
631 tm_found = TRUE;
632 if (ctags_found && tm_found)
633 break;
635 if (!ctags_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));
638 if (!tm_found)
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));