16ae73029SMasatake YAMATO /*
26ae73029SMasatake YAMATO * Copyright (c) 2017, Masatake YAMATO
36ae73029SMasatake YAMATO *
46ae73029SMasatake YAMATO * This source code is released for free distribution under the terms of the
56ae73029SMasatake YAMATO * GNU General Public License version 2 or (at your option) any later version.
66ae73029SMasatake YAMATO *
76ae73029SMasatake YAMATO */
86ae73029SMasatake YAMATO
96ae73029SMasatake YAMATO #include "general.h" /* must always come first */
106ae73029SMasatake YAMATO #include "tcl.h"
116ae73029SMasatake YAMATO #include "entry.h"
12cecb4a16SMasatake YAMATO #include "param.h"
136ae73029SMasatake YAMATO #include "parse.h"
1494e60171SMasatake YAMATO #include "read.h"
1594e60171SMasatake YAMATO #include "keyword.h"
166ae73029SMasatake YAMATO
174952911fSMasatake YAMATO #include <string.h>
184952911fSMasatake YAMATO
194952911fSMasatake YAMATO
20e07c5f05SMasatake YAMATO struct itclSubparser {
21e07c5f05SMasatake YAMATO tclSubparser tcl;
22a87043aeSMasatake YAMATO bool foundITclNamespaceImported;
23e07c5f05SMasatake YAMATO };
24e07c5f05SMasatake YAMATO
2594e60171SMasatake YAMATO static scopeSeparator ITclGenericSeparators [] = {
26f92e6bf2SMasatake YAMATO { KIND_WILDCARD_INDEX, "::" },
2794e60171SMasatake YAMATO };
2894e60171SMasatake YAMATO
2994e60171SMasatake YAMATO enum ITclKind {
306ae73029SMasatake YAMATO K_CLASS,
316ae73029SMasatake YAMATO K_METHOD,
3294e60171SMasatake YAMATO K_VARIABLE,
3394e60171SMasatake YAMATO K_COMMON,
3494e60171SMasatake YAMATO K_PROC,
356ae73029SMasatake YAMATO };
366ae73029SMasatake YAMATO
376ae73029SMasatake YAMATO static kindDefinition ITclKinds[] = {
386ae73029SMasatake YAMATO { true, 'c', "class", "classes" },
3994e60171SMasatake YAMATO { true, 'm', "method", "methods",
4094e60171SMasatake YAMATO ATTACH_SEPARATORS(ITclGenericSeparators)},
4194e60171SMasatake YAMATO { true, 'v', "variable", "object-specific variables",
4294e60171SMasatake YAMATO ATTACH_SEPARATORS(ITclGenericSeparators)},
4394e60171SMasatake YAMATO { true, 'C', "common", "common variables",
4494e60171SMasatake YAMATO ATTACH_SEPARATORS(ITclGenericSeparators)},
4594e60171SMasatake YAMATO { true, 'p', "procedure", "procedures within the class namespace",
4694e60171SMasatake YAMATO ATTACH_SEPARATORS(ITclGenericSeparators)},
476ae73029SMasatake YAMATO };
486ae73029SMasatake YAMATO
4994e60171SMasatake YAMATO enum {
5094e60171SMasatake YAMATO KEYWORD_INHERIT,
5194e60171SMasatake YAMATO KEYWORD_METHOD,
5294e60171SMasatake YAMATO KEYWORD_PRIVATE,
5394e60171SMasatake YAMATO KEYWORD_PROTECTED,
5494e60171SMasatake YAMATO KEYWORD_PUBLIC,
5594e60171SMasatake YAMATO KEYWORD_VARIABLE,
5694e60171SMasatake YAMATO KEYWORD_COMMON,
5794e60171SMasatake YAMATO KEYWORD_PROC,
5894e60171SMasatake YAMATO };
5994e60171SMasatake YAMATO
6094e60171SMasatake YAMATO typedef int keywordId; /* to allow KEYWORD_NONE */
6194e60171SMasatake YAMATO
6294e60171SMasatake YAMATO static const keywordTable ITclKeywordTable[] = {
6394e60171SMasatake YAMATO /* keyword keyword ID */
6494e60171SMasatake YAMATO { "inherit", KEYWORD_INHERIT },
6594e60171SMasatake YAMATO { "method", KEYWORD_METHOD },
6694e60171SMasatake YAMATO { "private", KEYWORD_PRIVATE },
6794e60171SMasatake YAMATO { "protected", KEYWORD_PROTECTED },
6894e60171SMasatake YAMATO { "public", KEYWORD_PUBLIC },
6994e60171SMasatake YAMATO { "variable", KEYWORD_VARIABLE },
7094e60171SMasatake YAMATO { "common", KEYWORD_COMMON },
7194e60171SMasatake YAMATO { "proc", KEYWORD_PROC },
7294e60171SMasatake YAMATO };
7394e60171SMasatake YAMATO
74cecb4a16SMasatake YAMATO static bool itclForceUse;
75cecb4a16SMasatake YAMATO
resolveKeyword(vString * string)7694e60171SMasatake YAMATO static keywordId resolveKeyword (vString *string)
7794e60171SMasatake YAMATO {
7894e60171SMasatake YAMATO char *s = vStringValue (string);
7994e60171SMasatake YAMATO static langType lang = LANG_AUTO;
8094e60171SMasatake YAMATO
8194e60171SMasatake YAMATO if (lang == LANG_AUTO)
8294e60171SMasatake YAMATO lang = getInputLanguage ();
8394e60171SMasatake YAMATO
8494e60171SMasatake YAMATO return lookupKeyword (s, lang);
8594e60171SMasatake YAMATO }
8694e60171SMasatake YAMATO
parseInherit(tokenInfo * token,int r)8794e60171SMasatake YAMATO static void parseInherit (tokenInfo *token, int r)
8894e60171SMasatake YAMATO {
8994e60171SMasatake YAMATO vString *inherits = vStringNew ();
9094e60171SMasatake YAMATO
9194e60171SMasatake YAMATO do {
9294e60171SMasatake YAMATO tokenRead (token);
9394e60171SMasatake YAMATO if (tokenIsType (token, TCL_IDENTIFIER))
9494e60171SMasatake YAMATO {
9594e60171SMasatake YAMATO if (vStringLength(inherits) != 0)
9694e60171SMasatake YAMATO vStringPut (inherits, ',');
9794e60171SMasatake YAMATO vStringCat(inherits, token->string);
9894e60171SMasatake YAMATO }
9994e60171SMasatake YAMATO else if (tokenIsType(token, TCL_EOL))
10094e60171SMasatake YAMATO break;
10194e60171SMasatake YAMATO else
10294e60171SMasatake YAMATO {
10394e60171SMasatake YAMATO skipToEndOfTclCmdline (token);
10494e60171SMasatake YAMATO break;
10594e60171SMasatake YAMATO }
10694e60171SMasatake YAMATO } while (1);
10794e60171SMasatake YAMATO
10894e60171SMasatake YAMATO if (vStringLength(inherits) > 0)
10994e60171SMasatake YAMATO {
11094e60171SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (r);
11194e60171SMasatake YAMATO if (e)
11294e60171SMasatake YAMATO {
11394e60171SMasatake YAMATO e->extensionFields.inheritance = vStringDeleteUnwrap (inherits);
11494e60171SMasatake YAMATO return;
11594e60171SMasatake YAMATO }
11694e60171SMasatake YAMATO }
11794e60171SMasatake YAMATO
11894e60171SMasatake YAMATO vStringDelete (inherits);
11994e60171SMasatake YAMATO }
12094e60171SMasatake YAMATO
attachProtectionMaybe(tagEntryInfo * e,keywordId protection)12194e60171SMasatake YAMATO static void attachProtectionMaybe(tagEntryInfo *e, keywordId protection)
12294e60171SMasatake YAMATO {
12394e60171SMasatake YAMATO switch (protection)
12494e60171SMasatake YAMATO {
12594e60171SMasatake YAMATO case KEYWORD_PROTECTED:
1261c5b56fcSMasatake YAMATO e->extensionFields.access = "protected";
12794e60171SMasatake YAMATO break;
12894e60171SMasatake YAMATO case KEYWORD_PRIVATE:
1291c5b56fcSMasatake YAMATO e->extensionFields.access = "private";
13094e60171SMasatake YAMATO break;
13194e60171SMasatake YAMATO case KEYWORD_PUBLIC:
1321c5b56fcSMasatake YAMATO e->extensionFields.access = "public";
13394e60171SMasatake YAMATO break;
13494e60171SMasatake YAMATO }
13594e60171SMasatake YAMATO }
13694e60171SMasatake YAMATO
parseSubobject(tokenInfo * token,int parent,enum ITclKind kind,keywordId protection)13794e60171SMasatake YAMATO static void parseSubobject (tokenInfo *token, int parent, enum ITclKind kind, keywordId protection)
1386ae73029SMasatake YAMATO {
1396ae73029SMasatake YAMATO int r = CORK_NIL;
1406ae73029SMasatake YAMATO
14194e60171SMasatake YAMATO tokenRead (token);
14294e60171SMasatake YAMATO if (tokenIsType (token, TCL_IDENTIFIER))
14394e60171SMasatake YAMATO {
14494e60171SMasatake YAMATO tagEntryInfo e;
14594e60171SMasatake YAMATO
14616a2541cSMasatake YAMATO initTagEntry(&e, vStringValue (token->string), kind);
14794e60171SMasatake YAMATO e.extensionFields.scopeIndex = parent;
14894e60171SMasatake YAMATO attachProtectionMaybe (&e, protection);
14994e60171SMasatake YAMATO r = makeTagEntry (&e);
15094e60171SMasatake YAMATO }
15194e60171SMasatake YAMATO
15294e60171SMasatake YAMATO skipToEndOfTclCmdline (token);
15394e60171SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (r);
1543671ad72SMasatake YAMATO if (e)
15594e60171SMasatake YAMATO e->extensionFields.endLine = token->lineNumber;
15694e60171SMasatake YAMATO }
15794e60171SMasatake YAMATO
15894e60171SMasatake YAMATO
parseVariable(tokenInfo * token,int r,keywordId protection)15994e60171SMasatake YAMATO static void parseVariable (tokenInfo *token, int r, keywordId protection)
16094e60171SMasatake YAMATO {
16194e60171SMasatake YAMATO parseSubobject(token, r, K_VARIABLE, protection);
16294e60171SMasatake YAMATO }
16394e60171SMasatake YAMATO
parseMethod(tokenInfo * token,int r,keywordId protection)16494e60171SMasatake YAMATO static void parseMethod (tokenInfo *token, int r, keywordId protection)
16594e60171SMasatake YAMATO {
16694e60171SMasatake YAMATO parseSubobject(token, r, K_METHOD, protection);
16794e60171SMasatake YAMATO }
16894e60171SMasatake YAMATO
parseProc(tokenInfo * token,int r,keywordId protection)16994e60171SMasatake YAMATO static void parseProc (tokenInfo *token, int r, keywordId protection)
17094e60171SMasatake YAMATO {
17194e60171SMasatake YAMATO parseSubobject(token, r, K_PROC, protection);
17294e60171SMasatake YAMATO }
17394e60171SMasatake YAMATO
parseCommon(tokenInfo * token,int r,keywordId protection)17494e60171SMasatake YAMATO static void parseCommon (tokenInfo *token, int r, keywordId protection)
17594e60171SMasatake YAMATO {
17694e60171SMasatake YAMATO parseSubobject(token, r, K_COMMON, protection);
17794e60171SMasatake YAMATO }
17894e60171SMasatake YAMATO
parseClass(tclSubparser * s CTAGS_ATTR_UNUSED,int parentIndex,void * pstate)1795d9d66cfSMasatake YAMATO static int parseClass (tclSubparser *s CTAGS_ATTR_UNUSED, int parentIndex,
1805d9d66cfSMasatake YAMATO void *pstate)
1816ae73029SMasatake YAMATO {
1825d9d66cfSMasatake YAMATO tokenInfo *token = newTclToken (pstate);
18394e60171SMasatake YAMATO int r = CORK_NIL;
1846ae73029SMasatake YAMATO
1856ae73029SMasatake YAMATO tokenRead (token);
1866ae73029SMasatake YAMATO if (tokenIsType (token, TCL_IDENTIFIER))
1876ae73029SMasatake YAMATO {
1886ae73029SMasatake YAMATO tagEntryInfo e;
1896ae73029SMasatake YAMATO
19016a2541cSMasatake YAMATO initTagEntry(&e, vStringValue (token->string), K_CLASS);
1916ae73029SMasatake YAMATO e.extensionFields.scopeIndex = parentIndex;
1926ae73029SMasatake YAMATO r = makeTagEntry (&e);
1936ae73029SMasatake YAMATO }
19494e60171SMasatake YAMATO
19594e60171SMasatake YAMATO if (tokenSkipToType (token, '{'))
1966ae73029SMasatake YAMATO {
19794e60171SMasatake YAMATO keywordId protection = KEYWORD_NONE;
19894e60171SMasatake YAMATO
19994e60171SMasatake YAMATO do {
2006ae73029SMasatake YAMATO tokenRead (token);
201affb14f4SMasatake YAMATO if (tokenIsType (token, TCL_IDENTIFIER)
202affb14f4SMasatake YAMATO || tokenIsType (token, TCL_KEYWORD))
2036ae73029SMasatake YAMATO {
20494e60171SMasatake YAMATO keywordId k = resolveKeyword (token->string);
20594e60171SMasatake YAMATO switch (k)
20694e60171SMasatake YAMATO {
20794e60171SMasatake YAMATO case KEYWORD_INHERIT:
20894e60171SMasatake YAMATO parseInherit(token, r);
20994e60171SMasatake YAMATO protection = KEYWORD_NONE;
21094e60171SMasatake YAMATO break;
21194e60171SMasatake YAMATO case KEYWORD_VARIABLE:
21294e60171SMasatake YAMATO parseVariable(token, r, protection);
21394e60171SMasatake YAMATO protection = KEYWORD_NONE;
21494e60171SMasatake YAMATO break;
21594e60171SMasatake YAMATO case KEYWORD_METHOD:
21694e60171SMasatake YAMATO parseMethod(token, r, protection);
21794e60171SMasatake YAMATO protection = KEYWORD_NONE;
21894e60171SMasatake YAMATO break;
21994e60171SMasatake YAMATO case KEYWORD_COMMON:
22094e60171SMasatake YAMATO parseCommon(token, r, protection);
22194e60171SMasatake YAMATO protection = KEYWORD_NONE;
22294e60171SMasatake YAMATO break;
22394e60171SMasatake YAMATO case KEYWORD_PUBLIC:
22494e60171SMasatake YAMATO case KEYWORD_PROTECTED:
22594e60171SMasatake YAMATO case KEYWORD_PRIVATE:
22694e60171SMasatake YAMATO protection = k;
22794e60171SMasatake YAMATO continue;
228affb14f4SMasatake YAMATO case KEYWORD_PROC:
229affb14f4SMasatake YAMATO parseProc(token, r, protection);
230affb14f4SMasatake YAMATO protection = KEYWORD_NONE;
231affb14f4SMasatake YAMATO break;
23294e60171SMasatake YAMATO default:
23394e60171SMasatake YAMATO protection = KEYWORD_NONE;
23494e60171SMasatake YAMATO skipToEndOfTclCmdline (token);
23594e60171SMasatake YAMATO break;
2366ae73029SMasatake YAMATO }
2376ae73029SMasatake YAMATO }
23894e60171SMasatake YAMATO else if (token->type == '}')
23994e60171SMasatake YAMATO {
24094e60171SMasatake YAMATO protection = KEYWORD_NONE;
24194e60171SMasatake YAMATO break;
24294e60171SMasatake YAMATO }
2436ae73029SMasatake YAMATO else
24494e60171SMasatake YAMATO {
24594e60171SMasatake YAMATO protection = KEYWORD_NONE;
24694e60171SMasatake YAMATO skipToEndOfTclCmdline (token);
2476ae73029SMasatake YAMATO }
24894e60171SMasatake YAMATO } while (!tokenIsEOF(token));
24994e60171SMasatake YAMATO }
25094e60171SMasatake YAMATO
251a203ce0eSMasatake YAMATO tokenDelete(token);
25294e60171SMasatake YAMATO return r;
25394e60171SMasatake YAMATO }
25494e60171SMasatake YAMATO
commandNotify(tclSubparser * s,char * command,int parentIndex,void * pstate)25594e60171SMasatake YAMATO static int commandNotify (tclSubparser *s, char *command,
2565d9d66cfSMasatake YAMATO int parentIndex, void *pstate)
25794e60171SMasatake YAMATO {
258e07c5f05SMasatake YAMATO struct itclSubparser *itcl = (struct itclSubparser *)s;
25994e60171SMasatake YAMATO int r = CORK_NIL;
26094e60171SMasatake YAMATO
261a87043aeSMasatake YAMATO if ((itcl->foundITclNamespaceImported
262a87043aeSMasatake YAMATO && (strcmp (command, "class") == 0))
26394e60171SMasatake YAMATO || (strcmp (command, "itcl::class") == 0))
2645d9d66cfSMasatake YAMATO r = parseClass (s, parentIndex, pstate);
26594e60171SMasatake YAMATO
2666ae73029SMasatake YAMATO return r;
2676ae73029SMasatake YAMATO }
2686ae73029SMasatake YAMATO
namespaceImportNotify(tclSubparser * s,char * namespace,void * pstate CTAGS_ATTR_UNUSED)2695d9d66cfSMasatake YAMATO static void namespaceImportNotify (tclSubparser *s, char *namespace,
2705d9d66cfSMasatake YAMATO void *pstate CTAGS_ATTR_UNUSED)
271a87043aeSMasatake YAMATO {
272a87043aeSMasatake YAMATO struct itclSubparser *itcl = (struct itclSubparser *)s;
273a87043aeSMasatake YAMATO
274a87043aeSMasatake YAMATO if (strcmp(namespace, "itcl::*") == 0
275a87043aeSMasatake YAMATO || strcmp(namespace, "itcl::class") == 0)
276a87043aeSMasatake YAMATO itcl->foundITclNamespaceImported = true;
277a87043aeSMasatake YAMATO }
278a87043aeSMasatake YAMATO
inputStart(subparser * s)279e07c5f05SMasatake YAMATO static void inputStart (subparser *s)
280e07c5f05SMasatake YAMATO {
281e07c5f05SMasatake YAMATO struct itclSubparser *itcl = (struct itclSubparser *)s;
282e07c5f05SMasatake YAMATO
283cecb4a16SMasatake YAMATO itcl->foundITclNamespaceImported = itclForceUse;
284e07c5f05SMasatake YAMATO }
285e07c5f05SMasatake YAMATO
286*a2d077b3SMasatake YAMATO static struct itclSubparser itclSubparser = {
287e07c5f05SMasatake YAMATO .tcl = {
288e07c5f05SMasatake YAMATO .subparser = {
289e07c5f05SMasatake YAMATO .direction = SUBPARSER_BI_DIRECTION,
290e07c5f05SMasatake YAMATO .inputStart = inputStart,
291e07c5f05SMasatake YAMATO },
292e07c5f05SMasatake YAMATO .commandNotify = commandNotify,
293a87043aeSMasatake YAMATO .namespaceImportNotify = namespaceImportNotify,
294e07c5f05SMasatake YAMATO },
295e07c5f05SMasatake YAMATO };
296e07c5f05SMasatake YAMATO
findITclTags(void)2976ae73029SMasatake YAMATO static void findITclTags(void)
2986ae73029SMasatake YAMATO {
2996ae73029SMasatake YAMATO scheduleRunningBaseparser (RUN_DEFAULT_SUBPARSERS);
3006ae73029SMasatake YAMATO }
3016ae73029SMasatake YAMATO
itclForceUseParamHandler(const langType language CTAGS_ATTR_UNUSED,const char * name,const char * arg)302cecb4a16SMasatake YAMATO static void itclForceUseParamHandler (const langType language CTAGS_ATTR_UNUSED,
303cecb4a16SMasatake YAMATO const char *name, const char *arg)
304cecb4a16SMasatake YAMATO {
305cecb4a16SMasatake YAMATO itclForceUse = paramParserBool (arg, itclForceUse, name, "parameter");
306cecb4a16SMasatake YAMATO }
307cecb4a16SMasatake YAMATO
308cecb4a16SMasatake YAMATO static parameterHandlerTable ItclParameterHandlerTable [] = {
309cecb4a16SMasatake YAMATO { .name = "forceUse",
310cecb4a16SMasatake YAMATO .desc = "enable the parser even when `itcl' namespace is not specified in the input (true or [false])" ,
311cecb4a16SMasatake YAMATO .handleParameter = itclForceUseParamHandler,
312cecb4a16SMasatake YAMATO },
313cecb4a16SMasatake YAMATO };
314cecb4a16SMasatake YAMATO
ITclParser(void)3156ae73029SMasatake YAMATO extern parserDefinition* ITclParser (void)
3166ae73029SMasatake YAMATO {
3176ae73029SMasatake YAMATO static const char *const extensions [] = { "itcl", NULL };
3186ae73029SMasatake YAMATO parserDefinition* const def = parserNew("ITcl");
3196ae73029SMasatake YAMATO
3206ae73029SMasatake YAMATO static parserDependency dependencies [] = {
3216ae73029SMasatake YAMATO [0] = { DEPTYPE_SUBPARSER, "Tcl", &itclSubparser },
3226ae73029SMasatake YAMATO };
3236ae73029SMasatake YAMATO
3246ae73029SMasatake YAMATO def->dependencies = dependencies;
3256ae73029SMasatake YAMATO def->dependencyCount = ARRAY_SIZE (dependencies);
3266ae73029SMasatake YAMATO
3276ae73029SMasatake YAMATO def->kindTable = ITclKinds;
3286ae73029SMasatake YAMATO def->kindCount = ARRAY_SIZE(ITclKinds);
3296ae73029SMasatake YAMATO
3306ae73029SMasatake YAMATO def->extensions = extensions;
3316ff1e862SMasatake YAMATO def->parser = findITclTags;
3326b1a862eSMasatake YAMATO def->useCork = CORK_QUEUE;
33394e60171SMasatake YAMATO def->requestAutomaticFQTag = true;
33494e60171SMasatake YAMATO
33594e60171SMasatake YAMATO def->keywordTable = ITclKeywordTable;
33694e60171SMasatake YAMATO def->keywordCount = ARRAY_SIZE (ITclKeywordTable);
3376ae73029SMasatake YAMATO
338cecb4a16SMasatake YAMATO def->parameterHandlerTable = ItclParameterHandlerTable;
339cecb4a16SMasatake YAMATO def->parameterHandlerCount = ARRAY_SIZE(ItclParameterHandlerTable);
340cecb4a16SMasatake YAMATO
3416ae73029SMasatake YAMATO return def;
3426ae73029SMasatake YAMATO }
343