fix multiline comment parsing, extended comment test
[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
10 #include "adt/error.h"
11
12 struct obstack ast_obstack;
13
14 static
15 void print_const(FILE *out, const const_t *cnst)
16 {
17         fprintf(out, "%d", cnst->value);
18 }
19
20 static
21 void print_string_literal(FILE *out, const string_literal_t *string_literal)
22 {
23         /* TODO escape " and non-printable chars */
24         fprintf(out, "\"%s\"", string_literal->value);
25 }
26
27 static
28 void print_call_expression(FILE *out, const call_expression_t *call)
29 {
30         print_expression(out, call->method);
31         fprintf(out, "(");
32         call_argument_t *argument = call->arguments;
33         int              first    = 1;
34         while(argument != NULL) {
35                 if(!first) {
36                         fprintf(out, ", ");
37                 } else {
38                         first = 0;
39                 }
40                 print_expression(out, argument->expression);
41
42                 argument = argument->next;
43         }
44         fprintf(out, ")");
45 }
46
47 static
48 void print_binary_expression(FILE *out, const binary_expression_t *binexpr)
49 {
50         fprintf(out, "(");
51         print_expression(out, binexpr->left);
52         fprintf(out, " ");
53         switch(binexpr->type) {
54         case BINEXPR_INVALID:
55                 fprintf(out, "INVOP");
56                 break;
57         case BINEXPR_ASSIGN:
58                 fprintf(out, "<-");
59                 break;
60         case BINEXPR_ADD:
61                 fprintf(out, "+");
62                 break;
63         case BINEXPR_SUB:
64                 fprintf(out, "-");
65                 break;
66         case BINEXPR_NOTEQUAL:
67                 fprintf(out, "/=");
68                 break;
69         case BINEXPR_EQUAL:
70                 fprintf(out, "=");
71                 break;
72         case BINEXPR_LESS:
73                 fprintf(out, "<");
74                 break;
75         case BINEXPR_LESSEQUAL:
76                 fprintf(out, "<=");
77                 break;
78         case BINEXPR_GREATER:
79                 fprintf(out, ">");
80                 break;
81         case BINEXPR_GREATEREQUAL:
82                 fprintf(out, ">=");
83                 break;
84         default:
85                 /* TODO: add missing ops */
86                 fprintf(out, "op%d", binexpr->type);
87                 break;
88         }
89         fprintf(out, " ");
90         print_expression(out, binexpr->right);
91         fprintf(out, ")");
92 }
93
94 void print_expression(FILE *out, const expression_t *expression)
95 {
96         switch(expression->type) {
97         case EXPR_INVALID:
98                 fprintf(out, "*invalid expression*");
99                 break;
100         case EXPR_CONST:
101                 print_const(out, (const const_t*) expression);
102                 break;
103         case EXPR_STRING_LITERAL:
104                 print_string_literal(out, (const string_literal_t*) expression);
105                 break;
106         case EXPR_CALL:
107                 print_call_expression(out, (const call_expression_t*) expression);
108                 break;
109         case EXPR_BINARY:
110                 print_binary_expression(out, (const binary_expression_t*) expression);
111                 break;
112         case EXPR_REFERENCE:
113         case EXPR_UNARY:
114         case EXPR_SELECT:
115         case EXPR_ARRAY_ACCESS:
116         case EXPR_SIZEOF:
117                 /* TODO */
118                 fprintf(out, "some expression of type %d", expression->type);
119                 break;
120         }
121 }
122
123 static
124 void print_block_statement(FILE *out, int indent,
125                            const block_statement_t *block)
126 {
127         statement_t *statement = block->first_statement;
128         while(statement != NULL) {
129                 print_statement(out, indent + 1, statement);
130
131                 statement = statement->next;
132         }
133 }
134
135 static
136 void print_return_statement(FILE *out, const return_statement_t *statement)
137 {
138         fprintf(out, "return ");
139         if(statement->return_value != NULL)
140                 print_expression(out, statement->return_value);
141 }
142
143 static
144 void print_expression_statement(FILE *out,
145                                 const expression_statement_t *statement)
146 {
147         print_expression(out, statement->expression);
148 }
149
150 static
151 void print_goto_statement(FILE *out, const goto_statement_t *statement)
152 {
153         fprintf(out, "goto ");
154         if(statement->label != NULL) {
155                 fprintf(out, "%s", statement->label->symbol->string);
156         } else {
157                 fprintf(out, "?%s", statement->label_symbol->string);
158         }
159 }
160
161 static
162 void print_label_statement(FILE *out, const label_statement_t *statement)
163 {
164         fprintf(out, ":%s", statement->symbol->string);
165 }
166
167 static
168 void print_if_statement(FILE *out, int indent, const if_statement_t *statement)
169 {
170         fprintf(out, "if ");
171         print_expression(out, statement->condition);
172         fprintf(out, ":\n");
173         if(statement->true_statement != NULL) {
174                 print_statement(out, indent, statement->true_statement);
175         }
176
177         if(statement->false_statement != NULL) {
178                 fprintf(out, "else:\n");
179                 print_statement(out, indent, statement->false_statement);
180         }
181 }
182
183 static
184 void print_variable_declaration_statement(FILE *out,
185                      const variable_declaration_statement_t *statement)
186 {
187         fprintf(out, "var");
188         if(statement->type != NULL) {
189                 fprintf(out, "<");
190                 print_type(out, statement->type);
191                 fprintf(out, ">");
192         }
193         fprintf(out, " %s", statement->symbol->string);
194 }
195
196 void print_statement(FILE *out, int indent, const statement_t *statement)
197 {
198         for(int i = 0; i < indent; ++i)
199                 fprintf(out, "\t");
200
201         switch(statement->type) {
202         case STATEMENT_BLOCK:
203                 print_block_statement(out, indent,
204                                       (const block_statement_t*) statement);
205                 break;
206         case STATEMENT_RETURN:
207                 print_return_statement(out, (const return_statement_t*) statement);
208                 break;
209         case STATEMENT_EXPRESSION:
210                 print_expression_statement(out,
211                                            (const expression_statement_t*) statement);
212                 break;
213         case STATEMENT_LABEL:
214                 print_label_statement(out, (const label_statement_t*) statement);
215                 break;
216         case STATEMENT_GOTO:
217                 print_goto_statement(out, (const goto_statement_t*) statement);
218                 break;
219         case STATEMENT_IF:
220                 print_if_statement(out, indent, (const if_statement_t*) statement);
221                 break;
222         case STATEMENT_VARIABLE_DECLARATION:
223                 print_variable_declaration_statement(out,
224                         (const variable_declaration_statement_t*) statement);
225                 break;
226         case STATEMENT_INVALID:
227         default:
228                 fprintf(out, "*invalid statement*");
229                 break;
230
231         }
232         fprintf(out, "\n");
233 }
234
235 static
236 void print_method_parameters(FILE *out, const method_parameter_t *parameters,
237                              const method_type_t *method_type)
238 {
239         fprintf(out, "(");
240
241         int                            first          = 1;
242         const method_parameter_t      *parameter      = parameters;
243         const method_parameter_type_t *parameter_type
244                 = method_type->parameter_types;
245         while(parameter != NULL && parameter_type != NULL) {
246                 if(!first) {
247                         fprintf(out, ", ");
248                 } else {
249                         first = 0;
250                 }
251
252                 print_type(out, parameter_type->type);
253                 fprintf(out, " %s", parameter->symbol->string);
254
255                 parameter      = parameter->next;
256                 parameter_type = parameter_type->next;
257         }
258         assert(parameter == NULL && parameter_type == NULL);
259
260         fprintf(out, ")");
261 }
262
263 static
264 void print_method(FILE *out, const method_t *method)
265 {
266         method_type_t *type = method->type;
267
268         fprintf(out, "func ");
269         print_type(out, type->result_type);
270         fprintf(out, " %s", method->symbol->string);
271
272         print_method_parameters(out, method->parameters, type);
273
274         if(method->statement != NULL) {
275                 fprintf(out, ":\n");
276                 print_statement(out, 0, method->statement);
277         } else {
278                 fprintf(out, "\n");
279         }
280 }
281
282 static
283 void print_namespace_entry(FILE *out, const namespace_entry_t *entry)
284 {
285         switch(entry->type) {
286         case NAMESPACE_ENTRY_METHOD:
287                 print_method(out, (const method_t*) entry);
288                 break;
289         case NAMESPACE_ENTRY_VARIABLE:
290                 /* TODO */
291                 fprintf(out, "some namespace entry of type %d\n\n", entry->type);
292                 break;
293         case NAMESPACE_ENTRY_INVALID:
294         default:
295                 fprintf(out, "invalid namespace entry (%d)\n", entry->type);
296                 break;
297         }
298 }
299
300 void print_ast(FILE *out, const namespace_t *namespace)
301 {
302         namespace_entry_t *entry = namespace->entries;
303
304         while(entry != NULL) {
305                 print_namespace_entry(out, entry);
306
307                 entry = entry->next;
308         }
309 }
310
311 void init_ast_module(void)
312 {
313         obstack_init(&ast_obstack);
314 }
315
316 void exit_ast_module(void)
317 {
318         obstack_free(&ast_obstack, NULL);
319 }
320
321 void* (allocate_ast) (size_t size)
322 {
323         return _allocate_ast(size);
324 }