Skip to content

Commit 88f804c

Browse files
authored
Merge pull request #3249 from techee/basic
Basic: various improvements from Geany
2 parents 210867b + 08a9d8b commit 88f804c

File tree

3 files changed

+172
-66
lines changed

3 files changed

+172
-66
lines changed

Units/parser-basic.r/simple.bas.d/expected.tags

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
a input.bas /^Common a As Integer$/;" v
22
b input.bas /^Dim b As Integer$/;" v
3+
c input.bas /^dim as string c(20), d="a", e$/;" v
4+
d input.bas /^dim as string c(20), d="a", e$/;" v
5+
e input.bas /^dim as string c(20), d="a", e$/;" v
36
f input.bas /^Function f()$/;" f
7+
g input.bas /^dim shared as string g$/;" v
8+
h input.bas /^dim as string ptr h$/;" v
9+
i input.bas /^dim as string * 4096 i$/;" v
10+
j input.bas /^dim j as string="Export_GIR_FULL_"+mid(date,7)+","+mid(date,1,2)+""+mid(date,4,2)+".csv"$/;" v
11+
k input.bas /^dim as string k="Export_GIR_FULL_"+mid(date(),"(")+","+mid(date,1,2)+""+mid(date,4,2)+".csv", l$/;" v
12+
l input.bas /^dim as string k="Export_GIR_FULL_"+mid(date(),"(")+","+mid(date,1,2)+""+mid(date,4,2)+".csv", l$/;" v
413
one input.bas /^Const one = 1$/;" c
514
start input.bas /^start:$/;" l
615
str input.bas /^DIM AS STRING str$/;" v

Units/parser-basic.r/simple.bas.d/input.bas

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ Const one = 1
55
Common a As Integer
66
Dim b As Integer
77
DIM AS STRING str
8+
dim as string c(20), d="a", e
9+
dim shared as string g
10+
dim as string ptr h
11+
dim as string * 4096 i
12+
dim j as string="Export_GIR_FULL_"+mid(date,7)+","+mid(date,1,2)+""+mid(date,4,2)+".csv"
13+
dim as string k="Export_GIR_FULL_"+mid(date(),"(")+","+mid(date,1,2)+""+mid(date,4,2)+".csv", l
814

915
Type test
1016
a As Integer

parsers/basic.c

