13ae02089SMasatake YAMATO /**
23ae02089SMasatake YAMATO * Copyright (c) 2015, Miloslav Nenadál <nenadalm@gmail.com>
33ae02089SMasatake YAMATO *
43ae02089SMasatake YAMATO * This source code is released for free distribution under the terms of the
50ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
63ae02089SMasatake YAMATO *
73ae02089SMasatake YAMATO * This module contains code for generating tags for the Clojure language.
83ae02089SMasatake YAMATO */
93ae02089SMasatake YAMATO
103ae02089SMasatake YAMATO #include "general.h"
113ae02089SMasatake YAMATO
12f1d950b8SMasatake YAMATO #include <string.h>
13f1d950b8SMasatake YAMATO
143ae02089SMasatake YAMATO #include "parse.h"
153ae02089SMasatake YAMATO #include "read.h"
163db72c21SMasatake YAMATO #include "routines.h"
173ae02089SMasatake YAMATO #include "vstring.h"
183ae02089SMasatake YAMATO #include "entry.h"
193ae02089SMasatake YAMATO
203ae02089SMasatake YAMATO typedef enum {
213ae02089SMasatake YAMATO K_FUNCTION,
223ae02089SMasatake YAMATO K_NAMESPACE
233ae02089SMasatake YAMATO } clojureKind;
243ae02089SMasatake YAMATO
25e112e8abSMasatake YAMATO static kindDefinition ClojureKinds[] = {
26ce990805SThomas Braun {true, 'f', "function", "functions"},
27ce990805SThomas Braun {true, 'n', "namespace", "namespaces"}
283ae02089SMasatake YAMATO };
293ae02089SMasatake YAMATO
isNamespace(const char * strp)303ae02089SMasatake YAMATO static int isNamespace (const char *strp)
313ae02089SMasatake YAMATO {
323ae02089SMasatake YAMATO return strncmp (++strp, "ns", 2) == 0 && isspace (strp[2]);
333ae02089SMasatake YAMATO }
343ae02089SMasatake YAMATO
isCoreNamespace(const char * strp)359f5a3ddaSVlad Bokov static int isCoreNamespace (const char *strp)
369f5a3ddaSVlad Bokov {
379f5a3ddaSVlad Bokov return strncmp (++strp, "clojure.core/ns", 15) == 0 && isspace (strp[15]);
389f5a3ddaSVlad Bokov }
399f5a3ddaSVlad Bokov
isFunction(const char * strp)403ae02089SMasatake YAMATO static int isFunction (const char *strp)
413ae02089SMasatake YAMATO {
429f5a3ddaSVlad Bokov return (strncmp (++strp, "defn", 4) == 0 && isspace (strp[4]));
43a761eaf7SVlad Bokov }
44a761eaf7SVlad Bokov
isCoreFunction(const char * strp)45a761eaf7SVlad Bokov static int isCoreFunction (const char *strp)
46a761eaf7SVlad Bokov {
47a761eaf7SVlad Bokov return (strncmp (++strp, "clojure.core/defn", 17) == 0 && isspace (strp[17]));
483ae02089SMasatake YAMATO }
493ae02089SMasatake YAMATO
isQuote(const char * strp)503ae02089SMasatake YAMATO static int isQuote (const char *strp)
513ae02089SMasatake YAMATO {
523ae02089SMasatake YAMATO return strncmp (++strp, "quote", 5) == 0 && isspace (strp[5]);
533ae02089SMasatake YAMATO }
543ae02089SMasatake YAMATO
functionName(vString * const name,const char * dbp)553ae02089SMasatake YAMATO static void functionName (vString * const name, const char *dbp)
563ae02089SMasatake YAMATO {
573ae02089SMasatake YAMATO const char *p;
583ae02089SMasatake YAMATO
593ae02089SMasatake YAMATO if (*dbp == '\'')
603ae02089SMasatake YAMATO dbp++;
613ae02089SMasatake YAMATO else if (*dbp == '(' && isQuote (dbp))
623ae02089SMasatake YAMATO {
633ae02089SMasatake YAMATO dbp += 7;
643ae02089SMasatake YAMATO while (isspace (*dbp))
653ae02089SMasatake YAMATO dbp++;
663ae02089SMasatake YAMATO }
673ae02089SMasatake YAMATO
683ae02089SMasatake YAMATO for (p = dbp; *p != '\0' && *p != '(' && !isspace ((int) *p) && *p != ')';
693ae02089SMasatake YAMATO p++)
703ae02089SMasatake YAMATO vStringPut (name, *p);
713ae02089SMasatake YAMATO }
723ae02089SMasatake YAMATO
skipMetadata(const char * dbp)7393423845SMasatake YAMATO const char* skipMetadata (const char *dbp)
7493423845SMasatake YAMATO {
7593423845SMasatake YAMATO while (1)
7693423845SMasatake YAMATO {
7793423845SMasatake YAMATO if (*dbp == '^')
7893423845SMasatake YAMATO {
7993423845SMasatake YAMATO dbp++;
8093423845SMasatake YAMATO if (*dbp == '{')
8193423845SMasatake YAMATO {
8293423845SMasatake YAMATO /* skipping an arraymap */
8393423845SMasatake YAMATO for (; *dbp != '\0' && *dbp != '}'; dbp++)
8493423845SMasatake YAMATO ;
8593423845SMasatake YAMATO }
8693423845SMasatake YAMATO else
8793423845SMasatake YAMATO {
8893423845SMasatake YAMATO /* skip a keyword or a symbol */
8993423845SMasatake YAMATO for (; *dbp != '\0' && !isspace((unsigned char)*dbp); dbp++)
9093423845SMasatake YAMATO ;
9193423845SMasatake YAMATO }
9293423845SMasatake YAMATO
9393423845SMasatake YAMATO if (*dbp == '\0')
9493423845SMasatake YAMATO break;
9593423845SMasatake YAMATO
9693423845SMasatake YAMATO dbp++;
9793423845SMasatake YAMATO while (isspace ((unsigned char)*dbp))
9893423845SMasatake YAMATO dbp++;
9993423845SMasatake YAMATO }
10093423845SMasatake YAMATO else
10193423845SMasatake YAMATO break;
10293423845SMasatake YAMATO }
10393423845SMasatake YAMATO
10493423845SMasatake YAMATO return dbp;
10593423845SMasatake YAMATO }
10693423845SMasatake YAMATO
makeNamespaceTag(vString * const name,const char * dbp)10718599907SMasatake YAMATO static int makeNamespaceTag (vString * const name, const char *dbp)
1083ae02089SMasatake YAMATO {
10993423845SMasatake YAMATO dbp = skipMetadata (dbp);
1103ae02089SMasatake YAMATO functionName (name, dbp);
1114a95e4a5SColomban Wendling if (vStringLength (name) > 0 && ClojureKinds[K_NAMESPACE].enabled)
1123ae02089SMasatake YAMATO {
1133ae02089SMasatake YAMATO tagEntryInfo e;
11416a2541cSMasatake YAMATO initTagEntry (&e, vStringValue (name), K_NAMESPACE);
115a31b37dcSMasatake YAMATO e.lineNumber = getInputLineNumber ();
1163ae02089SMasatake YAMATO e.filePosition = getInputFilePosition ();
1173ae02089SMasatake YAMATO
11818599907SMasatake YAMATO return makeTagEntry (&e);
1193ae02089SMasatake YAMATO }
12018599907SMasatake YAMATO else
121f6027918SMasatake YAMATO return CORK_NIL;
1223ae02089SMasatake YAMATO }
1233ae02089SMasatake YAMATO
makeFunctionTag(vString * const name,const char * dbp,int scope_index)12418599907SMasatake YAMATO static void makeFunctionTag (vString * const name, const char *dbp, int scope_index)
1253ae02089SMasatake YAMATO {
126*c18ddfadSAlex Chen dbp = skipMetadata (dbp);
1273ae02089SMasatake YAMATO functionName (name, dbp);
1284a95e4a5SColomban Wendling if (vStringLength (name) > 0 && ClojureKinds[K_FUNCTION].enabled)
1293ae02089SMasatake YAMATO {
1303ae02089SMasatake YAMATO tagEntryInfo e;
13116a2541cSMasatake YAMATO initTagEntry (&e, vStringValue (name), K_FUNCTION);
132a31b37dcSMasatake YAMATO e.lineNumber = getInputLineNumber ();
1333ae02089SMasatake YAMATO e.filePosition = getInputFilePosition ();
1343ae02089SMasatake YAMATO
1353b5d9090SMasatake YAMATO e.extensionFields.scopeIndex = scope_index;
1363ae02089SMasatake YAMATO makeTagEntry (&e);
1373ae02089SMasatake YAMATO }
1383ae02089SMasatake YAMATO }
1393ae02089SMasatake YAMATO
skipToSymbol(const char ** p)1403ae02089SMasatake YAMATO static void skipToSymbol (const char **p)
1413ae02089SMasatake YAMATO {
1423ae02089SMasatake YAMATO while (**p != '\0' && !isspace ((int) **p))
1433ae02089SMasatake YAMATO *p = *p + 1;
1443ae02089SMasatake YAMATO while (isspace ((int) **p))
1453ae02089SMasatake YAMATO *p = *p + 1;
1463ae02089SMasatake YAMATO }
1473ae02089SMasatake YAMATO
findClojureTags(void)1483ae02089SMasatake YAMATO static void findClojureTags (void)
1493ae02089SMasatake YAMATO {
1503ae02089SMasatake YAMATO vString *name = vStringNew ();
1513ae02089SMasatake YAMATO const char *p;
152f6027918SMasatake YAMATO int scope_index = CORK_NIL;
1533ae02089SMasatake YAMATO
1541b312fe7SMasatake YAMATO while ((p = (char *)readLineFromInputFile ()) != NULL)
1553ae02089SMasatake YAMATO {
1563ae02089SMasatake YAMATO vStringClear (name);
1573ae02089SMasatake YAMATO
1583ae02089SMasatake YAMATO while (isspace (*p))
1593ae02089SMasatake YAMATO p++;
1603ae02089SMasatake YAMATO
1613ae02089SMasatake YAMATO if (*p == '(')
1623ae02089SMasatake YAMATO {
1639f5a3ddaSVlad Bokov if (isNamespace (p) || isCoreNamespace (p))
1643ae02089SMasatake YAMATO {
1653ae02089SMasatake YAMATO skipToSymbol (&p);
16618599907SMasatake YAMATO scope_index = makeNamespaceTag (name, p);
1673ae02089SMasatake YAMATO }
168a761eaf7SVlad Bokov else if (isFunction (p) || isCoreFunction (p))
1693ae02089SMasatake YAMATO {
1703ae02089SMasatake YAMATO skipToSymbol (&p);
17118599907SMasatake YAMATO makeFunctionTag (name, p, scope_index);
1723ae02089SMasatake YAMATO }
1733ae02089SMasatake YAMATO }
1743ae02089SMasatake YAMATO }
1753ae02089SMasatake YAMATO vStringDelete (name);
1763ae02089SMasatake YAMATO }
1773ae02089SMasatake YAMATO
ClojureParser(void)1783ae02089SMasatake YAMATO extern parserDefinition *ClojureParser (void)
1793ae02089SMasatake YAMATO {
1803ae02089SMasatake YAMATO static const char *const extensions[] = {
18175145629SFöldi Tamás "clj", "cljs", "cljc", NULL
1823ae02089SMasatake YAMATO };
1833ae02089SMasatake YAMATO static const char *const aliases[] = {
1843ae02089SMasatake YAMATO NULL
1853ae02089SMasatake YAMATO };
1863ae02089SMasatake YAMATO
1873ae02089SMasatake YAMATO parserDefinition *def = parserNew ("Clojure");
18809ae690fSMasatake YAMATO def->kindTable = ClojureKinds;
1893db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE (ClojureKinds);
1903ae02089SMasatake YAMATO def->extensions = extensions;
1913ae02089SMasatake YAMATO def->aliases = aliases;
1923ae02089SMasatake YAMATO def->parser = findClojureTags;
1936b1a862eSMasatake YAMATO def->useCork = CORK_QUEUE;
1943ae02089SMasatake YAMATO return def;
1953ae02089SMasatake YAMATO }
196