1 /*
2 * Copyright (c) 2021 Jan Dolinár
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 functions to generate tags for Kotlin.
8 */
9
10 /*
11 * INCLUDE FILES
12 */
13 #include "parse.h"
14 #include "trace.h"
15
16 /*
17 * FUNCTION DEFINITIONS
18 */
getcFromKotlinFile(struct parserCtx * auxil)19 static int getcFromKotlinFile(struct parserCtx *auxil)
20 {
21 int c = getcFromInputFile();
22 if (auxil->parenthesis_level > 0 && (c == '\r' || c == '\n'))
23 {
24 return ' ';
25 }
26 return c;
27 }
28
makeKotlinTag(struct parserCtx * auxil,const char * name,long offset,bool pushScope)29 static void makeKotlinTag (struct parserCtx *auxil, const char *name, long offset, bool pushScope)
30 {
31 int k = PEEK_KIND(auxil);
32 if (k == K_IGNORE) return;
33 tagEntryInfo e;
34 char *stripped = NULL;
35 if (*name != '`')
36 {
37 initTagEntry(&e, name, k);
38 } else
39 {
40 size_t len = strlen(name);
41 Assert(len >= 2);
42 len -= 2;
43 stripped = eStrndup (name + 1, len);
44 initTagEntry(&e, stripped, k);
45 }
46 e.lineNumber = getInputLineNumberForFileOffset (offset);
47 e.filePosition = getInputFilePositionForLine (e.lineNumber);
48 e.extensionFields.scopeIndex = BASE_SCOPE(auxil);
49 int scope_index = makeTagEntry (&e);
50 if (pushScope)
51 {
52 SET_SCOPE(auxil, scope_index);
53 }
54 if (stripped)
55 eFree (stripped);
56 }
57
58 #ifdef DEBUG
reportFailure(struct parserCtx * auxil,long offset)59 static void reportFailure(struct parserCtx *auxil, long offset)
60 {
61 if(auxil->fail_offset < 0)
62 {
63 auxil->fail_offset = offset;
64 }
65 }
66
resetFailure(struct parserCtx * auxil,long offset)67 static void resetFailure(struct parserCtx *auxil, long offset)
68 {
69 if(auxil->fail_offset >= 0)
70 {
71 unsigned long startLine = getInputLineNumberForFileOffset(auxil->fail_offset);
72 unsigned long endLine = getInputLineNumberForFileOffset(offset-1);
73 if (startLine == endLine)
74 {
75 TRACE_PRINT("Failed to parse '%s' at line %lu!\n", getInputFileName(), startLine);
76 } else
77 {
78 TRACE_PRINT("Failed to parse '%s' from line %lu to line %lu!\n", getInputFileName(), startLine, endLine);
79 }
80 }
81 auxil->fail_offset = -1;
82 }
83 #endif
84
ctxInit(struct parserCtx * auxil)85 static void ctxInit (struct parserCtx *auxil)
86 {
87 BASE_INIT(auxil, K_INTERFACE);
88 auxil->parenthesis_level = 0;
89 #ifdef DEBUG
90 auxil->fail_offset = -1;
91 #endif
92 }
93
ctxFini(struct parserCtx * auxil)94 static void ctxFini (struct parserCtx *auxil)
95 {
96 BASE_FINI(auxil);
97 }
98
findKotlinTags(void)99 static void findKotlinTags (void)
100 {
101 struct parserCtx auxil;
102
103 ctxInit (&auxil);
104 pkotlin_context_t *pctx = pkotlin_create(&auxil);
105
106 while (pkotlin_parse(pctx, NULL) && (!BASE_ERROR(&auxil)) );
107
108 pkotlin_destroy(pctx);
109 ctxFini (&auxil);
110 }
111
KotlinParser(void)112 extern parserDefinition* KotlinParser (void)
113 {
114 static const char *const extensions [] = { "kt", "kts", NULL };
115 parserDefinition* def = parserNew ("Kotlin");
116 def->kindTable = KotlinKinds;
117 def->kindCount = ARRAY_SIZE (KotlinKinds);
118 def->extensions = extensions;
119 def->parser = findKotlinTags;
120 def->useCork = true;
121 def->requestAutomaticFQTag = true;
122 def->defaultScopeSeparator = ".";
123 def->enabled = true;
124 return def;
125 }
126