r5123 | ntrel | 2010-08-10 17:12:24 +0100 (Tue, 10 Aug 2010) | 4 lines
[geany-mirror.git] / tagmanager / basic.c
bloba83a5db801de9b8233400be710454b5162bb83d1
1 /*
2 * $Id$
4 * Copyright (c) 2000-2006, Darren Hiebert, Elias Pschernig
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 BlitzBasic
10 * (BlitzMax), PureBasic and FreeBasic language files. For now, this is kept
11 * quite simple - but feel free to ask for more things added any time -
12 * patches are of course most welcome.
16 * INCLUDE FILES
18 #include "general.h" /* must always come first */
20 #include <string.h>
22 #include "parse.h"
23 #include "read.h"
24 #include "vstring.h"
27 * DATA DEFINITIONS
29 typedef enum {
30 K_CONST,
31 K_FUNCTION,
32 K_LABEL,
33 K_TYPE,
34 K_VARIABLE,
35 K_ENUM
36 } BasicKind;
38 typedef struct {
39 char const *token;
40 BasicKind kind;
41 } KeyWord;
43 static kindOption BasicKinds[] = {
44 {TRUE, 'c', "macro", "constants"},
45 {TRUE, 'f', "function", "functions"},
46 {TRUE, 'l', "namespace", "labels"},
47 {TRUE, 't', "struct", "types"},
48 {TRUE, 'v', "variable", "variables"},
49 {TRUE, 'g', "externvar", "enumerations"}
52 static KeyWord freebasic_keywords[] = {
53 {"dim", K_VARIABLE}, /* must always be the first */
54 {"common", K_VARIABLE}, /* must always be the second */
55 {"const", K_CONST}, /* must always be the third */
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 {"type", K_TYPE},
63 {"enum", K_ENUM},
64 {NULL, 0}
68 * FUNCTION DEFINITIONS
71 /* Match the name of a dim or const starting at pos. */
72 static int extract_dim (char const *pos, vString * name, BasicKind kind)
74 const char *old_pos = pos;
75 while (isspace (*pos))
76 pos++;
78 /* create tags only if there is some space between the keyword and the identifier */
79 if (old_pos == pos)
80 return 0;
82 vStringClear (name);
84 if (strncasecmp (pos, "shared", 6) == 0)
85 pos += 6; /* skip keyword "shared" */
87 while (isspace (*pos))
88 pos++;
90 /* capture "dim as String str" */
91 if (strncasecmp (pos, "as", 2) == 0)
93 pos += 2; /* skip keyword "as" */
95 while (isspace (*pos))
96 pos++;
97 while (!isspace (*pos)) /* skip next part which is a type */
98 pos++;
99 while (isspace (*pos))
100 pos++;
101 /* now we are at the name */
103 /* capture "dim as foo ptr bar" */
104 if (strncasecmp (pos, "ptr", 3) == 0 && isspace(*(pos+4)))
106 pos += 3; /* skip keyword "ptr" */
107 while (isspace (*pos))
108 pos++;
110 /* capture "dim as string * 4096 chunk" */
111 if (strncmp (pos, "*", 1) == 0)
113 pos += 1; /* skip "*" */
114 while (isspace (*pos) || isdigit(*pos) || ispunct(*pos))
115 pos++;
118 for (; *pos && !isspace (*pos) && *pos != '(' && *pos != ',' && *pos != '='; pos++)
119 vStringPut (name, *pos);
120 vStringTerminate (name);
121 makeSimpleTag (name, BasicKinds, kind);
123 /* if the line contains a ',', we have multiple declarations */
124 while (*pos && strchr (pos, ','))
126 /* skip all we don't need(e.g. "..., new_array(5), " we skip "(5)") */
127 while (*pos != ',' && *pos != '\'')
128 pos++;
130 if (*pos == '\'')
131 return 0; /* break if we are in a comment */
133 while (isspace (*pos) || *pos == ',')
134 pos++;
136 if (*pos == '\'')
137 return 0; /* break if we are in a comment */
139 vStringClear (name);
140 for (; *pos && !isspace (*pos) && *pos != '(' && *pos != ',' && *pos != '='; pos++)
141 vStringPut (name, *pos);
142 vStringTerminate (name);
143 makeSimpleTag (name, BasicKinds, kind);
146 vStringDelete (name);
147 return 1;
150 /* Match the name of a tag (function, variable, type, ...) starting at pos. */
151 static char const *extract_name (char const *pos, vString * name)
153 while (isspace (*pos))
154 pos++;
155 vStringClear (name);
156 for (; *pos && !isspace (*pos) && *pos != '(' && *pos != ',' && *pos != '='; pos++)
157 vStringPut (name, *pos);
158 vStringTerminate (name);
159 return pos;
162 /* Match a keyword starting at p (case insensitive). */
163 static int match_keyword (const char *p, KeyWord const *kw)
165 vString *name;
166 size_t i;
167 int j;
168 const char *old_p;
169 for (i = 0; i < strlen (kw->token); i++)
171 if (tolower (p[i]) != kw->token[i])
172 return 0;
174 name = vStringNew ();
175 p += i;
176 if (kw == &freebasic_keywords[0] ||
177 kw == &freebasic_keywords[1] ||
178 kw == &freebasic_keywords[2])
179 return extract_dim (p, name, kw->kind); /* extract_dim adds the found tag(s) */
181 old_p = p;
182 while (isspace (*p))
183 p++;
185 /* create tags only if there is some space between the keyword and the identifier */
186 if (old_p == p)
188 vStringDelete (name);
189 return 0;
192 for (j = 0; j < 1; j++)
194 p = extract_name (p, name);
196 makeSimpleTag (name, BasicKinds, kw->kind);
197 vStringDelete (name);
199 return 1;
202 /* Match a "label:" style label. */
203 static void match_colon_label (char const *p)
205 char const *end = p + strlen (p) - 1;
206 while (isspace (*end))
207 end--;
208 if (*end == ':')
210 vString *name = vStringNew ();
211 vStringNCatS (name, p, end - p);
212 makeSimpleTag (name, BasicKinds, K_LABEL);
213 vStringDelete (name);
217 static void findBasicTags (void)
219 const char *line;
220 KeyWord *keywords;
222 keywords = freebasic_keywords;
224 while ((line = (const char *) fileReadLine ()) != NULL)
226 const char *p = line;
227 KeyWord const *kw;
229 while (isspace (*p))
230 p++;
232 /* Empty line or comment? */
233 if (!*p || *p == '\'')
234 continue;
236 /* In Basic, keywords always are at the start of the line. */
237 for (kw = keywords; kw->token; kw++)
238 if (match_keyword (p, kw)) break;
240 /* Is it a label? */
241 match_colon_label (p);
245 parserDefinition *FreeBasicParser (void)
247 static char const *extensions[] = { "bas", "bi", "bb", "pb", NULL };
248 parserDefinition *def = parserNew ("FreeBasic");
249 def->kinds = BasicKinds;
250 def->kindCount = KIND_COUNT (BasicKinds);
251 def->extensions = extensions;
252 def->parser = findBasicTags;
253 return def;
256 /* vi:set tabstop=4 shiftwidth=4: */