2
* $Id: erlang.c,v 1.3 2006/05/30 04:37:12 darren Exp $
4
* Copyright (c) 2003, Brent Fulgham <bfulgham@debian.org>
6
* This source code is released for free distribution under the terms of the
7
* GNU General Public License.
9
* This module contains functions for generating tags for Erlang language
10
* files. Some of the parsing constructs are based on the Emacs 'etags'
11
* program by Francesco Potori <pot@gnu.org>
16
#include "general.h" /* must always come first */
30
K_MACRO, K_FUNCTION, K_MODULE, K_RECORD
33
static kindOption ErlangKinds[] = {
34
{TRUE, 'd', "macro", "macro definitions"},
35
{TRUE, 'f', "function", "functions"},
36
{TRUE, 'm', "module", "modules"},
37
{TRUE, 'r', "record", "record definitions"},
41
* FUNCTION DEFINITIONS
43
/* tagEntryInfo and vString should be preinitialized/preallocated but not
44
* necessary. If successful you will find class name in vString
47
static boolean isIdentifierFirstCharacter (int c)
49
return (boolean) (isalpha (c));
52
static boolean isIdentifierCharacter (int c)
54
return (boolean) (isalnum (c) || c == '_' || c == ':');
57
static const unsigned char *skipSpace (const unsigned char *cp)
59
while (isspace ((int) *cp))
64
static const unsigned char *parseIdentifier (
65
const unsigned char *cp, vString *const identifier)
67
vStringClear (identifier);
68
while (isIdentifierCharacter ((int) *cp))
70
vStringPut (identifier, (int) *cp);
73
vStringTerminate (identifier);
77
static void makeMemberTag (
78
vString *const identifier, erlangKind kind, vString *const module)
80
if (ErlangKinds [kind].enabled && vStringLength (identifier) > 0)
83
initTagEntry (&tag, vStringValue (identifier));
84
tag.kindName = ErlangKinds[kind].name;
85
tag.kind = ErlangKinds[kind].letter;
87
if (module != NULL && vStringLength (module) > 0)
89
tag.extensionFields.scope [0] = "module";
90
tag.extensionFields.scope [1] = vStringValue (module);
96
static void parseModuleTag (const unsigned char *cp, vString *const module)
98
vString *const identifier = vStringNew ();
99
parseIdentifier (cp, identifier);
100
makeSimpleTag (identifier, ErlangKinds, K_MODULE);
102
/* All further entries go in the new module */
103
vStringCopy (module, identifier);
104
vStringDelete (identifier);
107
static void parseSimpleTag (const unsigned char *cp, erlangKind kind)
109
vString *const identifier = vStringNew ();
110
parseIdentifier (cp, identifier);
111
makeSimpleTag (identifier, ErlangKinds, kind);
112
vStringDelete (identifier);
115
static void parseFunctionTag (const unsigned char *cp, vString *const module)
117
vString *const identifier = vStringNew ();
118
parseIdentifier (cp, identifier);
119
makeMemberTag (identifier, K_FUNCTION, module);
120
vStringDelete (identifier);
124
* Directives are of the form:
127
* -record(graph, {vtab = notable, cyclic = true}).
129
static void parseDirective (const unsigned char *cp, vString *const module)
132
* A directive will be either a record definition or a directive.
133
* Record definitions are handled separately
135
vString *const directive = vStringNew ();
136
const char *const drtv = vStringValue (directive);
137
cp = parseIdentifier (cp, directive);
142
if (strcmp (drtv, "record") == 0)
143
parseSimpleTag (cp, K_RECORD);
144
else if (strcmp (drtv, "define") == 0)
145
parseSimpleTag (cp, K_MACRO);
146
else if (strcmp (drtv, "module") == 0)
147
parseModuleTag (cp, module);
148
/* Otherwise, it was an import, export, etc. */
150
vStringDelete (directive);
153
static void findErlangTags (void)
155
vString *const module = vStringNew ();
156
const unsigned char *line;
158
while ((line = fileReadLine ()) != NULL)
160
const unsigned char *cp = line;
162
if (*cp == '%') /* skip initial comment */
164
if (*cp == '"') /* strings sometimes start in column one */
169
++cp; /* Move off of the '-' */
170
parseDirective(cp, module);
172
else if (isIdentifierFirstCharacter ((int) *cp))
173
parseFunctionTag (cp, module);
175
vStringDelete (module);
178
extern parserDefinition *ErlangParser (void)
180
static const char *const extensions[] = { "erl", "ERL", "hrl", "HRL", NULL };
181
parserDefinition *def = parserNew ("Erlang");
182
def->kinds = ErlangKinds;
183
def->kindCount = KIND_COUNT (ErlangKinds);
184
def->extensions = extensions;
185
def->parser = findErlangTags;
189
/* vi:set tabstop=4 shiftwidth=4: */