Parse function body.
[mcc.git] / stree.c
blobcd5d7c13aa1d82eb65c3516fdcc386158ec83f71
1 #include "stree.h"
2 #include "scanner.h"
3 #include "cc.h"
4 #include "errors.h"
5 #include "stdlib.h"
6 #include "stdio.h"
7 #include "string.h"
8 #include "assert.h"
9 #include "bstr.h"
11 static const char *form_strtab[] = {
12 "NONE",
13 "BINOP",
14 "UNOP",
15 "FACTOR",
16 "TAG",
17 "TYPE",
18 "FUNCTION",
19 "VARIABLE",
20 "PARAMETERS",
21 "BLOCK",
24 static int next_id = 1;
26 const char *stree_form_str(int form)
28 return form_strtab[form - STF_NONE];
31 struct stree *stree_create(void)
33 struct stree *st;
34 st = emalloc(sizeof(struct stree));
35 memset(st, 0, sizeof (struct stree));
36 st->id = next_id++;
37 return st;
40 void stree_append_child(struct stree *st_parent, struct stree *st_child)
42 struct stree *st_child_prev = st_parent->child;
43 if (!st_parent || !st_child)
44 return;
45 st_child->parent = st_parent;
46 if (st_child_prev){
47 // insert at end of child list
48 while (st_child_prev->next){
49 st_child_prev = st_child_prev->next;
51 st_child_prev->next = st_child;
52 st_child->prev = st_child_prev;
53 st_child->next = NULL;
54 } else {
55 // first child
56 st_parent->child = st_child;
57 st_child->prev = NULL;
58 st_child->next = NULL;
62 void stree_remove_child(struct stree *st_child)
64 struct stree *st_parent = st_child->parent;
65 if (st_child->prev){
66 st_child->prev->next = st_child->next;
67 } else {
68 st_parent->child = st_child->next;
70 if (st_child->next){
71 st_child->next->prev = st_child->prev;
73 st_child->prev = NULL;
74 st_child->next = NULL;
75 st_child->parent = NULL;
78 void stree_destroy(struct stree *st)
80 if (st){
81 // destroy children
82 struct stree *st_child = st->child,
83 *st_child_next;
85 while (st_child){
86 st_child_next = st_child->next;
87 stree_destroy(st_child);
88 st_child = st_child_next;
91 free(st);
95 void stree_next_child(struct stree *st, struct stree **pchild)
97 if (*pchild == NULL){
98 *pchild = st->child;
99 } else {
100 *pchild = (*pchild)->next;
104 // form a string representing 'node', for debug output
105 static char *make_type_str(struct stree *node)
107 char *s = NULL;
108 // is the type info valid?
109 switch (node->form){
110 case STF_VARIABLE:
111 case STF_FUNCTION:
112 case STF_TYPE:
113 // XXX: erm, use arrays perhaps?
114 if (node->btype.qualifiers & TQ_RESTRICT)
115 strdcat(&s, "restrict ");
116 if (node->btype.qualifiers & TQ_VOLATILE)
117 strdcat(&s, "volatile ");
118 if (node->btype.qualifiers & TQ_CONST)
119 strdcat(&s, "const ");
120 if (node->btype.qualifiers & TQ_SIGNED)
121 strdcat(&s, "signed ");
122 if (node->btype.qualifiers & TQ_UNSIGNED)
123 strdcat(&s, "unsigned ");
124 if (node->btype.qualifiers & TQ_LONG_LONG)
125 strdcat(&s, "long long ");
126 if (node->btype.qualifiers & TQ_LONG)
127 strdcat(&s, "long ");
128 if (node->btype.qualifiers & TQ_SHORT)
129 strdcat(&s, "short ");
130 switch (node->btype.base_type){
131 case BT_VOID:
132 strdcat(&s, "void");
133 break;
134 case BT_CHAR:
135 strdcat(&s, "char");
136 break;
137 case BT_INT:
138 strdcat(&s, "int");
139 break;
140 case BT_FLOAT:
141 strdcat(&s, "float");
142 break;
143 case BT_DOUBLE:
144 strdcat(&s, "double");
145 break;
146 case BT_POINTER:
147 strdcat(&s, "pointer");
148 // TODO: pointing to what?
149 break;
150 case BT_STRUCT:
151 strdcat(&s, "struct");
152 // TODO: more informations!
153 break;
155 break;
156 default:
157 break;
159 return s;
162 static void stree_dump_internal(struct cc *cc, struct stree_stack *stack, FILE *output)
164 struct stree_stack stack_item;
166 // dump this node
167 struct stree_stack *p = stack;
168 assert(p);
169 // locate bottom of stack
170 while (p->prev){
171 p = p->prev;
173 while (p && p->next){
174 if (p->st_node->next){
175 fprintf(output, " | ");
176 } else {
177 fprintf(output, " ");
179 p = p->next;
181 if (stack->st_node->next){
182 fprintf(output, " +--");
183 } else {
184 fprintf(output, " L--");
187 char *type_str = make_type_str(stack->st_node);
188 fprintf(output, "%d:%s [%s]%s%s\n", stack->st_node->id,
189 stree_form_str(stack->st_node->form),
190 lex_get_tok_str(&cc->lex, stack->st_node->tok, NULL),
191 type_str ? " : " : "",
192 type_str ? type_str : "");
193 free(type_str);
196 // and the children
197 stack_item.prev = stack;
198 stack_item.next = NULL;
199 stack->next = &stack_item;
200 stack_item.st_node = stack->st_node->child;
201 while (stack_item.st_node){
202 stree_dump_internal(cc, &stack_item, output);
203 stack_item.st_node = stack_item.st_node->next;
205 stack->next = NULL; // pop stack
209 void stree_dump(struct cc *cc, struct stree *st_root, FILE *output)
211 struct stree_stack stack_item;
212 if (!st_root){
213 fprintf(output, "[TREE:NULL]\n");
214 return;
216 stack_item.st_node = st_root;
217 stack_item.prev = NULL;
218 stack_item.next = NULL;
219 stree_dump_internal(cc, &stack_item, output);
222 struct stree *stree_right(struct stree *st)
224 struct stree *p = st->child;
225 while (p && p->next){
226 p = p->next;
228 return p;
231 int stree_child_count(struct stree *st)
233 int n = 0;
234 struct stree *child_st;
235 if (!st){
236 return 0;
238 child_st = st->child;
239 while (child_st){
240 n++;
241 child_st = child_st->next;
243 return n;
246 struct stree *stree_find_local(struct stree *scope, enum stree_form form, tok_t tok)
248 if (!scope)
249 return NULL;
250 struct stree *p = scope->child;
251 while (p && !(p->form == form && p->tok == tok)){
252 p = p->next;
254 return p;
257 struct stree *stree_get_child_by_form(struct stree *st, enum stree_form form)
259 struct stree *child_st;
260 child_st = st->child;
261 while (child_st && child_st->form != form){
262 child_st = child_st->next;
264 return child_st;