Lines changed: 157 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ typedef enum {
3737
typedef struct {
3838
char const *token;
3939
BasicKind kind;
40-
int skip;
4140
} KeyWord;
4241

4342
static kindDefinition BasicKinds[] = {
@@ -49,76 +48,182 @@ static kindDefinition BasicKinds[] = {
4948
{true, 'g', "enum", "enumerations"}
5049
};
5150

52-
static KeyWord blitzbasic_keywords[] = {
53-
{"const", K_CONST, 0},
54-
{"global", K_VARIABLE, 0},
55-
{"dim", K_VARIABLE, 0},
56-
{"function", K_FUNCTION, 0},
57-
{"type", K_TYPE, 0},
58-
{NULL, 0, 0}
59-
};
51+
static KeyWord basic_keywords[] = {
52+
/* freebasic */
53+
{"const", K_CONST},
54+
{"dim", K_VARIABLE},
55+
{"common", K_VARIABLE},
56+
{"function", K_FUNCTION},
57+
{"sub", K_FUNCTION},
58+
{"private sub", K_FUNCTION},
59+
{"public sub", K_FUNCTION},
60+
{"private function", K_FUNCTION},
61+
{"public function", K_FUNCTION},
62+
{"property", K_FUNCTION},
63+
{"constructor", K_FUNCTION},
64+
{"destructor", K_FUNCTION},
65+
{"type", K_TYPE},
66+
{"enum", K_ENUM},
6067

61-
static KeyWord purebasic_keywords[] = {
62-
{"newlist", K_VARIABLE, 0},
63-
{"global", K_VARIABLE, 0},
64-
{"dim", K_VARIABLE, 0},
65-
{"procedure", K_FUNCTION, 0},
66-
{"interface", K_TYPE, 0},
67-
{"structure", K_TYPE, 0},
68-
{NULL, 0, 0}
69-
};
68+
/* blitzbasic, purebasic */
69+
{"global", K_VARIABLE},
7070

71-
static KeyWord freebasic_keywords[] = {
72-
{"const", K_CONST, 0},
73-
{"dim as", K_VARIABLE, 1},
74-
{"dim", K_VARIABLE, 0},
75-
{"common", K_VARIABLE, 0},
76-
{"function", K_FUNCTION, 0},
77-
{"sub", K_FUNCTION, 0},
78-
{"private sub", K_FUNCTION, 0},
79-
{"public sub", K_FUNCTION, 0},
80-
{"private function", K_FUNCTION, 0},
81-
{"public function", K_FUNCTION, 0},
82-
{"type", K_TYPE, 0},
83-
{"enum", K_ENUM, 0},
84-
{NULL, 0, 0}
71+
/* purebasic */
72+
{"newlist", K_VARIABLE},
73+
{"procedure", K_FUNCTION},
74+
{"interface", K_TYPE},
75+
{"structure", K_TYPE},
76+
77+
{NULL, 0}
8578
};
8679

8780
/*
8881
* FUNCTION DEFINITIONS
8982
*/
9083

91-
/* Match the name of a tag (function, variable, type, ...) starting at pos. */
92-
static char const *extract_name (char const *pos, vString * name)
84+
static const char *skipToMatching (char begin, char end, const char *pos)
85+
{
86+
int counter = 1;
87+
pos++;
88+
while (*pos && counter > 0)
89+
{
90+
if (*pos == end)
91+
counter--;
92+
else if (*pos == begin)
93+
counter++;
94+
else if (*pos == '"')
95+
pos = skipToMatching ('"', '"', pos) - 1;
96+
pos++;
97+
}
98+
return pos;
99+
}
100+
101+
static const char *nextPos (const char *pos)
93102
{
103+
if (*pos == '\0')
104+
return pos;
105+
106+
pos++;
107+
switch (*pos)
108+
{
109+
case '(':
110+
pos = skipToMatching ('(', ')', pos);
111+
break;
112+
case '"':
113+
pos = skipToMatching ('"', '"', pos);
114+
break;
115+
}
116+
return pos;
117+
}
118+
119+
static bool isIdentChar (char c)
120+
{
121+
return c && !isspace (c) && c != '(' && c != ',' && c != '=';
122+
}
123+
124+
/* Match the name of a dim or const starting at pos. */
125+
static void extract_dim (char const *pos, BasicKind kind)
126+
{
127+
vString *name = vStringNew ();
128+
129+
if (strncasecmp (pos, "shared", 6) == 0)
130+
pos += 6; /* skip keyword "shared" */
131+
94132
while (isspace (*pos))
95133
pos++;
96-
vStringClear (name);
97-
for (; *pos && !isspace (*pos) && *pos != '(' && *pos != ','; pos++)
134+
135+
/* capture "dim as String str" */
136+
if (strncasecmp (pos, "as", 2) == 0)
137+
{
138+
pos += 2; /* skip keyword "as" */
139+
140+
while (isspace (*pos))
141+
pos++;
142+
while (!isspace (*pos) && *pos) /* skip next part which is a type */
143+
pos++;
144+
while (isspace (*pos))
145+
pos++;
146+
/* now we are at the name */
147+
}
148+
/* capture "dim as foo ptr bar" */
149+
if (strncasecmp (pos, "ptr", 3) == 0 && isspace(*(pos+3)))
150+
{
151+
pos += 3; /* skip keyword "ptr" */
152+
while (isspace (*pos))
153+
pos++;
154+
}
155+
/* capture "dim as string * 4096 chunk" */
156+
if (strncmp (pos, "*", 1) == 0)
157+
{
158+
pos += 1; /* skip "*" */
159+
while (isspace (*pos) || isdigit(*pos) || ispunct(*pos))
160+
pos++;
161+
}
162+
163+
for (; isIdentChar (*pos); pos++)
98164
vStringPut (name, *pos);
99-
return pos;
165+
makeSimpleTag (name, kind);
166+
167+
/* if the line contains a ',', we have multiple declarations */
168+
while (*pos && strchr (pos, ','))
169+
{
170+
/* skip all we don't need(e.g. "..., new_array(5), " we skip "(5)") */
171+
while (*pos != ',' && *pos != '\'' && *pos)
172+
pos = nextPos (pos);
173+
174+
if (*pos == '\'')
175+
break; /* break if we are in a comment */
176+
177+
while (isspace (*pos) || *pos == ',')
178+
pos++;
179+
180+
if (*pos == '\'')
181+
break; /* break if we are in a comment */
182+
183+
vStringClear (name);
184+
for (; isIdentChar (*pos); pos++)
185+
vStringPut (name, *pos);
186+
makeSimpleTag (name, kind);
187+
}
188+
189+
vStringDelete (name);
190+
}
191+
192+
/* Match the name of a tag (function, variable, type, ...) starting at pos. */
193+
static void extract_name (char const *pos, BasicKind kind)
194+
{
195+
vString *name = vStringNew ();
196+
for (; isIdentChar (*pos); pos++)
197+
vStringPut (name, *pos);
198+
makeSimpleTag (name, kind);
199+
vStringDelete (name);
100200
}
101201

102202
/* Match a keyword starting at p (case insensitive). */
103-
static int match_keyword (const char *p, KeyWord const *kw)
203+
static bool match_keyword (const char *p, KeyWord const *kw)
104204
{
105-
vString *name;
106205
size_t i;
107-
int j;
206+
const char *old_p;
108207
for (i = 0; i < strlen (kw->token); i++)
109208
{
110209
if (tolower (p[i]) != kw->token[i])
111-
return 0;
210+
return false;
112211
}
113-
name = vStringNew ();
114212
p += i;
115-
for (j = 0; j < 1 + kw->skip; j++)
116-
{
117-
p = extract_name (p, name);
118-
}
119-
makeSimpleTag (name, kw->kind);
120-
vStringDelete (name);
121-
return 1;
213+
214+
old_p = p;
215+
while (isspace (*p))
216+
p++;
217+
218+
/* create tags only if there is some space between the keyword and the identifier */
219+
if (old_p == p)
220+
return false;
221+
222+
if (kw->kind == K_VARIABLE)
223+
extract_dim (p, kw->kind); /* extract_dim adds the found tag(s) */
224+
else
225+
extract_name (p, kw->kind);
226+
return true;
122227
}
123228

124229
/* Match a "label:" style label. */
@@ -140,26 +245,12 @@ static void match_colon_label (char const *p)
140245
static void match_dot_label (char const *p)
141246
{
142247
if (*p == '.')
143-
{
144-
vString *name = vStringNew ();
145-
extract_name (p + 1, name);
146-
makeSimpleTag (name, K_LABEL);
147-
vStringDelete (name);
148-
}
248+
extract_name (p + 1, K_LABEL);
149249
}
150250

151251
static void findBasicTags (void)
152252
{
153253
const char *line;
154-
const char *extension = fileExtension (getInputFileName ());
155-
KeyWord *keywords;
156-
157-
if (strcmp (extension, "bb") == 0)
158-
keywords = blitzbasic_keywords;
159-
else if (strcmp (extension, "pb") == 0)
160-
keywords = purebasic_keywords;
161-
else
162-
keywords = freebasic_keywords;
163254

164255
while ((line = (const char *) readLineFromInputFile ()) != NULL)
165256
{
@@ -183,11 +274,11 @@ static void findBasicTags (void)
183274
continue;
184275

185276
/* In Basic, keywords always are at the start of the line. */
186-
for (kw = keywords; kw->token; kw++)
277+
for (kw = basic_keywords; kw->token; kw++)
187278
if (match_keyword (p, kw)) break;
188279

189280
/* Is it a label? */
190-
if (strcmp (extension, "bb") == 0)
281+
if (*p == '.')
191282
match_dot_label (p);
192283
else
193284
match_colon_label (p);

0 commit comments

Comments
 (0)