2 * Deals with all the complexity in C's declaration specification with
3 * a rather large state machine model. C has a lot of ways to specify
4 * something, that happens to be equivlant to other meanings, which are
5 * also used. This state machine monitors the occurance of certain
6 * identifiers to build a serise of on/off state which ultimatly
7 * allows us to disambiguate the meaning, while at the same time enforcing
10 * For instance it isn't legal in C to have a typedef of a 'signed' size
11 * specified type, than use that typedef with another size specifier.
12 * More of these rules apply as well, and are documented in the state
15 * Once the state machine has completed it's work the get function uses
16 * the state of the machine to determine what type to return from the
17 * ast data table for types, or if there needs to be a new type created
18 * to compensate for the declaration. Similarly at this stage the state
19 * can be invalid (if something wen terribly wrong) and we can handle,
22 * The main entry point is decl_spec and it's called from the parser,
23 * if everything passes the callsite gets a data_type_t of the type
55 static const char *spec_type_string[] = {
56 "null", "void", "_Bool", "char",
57 "int", "float", "double"
60 static const char *spec_size_string[] = {
61 "null", "short", "long", "long long"
64 static const char *spec_sign_string[] = {
65 "null", "signed", "unsigned"
68 static const char *spec_var_string[] = {
69 "null", "type", "size", "sign", "user"
91 #define decl_spec_error(X, SELECT) \
92 decl_spec_error_impl((X), (SELECT), __LINE__)
94 static const char *debug_storage_string(const storage_t class) {
96 case STORAGE_AUTO: return "auto";
97 case STORAGE_EXTERN: return "extern";
98 case STORAGE_REGISTER: return "register";
99 case STORAGE_STATIC: return "static";
100 case STORAGE_TYPEDEF: return "typedef";
105 static void decl_spec_error_impl(const decl_spec_t *spec, const decl_var_t select, const size_t line) {
106 const char *type = spec_type_string[spec->type];
107 const char *size = spec_size_string[spec->size];
108 const char *sign = spec_sign_string[spec->sign];
109 const char *var = spec_var_string[select];
111 if (!type) type = "unspecified";
112 if (!size) size = "unspecified";
113 if (!sign) sign = "unspecified";
114 if (!var) var = "unspecified";
116 compile_ice("declaration specifier error %d\n"
128 debug_storage_string(spec->class),
132 bool_string(spec->kconst),
133 bool_string(spec->kvolatile),
134 bool_string(spec->kinline)
138 static void decl_spec_class(decl_spec_t *spec, const storage_t class) {
139 if (spec->class != 0)
140 decl_spec_error(spec, SPEC_VAR_NULL);
144 static void decl_spec_set(decl_spec_t *spec, const decl_var_t select, void *value) {
147 if (spec->sign != SPEC_SIGN_NULL)
148 decl_spec_error(spec, select);
149 spec->sign = *(spec_sign_t*)value;
152 if (spec->size != SPEC_SIZE_NULL)
153 decl_spec_error(spec, select);
154 spec->size = *(spec_size_t*)value;
157 if (spec->type != SPEC_TYPE_NULL)
158 decl_spec_error(spec, select);
159 spec->type = *(spec_type_t*)value;
163 decl_spec_error(spec, select);
167 compile_ice("decl_spec_get state machine got null variable reference");
171 /* bool cannot have a sign, it's only legal as it's own entity. */
172 if (spec->type == SPEC_TYPE_BOOL && (spec->size != SPEC_SIZE_NULL && spec->sign != SPEC_SIGN_NULL))
173 decl_spec_error(spec, select);
175 switch (spec->size) {
176 case SPEC_SIZE_SHORT:
178 * short and short int are the only legal uses of the short
181 if (spec->type != SPEC_TYPE_NULL && spec->type != SPEC_TYPE_INT)
182 decl_spec_error(spec, select);
187 * long, long int and long double are the only legal uses of
188 * long size specifier.
190 if (spec->type != SPEC_TYPE_NULL && spec->type != SPEC_TYPE_INT && spec->type != SPEC_TYPE_DOUBLE)
191 decl_spec_error(spec, select);
199 * sign and unsigned sign specifiers are not legal on void, float and
202 if (spec->sign != SPEC_SIGN_NULL) {
203 switch (spec->type) {
205 case SPEC_TYPE_FLOAT:
206 case SPEC_TYPE_DOUBLE:
207 decl_spec_error(spec, select);
215 * user types cannot have additional levels of specification on it,
216 * for instance 'typedef unsigned int foo; 'signed foo'.
218 if (spec->user && (spec->type != SPEC_TYPE_NULL ||
219 spec->size != SPEC_SIZE_NULL ||
220 spec->sign != SPEC_SIGN_NULL))
221 decl_spec_error(spec, select);
224 #define decl_spec_seti(SPEC, SELECT, VAR) \
225 decl_spec_set((SPEC), (SELECT), &(int){ VAR })
227 static data_type_t *decl_spec_get(const decl_spec_t *spec) {
228 bool sign = !!(spec->sign != SPEC_SIGN_UNSIGNED);
230 switch (spec->type) {
232 return ast_data_table[AST_DATA_VOID];
234 return ast_type_create(TYPE_BOOL, false);
236 return ast_type_create(TYPE_CHAR, sign);
237 case SPEC_TYPE_FLOAT:
238 return ast_type_create(TYPE_FLOAT, false);
239 case SPEC_TYPE_DOUBLE:
240 if (spec->size == SPEC_SIZE_LONG)
241 return ast_type_create(TYPE_LDOUBLE, false);
242 return ast_type_create(TYPE_DOUBLE, false);
247 switch (spec->size) {
248 case SPEC_SIZE_SHORT:
249 return ast_type_create(TYPE_SHORT, sign);
251 return ast_type_create(TYPE_LONG, sign);
252 case SPEC_SIZE_LLONG:
253 return ast_type_create(TYPE_LLONG, sign);
256 return ast_type_create(TYPE_INT, sign);
258 compile_ice("declaration specifier");
261 data_type_t *decl_spec(storage_t *const class) {
263 memset(&spec, 0, sizeof(spec));
266 lexer_token_t *token = lexer_next();
268 compile_error("type specification with unexpected ending");
270 if (token->type != LEXER_TOKEN_IDENTIFIER) {
275 if (!strcmp(token->string, "const"))
277 else if (!strcmp(token->string, "volatile"))
278 spec.kvolatile = true;
279 else if (!strcmp(token->string, "inline"))
281 else if (!strcmp(token->string, "typedef"))
282 decl_spec_class(&spec, STORAGE_TYPEDEF);
283 else if (!strcmp(token->string, "extern"))
284 decl_spec_class(&spec, STORAGE_EXTERN);
285 else if (!strcmp(token->string, "static") || !strcmp(token->string, "__static__"))
286 decl_spec_class(&spec, STORAGE_STATIC);
287 else if (!strcmp(token->string, "auto"))
288 decl_spec_class(&spec, STORAGE_AUTO);
289 else if (!strcmp(token->string, "register"))
290 decl_spec_class(&spec, STORAGE_REGISTER);
291 else if (!strcmp(token->string, "void"))
292 decl_spec_seti(&spec, SPEC_VAR_TYPE, SPEC_TYPE_VOID);
293 else if (!strcmp(token->string, "_Bool"))
294 decl_spec_seti(&spec, SPEC_VAR_TYPE, SPEC_TYPE_BOOL);
295 else if (!strcmp(token->string, "char"))
296 decl_spec_seti(&spec, SPEC_VAR_TYPE, SPEC_TYPE_CHAR);
297 else if (!strcmp(token->string, "int"))
298 decl_spec_seti(&spec, SPEC_VAR_TYPE, SPEC_TYPE_INT);
299 else if (!strcmp(token->string, "float"))
300 decl_spec_seti(&spec, SPEC_VAR_TYPE, SPEC_TYPE_FLOAT);
301 else if (!strcmp(token->string, "double"))
302 decl_spec_seti(&spec, SPEC_VAR_TYPE, SPEC_TYPE_DOUBLE);
303 else if (!strcmp(token->string, "signed"))
304 decl_spec_seti(&spec, SPEC_VAR_SIGN, SPEC_SIGN_SIGNED);
305 else if (!strcmp(token->string, "unsigned"))
306 decl_spec_seti(&spec, SPEC_VAR_SIGN, SPEC_SIGN_UNSIGNED);
307 else if (!strcmp(token->string, "struct"))
308 decl_spec_set(&spec, SPEC_VAR_USER, parse_structure());
309 else if (!strcmp(token->string, "union"))
310 decl_spec_set(&spec, SPEC_VAR_USER, parse_union());
311 else if (!strcmp(token->string, "enum"))
312 decl_spec_set(&spec, SPEC_VAR_USER, parse_enumeration());
313 else if (!strcmp(token->string, "short"))
314 decl_spec_seti(&spec, SPEC_VAR_SIZE, SPEC_SIZE_SHORT);
315 else if (!strcmp(token->string, "long")) {
317 decl_spec_seti(&spec, SPEC_VAR_SIZE, SPEC_SIZE_LONG);
318 else if (spec.size == SPEC_SIZE_LONG)
319 spec.size = SPEC_SIZE_LLONG;
321 decl_spec_error(&spec, SPEC_VAR_NULL);
323 else if (!strcmp(token->string, "typeof") || !strcmp(token->string, "__typeof__"))
324 decl_spec_set(&spec, SPEC_VAR_USER, parse_typeof());
325 else if (parse_typedef_find(token->string) && !spec.user)
326 decl_spec_set(&spec, SPEC_VAR_USER, parse_typedef_find(token->string));
338 return decl_spec_get(&spec);