Skip to content

Commit 7e06c76

Browse files
authored
Merge pull request #3205 from eht16/pascal_add_signature_parsing
Pascal: Add parsing of function/proc signatures
2 parents ac504cc + bd60584 commit 7e06c76

File tree

4 files changed

+131
-2
lines changed

4 files changed

+131
-2
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
--fields=+tS
2+
--sort=no
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
helloproc input.pas /^PROCEDURE helloproc(param1: STRING; param2: BYTE);$/;" p signature:(param1: STRING; param2: BYTE)
2+
max input.pas /^FUNCTION max(num1, num2: INTEGER): INTEGER;$/;" f typeref:typename:INTEGER signature:(num1, num2: INTEGER)
3+
noargs input.pas /^FUNCTION noargs: STRING;$/;" f typeref:typename:STRING signature:()
4+
emptyargs input.pas /^FUNCTION emptyargs(): STRING;$/;" f typeref:typename:STRING signature:()
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
PROGRAM hello;
2+
3+
TYPE
4+
simpletype = RECORD
5+
one: INTEGER;
6+
END;
7+
8+
9+
PROCEDURE helloproc(param1: STRING; param2: BYTE);
10+
BEGIN
11+
writeln('Hello World!');
12+
END;
13+
14+
15+
FUNCTION max(num1, num2: INTEGER): INTEGER;
16+
VAR
17+
result: INTEGER;
18+
BEGIN
19+
if (num1 > num2) then
20+
result := num1
21+
22+
else
23+
result := num2;
24+
max := result;
25+
END;
26+
27+
28+
FUNCTION noargs: STRING;
29+
BEGIN
30+
noargs := 'functon without arguments';
31+
END;
32+
33+
FUNCTION emptyargs(): STRING;
34+
BEGIN
35+
emptyargs := 'functon without arguments';
36+
END;
37+
38+
39+
VAR result : INTEGER;
40+
BEGIN
41+
helloproc('ignored', 1);
42+
result := max(73, 42);
43+
writeln('Result: ', result);
44+
END.

parsers/pascal.c

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,22 @@ static kindDefinition PascalKinds [] = {
3838
*/
3939

4040
static void createPascalTag (
41-
tagEntryInfo* const tag, const vString* const name, const int kind)
41+
tagEntryInfo* const tag, const vString* const name, const int kind,
42+
const vString *arglist, const vString *vartype)
4243
{
4344
if (PascalKinds [kind].enabled && name != NULL && vStringLength (name) > 0)
45+
{
4446
initTagEntry (tag, vStringValue (name), kind);
47+
if (arglist != NULL && !vStringIsEmpty(arglist))
48+
{
49+
tag->extensionFields.signature = vStringValue(arglist);
50+
}
51+
if (vartype && !vStringIsEmpty(vartype))
52+
{
53+
tag->extensionFields.typeRef[0] = "typename";
54+
tag->extensionFields.typeRef[1] = vStringValue(vartype);
55+
}
56+
}
4557
else
4658
/* TODO: Passing NULL as name makes an assertion behind initTagEntry failure */
4759
initTagEntry (tag, NULL, KIND_GHOST_INDEX);
@@ -74,6 +86,64 @@ static bool tail (const char *cp)
7486
return result;
7587
}
7688

89+
static void parseArglist(const char *buf, vString *arglist, vString *vartype)
90+
{
91+
const char *start, *end;
92+
int level;
93+
94+
if (NULL == buf || arglist == NULL)
95+
return;
96+
97+
/* parse argument list which can be missing like in "function ginit:integer;" */
98+
if (NULL != (start = strchr(buf, '(')))
99+
{
100+
for (level = 1, end = start + 1; level > 0; ++end)
101+
{
102+
if ('\0' == *end)
103+
break;
104+
else if ('(' == *end)
105+
++ level;
106+
else if (')' == *end)
107+
-- level;
108+
}
109+
}
110+
else /* if no argument list was found, continue looking for a return value */
111+
{
112+
start = NULL;
113+
end = buf;
114+
}
115+
116+
/* parse return type if requested by passing a non-NULL vartype argument */
117+
if (NULL != vartype)
118+
{
119+
char *var, *var_start;
120+
121+
if (NULL != (var = strchr(end, ':')))
122+
{
123+
var++; /* skip ':' */
124+
while (isspace((int) *var))
125+
++var;
126+
127+
if (starttoken(*var))
128+
{
129+
var_start = var;
130+
var++;
131+
while (intoken(*var))
132+
var++;
133+
if (endtoken(*var))
134+
{
135+
vStringNCatS(vartype, var_start, var - var_start);
136+
}
137+
}
138+
}
139+
}
140+
141+
if (NULL == start) /* no argument list */
142+
vStringCatS(arglist, "()");
143+
else
144+
vStringNCatS(arglist, start, end - start);
145+
}
146+
77147
/* Algorithm adapted from from GNU etags.
78148
* Locates tags for procedures & functions. Doesn't do any type- or
79149
* var-definitions. It does look for the keyword "extern" or "forward"
@@ -83,6 +153,8 @@ static bool tail (const char *cp)
83153
static void findPascalTags (void)
84154
{
85155
vString *name = vStringNew ();
156+
vString *arglist = vStringNew();
157+
vString *vartype = vStringNew();
86158
tagEntryInfo tag;
87159
pascalKind kind = K_FUNCTION;
88160
/* each of these flags is true iff: */
@@ -205,7 +277,12 @@ static void findPascalTags (void)
205277
for (cp = dbp ; *cp != '\0' && !endtoken (*cp) ; cp++)
206278
continue;
207279
vStringNCopyS (name, (const char*) dbp, cp - dbp);
208-
createPascalTag (&tag, name, kind);
280+
281+
vStringClear (arglist);
282+
vStringClear (vartype);
283+
parseArglist((const char*) cp, arglist, (kind == K_FUNCTION) ? vartype : NULL);
284+
285+
createPascalTag (&tag, name, kind, arglist, (kind == K_FUNCTION) ? vartype : NULL);
209286
dbp = cp; /* set dbp to e-o-token */
210287
get_tagname = false;
211288
found_tag = true;
@@ -246,6 +323,8 @@ static void findPascalTags (void)
246323
}
247324
} /* while not eof */
248325
}
326+
vStringDelete (arglist);
327+
vStringDelete (vartype);
249328
vStringDelete (name);
250329
}
251330

0 commit comments

Comments
 (0)