use builtin operator associativity functionality
[ccc.git] / ast.c
1 #include <stdlib.h>
2 #include <stdio.h>
3
4 #include "ast.h"
5
6 struct ast *ast_alloc()
7 {
8 struct ast *res = malloc(sizeof(struct ast));
9 if (res == NULL) {
10 perror("malloc");
11 exit(1);
12 }
13 return res;
14 }
15
16 struct ast *ast_cons(struct ast *el, struct ast *tail)
17 {
18 struct ast *res = ast_alloc();
19 res->type = an_cons;
20 res->data.an_cons.el = el;
21 res->data.an_cons.tail = tail;
22 return res;
23 }
24
25 struct ast *ast_binop(struct ast *l, enum binop op, struct ast *r)
26 {
27 struct ast *res = ast_alloc();
28 res->type = an_binop;
29 res->data.an_binop.l = l;
30 res->data.an_binop.op = op;
31 res->data.an_binop.r = r;
32 return res;
33 }
34
35 struct ast *ast_int(int integer)
36 {
37 struct ast *res = ast_alloc();
38 res->type = an_int;
39 res->data.an_int = integer;
40 return res;
41 }
42
43 struct ast *ast_unop(enum unop op, struct ast *l)
44 {
45 struct ast *res = ast_alloc();
46 res->type = an_unop;
47 res->data.an_unop.op = op;
48 res->data.an_unop.l = l;
49 return res;
50 }
51 static const char *binop_str[] = {
52 [binor] = "||",
53 [binand] = "&&",
54 [eq] = "==",
55 [neq] = "!=",
56 [leq] = "<=",
57 [le] = "<",
58 [geq] = ">=",
59 [ge] = ">",
60 [cons] = ":",
61 [plus] = "+",
62 [minus] = "-",
63 [times] = "*",
64 [divide] = "/",
65 [modulo] = "%",
66 [power] = "^",
67 };
68 static const char *unop_str[] = {
69 [inverse] = "!",
70 [negate] = "-",
71 };
72
73 void ast_print(struct ast * ast, FILE *out)
74 {
75 if (ast == NULL)
76 return;
77 switch(ast->type) {
78 case an_binop:
79 fprintf(out, "(");
80 ast_print(ast->data.an_binop.l, out);
81 fprintf(out, "%s", binop_str[ast->data.an_binop.op]);
82 ast_print(ast->data.an_binop.r, out);
83 fprintf(out, ")");
84 break;
85 case an_cons:
86 ast_print(ast->data.an_cons.el, out);
87 fprintf(out, ";\n");
88 ast_print(ast->data.an_cons.tail, out);
89 break;
90 case an_int:
91 fprintf(out, "%d", ast->data.an_int);
92 break;
93 case an_unop:
94 fprintf(out, "(-");
95 ast_print(ast->data.an_unop.l, out);
96 fprintf(out, ")");
97 break;
98 default:
99 fprintf(stderr, "Unsupported AST node\n");
100 exit(1);
101 }
102 }
103
104 void ast_free(struct ast *ast)
105 {
106 if (ast == NULL)
107 return;
108 switch(ast->type) {
109 case an_binop:
110 ast_free(ast->data.an_binop.l);
111 ast_free(ast->data.an_binop.r);
112 break;
113 case an_cons:
114 ast_free(ast->data.an_cons.el);
115 ast_free(ast->data.an_cons.tail);
116 break;
117 case an_int:
118 break;
119 default:
120 fprintf(stderr, "Unsupported AST node\n");
121 exit(1);
122 }
123 free(ast);
124 }