2 * Copyright (c) 2000-2006, Darren Hiebert, Elias Pschernig
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License version 2 or (at your option) any later version.
7 * This module contains functions for generating tags for BlitzBasic
8 * (BlitzMax), PureBasic and FreeBasic language files. For now, this is kept
9 * quite simple - but feel free to ask for more things added any time -
10 * patches are of course most welcome.
16 #include "general.h" /* must always come first */
42 static kindOption BasicKinds
[] = {
43 {TRUE
, 'c', "constant", "constants"},
44 {TRUE
, 'f', "function", "functions"},
45 {TRUE
, 'l', "label", "labels"},
46 {TRUE
, 't', "type", "types"},
47 {TRUE
, 'v', "variable", "variables"},
48 {TRUE
, 'g', "enum", "enumerations"}
51 static KeyWord freebasic_keywords
[] = {
52 {"dim", K_VARIABLE
}, /* must always be the first */
53 {"common", K_VARIABLE
}, /* must always be the second */
54 {"const", K_CONST
}, /* must always be the third */
55 {"function", K_FUNCTION
},
57 {"property", K_FUNCTION
},
58 {"constructor", K_FUNCTION
},
59 {"destructor", K_FUNCTION
},
60 {"private sub", K_FUNCTION
},
61 {"public sub", K_FUNCTION
},
62 {"private function", K_FUNCTION
},
63 {"public function", K_FUNCTION
},
70 * FUNCTION DEFINITIONS
73 /* Match the name of a dim or const starting at pos. */
74 static int extract_dim (char const *pos
, vString
* name
, BasicKind kind
)
76 const char *old_pos
= pos
;
77 while (isspace (*pos
))
80 /* create tags only if there is some space between the keyword and the identifier */
86 if (strncasecmp (pos
, "shared", 6) == 0)
87 pos
+= 6; /* skip keyword "shared" */
89 while (isspace (*pos
))
92 /* capture "dim as String str" */
93 if (strncasecmp (pos
, "as", 2) == 0)
95 pos
+= 2; /* skip keyword "as" */
97 while (isspace (*pos
))
99 while (!isspace (*pos
)) /* skip next part which is a type */
101 while (isspace (*pos
))
103 /* now we are at the name */
105 /* capture "dim as foo ptr bar" */
106 if (strncasecmp (pos
, "ptr", 3) == 0 && isspace(*(pos
+4)))
108 pos
+= 3; /* skip keyword "ptr" */
109 while (isspace (*pos
))
112 /* capture "dim as string * 4096 chunk" */
113 if (strncmp (pos
, "*", 1) == 0)
115 pos
+= 1; /* skip "*" */
116 while (isspace (*pos
) || isdigit(*pos
) || ispunct(*pos
))
120 for (; *pos
&& !isspace (*pos
) && *pos
!= '(' && *pos
!= ',' && *pos
!= '='; pos
++)
121 vStringPut (name
, *pos
);
122 vStringTerminate (name
);
123 makeSimpleTag (name
, BasicKinds
, kind
);
125 /* if the line contains a ',', we have multiple declarations */
126 while (*pos
&& strchr (pos
, ','))
128 /* skip all we don't need(e.g. "..., new_array(5), " we skip "(5)") */
129 while (*pos
!= ',' && *pos
!= '\'')
133 return 0; /* break if we are in a comment */
135 while (isspace (*pos
) || *pos
== ',')
139 return 0; /* break if we are in a comment */
142 for (; *pos
&& !isspace (*pos
) && *pos
!= '(' && *pos
!= ',' && *pos
!= '='; pos
++)
143 vStringPut (name
, *pos
);
144 vStringTerminate (name
);
145 makeSimpleTag (name
, BasicKinds
, kind
);
148 vStringDelete (name
);
152 /* Match the name of a tag (function, variable, type, ...) starting at pos. */
153 static char const *extract_name (char const *pos
, vString
* name
)
155 while (isspace (*pos
))
158 for (; *pos
&& !isspace (*pos
) && *pos
!= '(' && *pos
!= ',' && *pos
!= '='; pos
++)
159 vStringPut (name
, *pos
);
160 vStringTerminate (name
);
164 /* Match a keyword starting at p (case insensitive). */
165 static int match_keyword (const char *p
, KeyWord
const *kw
)
171 for (i
= 0; i
< strlen (kw
->token
); i
++)
173 if (tolower (p
[i
]) != kw
->token
[i
])
176 name
= vStringNew ();
178 if (kw
== &freebasic_keywords
[0] ||
179 kw
== &freebasic_keywords
[1] ||
180 kw
== &freebasic_keywords
[2])
181 return extract_dim (p
, name
, kw
->kind
); /* extract_dim adds the found tag(s) */
187 /* create tags only if there is some space between the keyword and the identifier */
190 vStringDelete (name
);
194 for (j
= 0; j
< 1; j
++)
196 p
= extract_name (p
, name
);
198 makeSimpleTag (name
, BasicKinds
, kw
->kind
);
199 vStringDelete (name
);
203 /* Match a "label:" style label. */
204 static void match_colon_label (char const *p
)
206 char const *end
= p
+ strlen (p
) - 1;
207 while (isspace (*end
))
211 vString
*name
= vStringNew ();
212 vStringNCatS (name
, p
, end
- p
);
213 makeSimpleTag (name
, BasicKinds
, K_LABEL
);
214 vStringDelete (name
);
218 static void findBasicTags (void)
223 keywords
= freebasic_keywords
;
225 while ((line
= (const char *) readLineFromInputFile ()) != NULL
)
227 const char *p
= line
;
233 /* Empty line or comment? */
234 if (!*p
|| *p
== '\'')
237 /* In Basic, keywords always are at the start of the line. */
238 for (kw
= keywords
; kw
->token
; kw
++)
239 if (match_keyword (p
, kw
)) break;
242 match_colon_label (p
);
246 parserDefinition
*FreeBasicParser (void)
248 static char const *extensions
[] = { "bas", "bi", "bb", "pb", NULL
};
249 parserDefinition
*def
= parserNew ("FreeBasic");
250 def
->kinds
= BasicKinds
;
251 def
->kindCount
= ARRAY_SIZE (BasicKinds
);
252 def
->extensions
= extensions
;
253 def
->parser
= findBasicTags
;
257 /* vi:set tabstop=4 shiftwidth=4: */