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