f4ba2a48913ad26c195efe24585031ac6a5fb91a
[cparser] / ast.c
1 #include <config.h>
2
3 #include "ast_t.h"
4 #include "type_t.h"
5
6 #include <assert.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <ctype.h>
10
11 #include "adt/error.h"
12
13 struct obstack ast_obstack;
14
15 static FILE *out;
16 static int   indent;
17
18 static void print_statement(const statement_t *statement);
19 static void print_declaration(const declaration_t *declaration);
20
21 static void print_indent(void)
22 {
23         for(int i = 0; i < indent; ++i)
24                 fprintf(out, "\t");
25 }
26
27 static void print_const(const const_t *cnst)
28 {
29         if(cnst->expression.datatype == NULL)
30                 return;
31
32         if(is_type_integer(cnst->expression.datatype)) {
33                 fprintf(out, "%d", cnst->v.int_value);
34         }
35 }
36
37 static void print_string_literal(const string_literal_t *string_literal)
38 {
39         fputc('"', out);
40         for(const char *c = string_literal->value; *c != '\0'; ++c) {
41                 switch(*c) {
42                 case '\"':  fputs("\\\"", out); break;
43                 case '\\':  fputs("\\\\", out); break;
44                 case '\a':  fputs("\\a", out); break;
45                 case '\b':  fputs("\\b", out); break;
46                 case '\f':  fputs("\\f", out); break;
47                 case '\n':  fputs("\\n", out); break;
48                 case '\r':  fputs("\\r", out); break;
49                 case '\t':  fputs("\\t", out); break;
50                 case '\v':  fputs("\\v", out); break;
51                 case '\?':  fputs("\\?", out); break;
52                 default:
53                         if(!isprint(*c)) {
54                                 fprintf(out, "\\x%x", *c);
55                                 break;
56                         }
57                         fputc(*c, out);
58                         break;
59                 }
60         }
61         fputc('"', out);
62 }
63
64 static void print_call_expression(const call_expression_t *call)
65 {
66         print_expression(call->method);
67         fprintf(out, "(");
68         call_argument_t *argument = call->arguments;
69         int              first    = 1;
70         while(argument != NULL) {
71                 if(!first) {
72                         fprintf(out, ", ");
73                 } else {
74                         first = 0;
75                 }
76                 print_expression(argument->expression);
77
78                 argument = argument->next;
79         }
80         fprintf(out, ")");
81 }
82
83 static void print_binary_expression(const binary_expression_t *binexpr)
84 {
85         fprintf(out, "(");
86         print_expression(binexpr->left);
87         fprintf(out, " ");
88         switch(binexpr->type) {
89         case BINEXPR_INVALID:            fputs("INVOP", out); break;
90         case BINEXPR_COMMA:              fputs(",", out);     break;
91         case BINEXPR_ASSIGN:             fputs("=", out);     break;
92         case BINEXPR_ADD:                fputs("+", out);     break;
93         case BINEXPR_SUB:                fputs("-", out);     break;
94         case BINEXPR_MUL:                fputs("*", out);     break;
95         case BINEXPR_MOD:                fputs("%", out);     break;
96         case BINEXPR_DIV:                fputs("/", out);     break;
97         case BINEXPR_BITWISE_OR:         fputs("|", out);     break;
98         case BINEXPR_BITWISE_AND:        fputs("&", out);     break;
99         case BINEXPR_BITWISE_XOR:        fputs("^", out);     break;
100         case BINEXPR_LOGICAL_OR:         fputs("||", out);    break;
101         case BINEXPR_LOGICAL_AND:        fputs("&&", out);    break;
102         case BINEXPR_NOTEQUAL:           fputs("!=", out);    break;
103         case BINEXPR_EQUAL:              fputs("==", out);    break;
104         case BINEXPR_LESS:               fputs("<", out);     break;
105         case BINEXPR_LESSEQUAL:          fputs("<=", out);    break;
106         case BINEXPR_GREATER:            fputs(">", out);     break;
107         case BINEXPR_GREATEREQUAL:       fputs(">=", out);    break;
108         case BINEXPR_SHIFTLEFT:          fputs("<<", out);    break;
109         case BINEXPR_SHIFTRIGHT:         fputs(">>", out);    break;
110
111         case BINEXPR_ADD_ASSIGN:         fputs("+=", out);    break;
112         case BINEXPR_SUB_ASSIGN:         fputs("-=", out);    break;
113         case BINEXPR_MUL_ASSIGN:         fputs("*=", out);    break;
114         case BINEXPR_MOD_ASSIGN:         fputs("%=", out);    break;
115         case BINEXPR_DIV_ASSIGN:         fputs("/=", out);    break;
116         case BINEXPR_BITWISE_OR_ASSIGN:  fputs("|=", out);    break;
117         case BINEXPR_BITWISE_AND_ASSIGN: fputs("&=", out);    break;
118         case BINEXPR_BITWISE_XOR_ASSIGN: fputs("^=", out);    break;
119         case BINEXPR_SHIFTLEFT_ASSIGN:   fputs("<<=", out);   break;
120         case BINEXPR_SHIFTRIGHT_ASSIGN:  fputs(">>=", out);   break;
121         }
122         fprintf(out, " ");
123         print_expression(binexpr->right);
124         fprintf(out, ")");
125 }
126
127 static void print_unary_expression(const unary_expression_t *unexpr)
128 {
129         switch(unexpr->type) {
130         case UNEXPR_NEGATE:           fputs("-", out);  break;
131         case UNEXPR_PLUS:             fputs("+", out);  break;
132         case UNEXPR_NOT:              fputs("!", out);  break;
133         case UNEXPR_BITWISE_NEGATE:   fputs("~", out);  break;
134         case UNEXPR_PREFIX_INCREMENT: fputs("++", out); break;
135         case UNEXPR_PREFIX_DECREMENT: fputs("--", out); break;
136         case UNEXPR_DEREFERENCE:      fputs("*", out);  break;
137         case UNEXPR_TAKE_ADDRESS:     fputs("&", out);  break;
138
139         case UNEXPR_POSTFIX_INCREMENT:
140                 fputs("(", out);
141                 print_expression(unexpr->value);
142                 fputs(")", out);
143                 fputs("++", out);
144                 return;
145         case UNEXPR_POSTFIX_DECREMENT:
146                 fputs("(", out);
147                 print_expression(unexpr->value);
148                 fputs(")", out);
149                 fputs("--", out);
150                 return;
151         case UNEXPR_CAST:
152                 fputs("(", out);
153                 print_type(unexpr->expression.datatype);
154                 fputs(")", out);
155                 break;
156         case UNEXPR_INVALID:
157                 fprintf(out, "unop%d", unexpr->type);
158                 break;
159         }
160         fputs("(", out);
161         print_expression(unexpr->value);
162         fputs(")", out);
163 }
164
165 static void print_reference_expression(const reference_expression_t *ref)
166 {
167         fprintf(out, "%s", ref->declaration->symbol->string);
168 }
169
170 static void print_array_expression(const array_access_expression_t *expression)
171 {
172         fputs("(", out);
173         print_expression(expression->array_ref);
174         fputs(")[", out);
175         print_expression(expression->index);
176         fputs("]", out);
177 }
178
179 static void print_sizeof_expression(const sizeof_expression_t *expression)
180 {
181         fputs("sizeof", out);
182         if(expression->size_expression != NULL) {
183                 fputc('(', out);
184                 print_expression(expression->size_expression);
185                 fputc(')', out);
186         } else {
187                 fputc('(', out);
188                 print_type(expression->type);
189                 fputc(')', out);
190         }
191 }
192
193 static void print_builtin_symbol(const builtin_symbol_expression_t *expression)
194 {
195         fputs(expression->symbol->string, out);
196 }
197
198 void print_expression(const expression_t *expression)
199 {
200         switch(expression->type) {
201         case EXPR_INVALID:
202                 fprintf(out, "*invalid expression*");
203                 break;
204         case EXPR_CONST:
205                 print_const((const const_t*) expression);
206                 break;
207         case EXPR_FUNCTION:
208         case EXPR_PRETTY_FUNCTION:
209         case EXPR_STRING_LITERAL:
210                 print_string_literal((const string_literal_t*) expression);
211                 break;
212         case EXPR_CALL:
213                 print_call_expression((const call_expression_t*) expression);
214                 break;
215         case EXPR_BINARY:
216                 print_binary_expression((const binary_expression_t*) expression);
217                 break;
218         case EXPR_REFERENCE:
219                 print_reference_expression((const reference_expression_t*) expression);
220                 break;
221         case EXPR_ARRAY_ACCESS:
222                 print_array_expression((const array_access_expression_t*) expression);
223                 break;
224         case EXPR_UNARY:
225                 print_unary_expression((const unary_expression_t*) expression);
226                 break;
227         case EXPR_SIZEOF:
228                 print_sizeof_expression((const sizeof_expression_t*) expression);
229                 break;
230         case EXPR_BUILTIN_SYMBOL:
231                 print_builtin_symbol((const builtin_symbol_expression_t*) expression);
232                 break;
233
234         case EXPR_CONDITIONAL:
235         case EXPR_OFFSETOF:
236         case EXPR_STATEMENT:
237         case EXPR_SELECT:
238                 /* TODO */
239                 fprintf(out, "some expression of type %d", expression->type);
240                 break;
241         }
242 }
243
244 static void print_compound_statement(const compound_statement_t *block)
245 {
246         fputs("{\n", out);
247         indent++;
248
249         statement_t *statement = block->statements;
250         while(statement != NULL) {
251                 print_indent();
252                 print_statement(statement);
253
254                 statement = statement->next;
255         }
256         indent--;
257         print_indent();
258         fputs("}\n", out);
259 }
260
261 static void print_return_statement(const return_statement_t *statement)
262 {
263         fprintf(out, "return ");
264         if(statement->return_value != NULL)
265                 print_expression(statement->return_value);
266         fputs(";\n", out);
267 }
268
269 static void print_expression_statement(const expression_statement_t *statement)
270 {
271         print_expression(statement->expression);
272         fputs(";\n", out);
273 }
274
275 static void print_goto_statement(const goto_statement_t *statement)
276 {
277         fprintf(out, "goto ");
278         if(statement->label != NULL) {
279                 fprintf(out, "%s", statement->label->symbol->string);
280         } else {
281                 fprintf(out, "?%s", statement->label_symbol->string);
282         }
283         fputs(";\n", out);
284 }
285
286 static void print_label_statement(const label_statement_t *statement)
287 {
288         fprintf(out, "%s:\n", statement->symbol->string);
289 }
290
291 static void print_if_statement(const if_statement_t *statement)
292 {
293         fputs("if(", out);
294         print_expression(statement->condition);
295         fputs(") ", out);
296         if(statement->true_statement != NULL) {
297                 print_statement(statement->true_statement);
298         }
299
300         if(statement->false_statement != NULL) {
301                 print_indent();
302                 fputs("else ", out);
303                 print_statement(statement->false_statement);
304         }
305 }
306
307 static void print_switch_statement(const switch_statement_t *statement)
308 {
309         fputs("switch(", out);
310         print_expression(statement->expression);
311         fputs(") ", out);
312         print_statement(statement->body);
313 }
314
315 static void print_case_label(const case_label_statement_t *statement)
316 {
317         if(statement->expression == NULL) {
318                 fputs("default:\n", out);
319         } else {
320                 fputs("case ", out);
321                 print_expression(statement->expression);
322                 fputs(":\n", out);
323         }
324 }
325
326 static void print_declaration_statement(
327                 const declaration_statement_t *statement)
328 {
329         declaration_t *declaration = statement->declarations_begin;
330         for( ; declaration != statement->declarations_end->next;
331                declaration = declaration->next) {
332                 print_declaration(declaration);
333         }
334 }
335
336 static void print_while_statement(const while_statement_t *statement)
337 {
338         fputs("while(", out);
339         print_expression(statement->condition);
340         fputs(") ", out);
341         print_statement(statement->body);
342 }
343
344 static void print_do_while_statement(const do_while_statement_t *statement)
345 {
346         fputs("do ", out);
347         print_statement(statement->body);
348         print_indent();
349         fputs("while(", out);
350         print_expression(statement->condition);
351         fputs(");\n", out);
352 }
353
354 static void print_for_statemenet(const for_statement_t *statement)
355 {
356         fprintf(out, "for(TODO) ");
357         print_statement(statement->body);
358 }
359
360 void print_statement(const statement_t *statement)
361 {
362         switch(statement->type) {
363         case STATEMENT_COMPOUND:
364                 print_compound_statement((const compound_statement_t*) statement);
365                 break;
366         case STATEMENT_RETURN:
367                 print_return_statement((const return_statement_t*) statement);
368                 break;
369         case STATEMENT_EXPRESSION:
370                 print_expression_statement((const expression_statement_t*) statement);
371                 break;
372         case STATEMENT_LABEL:
373                 print_label_statement((const label_statement_t*) statement);
374                 break;
375         case STATEMENT_GOTO:
376                 print_goto_statement((const goto_statement_t*) statement);
377                 break;
378         case STATEMENT_CONTINUE:
379                 fputs("continue;\n", out);
380                 break;
381         case STATEMENT_BREAK:
382                 fputs("break;\n", out);
383                 break;
384         case STATEMENT_IF:
385                 print_if_statement((const if_statement_t*) statement);
386                 break;
387         case STATEMENT_SWITCH:
388                 print_switch_statement((const switch_statement_t*) statement);
389                 break;
390         case STATEMENT_CASE_LABEL:
391                 print_case_label((const case_label_statement_t*) statement);
392                 break;
393         case STATEMENT_DECLARATION:
394                 print_declaration_statement((const declaration_statement_t*) statement);
395                 break;
396         case STATEMENT_WHILE:
397                 print_while_statement((const while_statement_t*) statement);
398                 break;
399         case STATEMENT_DO_WHILE:
400                 print_do_while_statement((const do_while_statement_t*) statement);
401                 break;
402         case STATEMENT_FOR:
403                 print_for_statemenet((const for_statement_t*) statement);
404                 break;
405         case STATEMENT_INVALID:
406                 fprintf(out, "*invalid statement*");
407                 break;
408         }
409 }
410
411 static void print_storage_class(storage_class_t storage_class)
412 {
413         switch(storage_class) {
414         case STORAGE_CLASS_ENUM_ENTRY:
415         case STORAGE_CLASS_NONE:
416                 break;
417         case STORAGE_CLASS_TYPEDEF:  fputs("typedef ", out); break;
418         case STORAGE_CLASS_EXTERN:   fputs("extern ", out); break;
419         case STORAGE_CLASS_STATIC:   fputs("static ", out); break;
420         case STORAGE_CLASS_AUTO:     fputs("auto ", out); break;
421         case STORAGE_CLASS_REGISTER: fputs("register ", out); break;
422         }
423 }
424
425 static void print_declaration(const declaration_t *declaration)
426 {
427         print_storage_class(declaration->storage_class);
428         print_type_ext(declaration->type, declaration->symbol,
429                        &declaration->context);
430         if(declaration->statement != NULL) {
431                 fputs("\n", out);
432                 print_statement(declaration->statement);
433         } else if(declaration->initializer != NULL) {
434                 fputs(" = ", out);
435                 print_expression(declaration->initializer);
436                 fprintf(out, ";\n");
437         } else {
438                 fprintf(out, ";\n");
439         }
440 }
441
442 void print_ast(const translation_unit_t *unit)
443 {
444         declaration_t *declaration = unit->context.declarations;
445         while(declaration != NULL) {
446                 print_declaration(declaration);
447
448                 declaration = declaration->next;
449         }
450 }
451
452 void init_ast(void)
453 {
454         obstack_init(&ast_obstack);
455 }
456
457 void exit_ast(void)
458 {
459         obstack_free(&ast_obstack, NULL);
460 }
461
462 void ast_set_output(FILE *stream)
463 {
464         out = stream;
465         type_set_output(stream);
466 }
467
468 void* (allocate_ast) (size_t size)
469 {
470         return _allocate_ast(size);
471 }