block: don't put spaces around :
[ironout.git] / parse.c
blobbb06cd234f995304f377d3e4ca01453cab3828ca
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "ast.h"
5 #include "hash.h"
6 #include "parse.h"
7 #include "utils.h"
10 static struct node *nodestack[1024];
11 static int nodecount = 0;
12 static int parse_error = 0;
14 static int list_nodetype(enum nodetype nodetype)
16 switch (nodetype) {
17 case AST_ARGLIST:
18 case AST_BLOCKLIST:
19 case AST_BODY:
20 case AST_DECLLIST:
21 case AST_DECLSPEC:
22 case AST_DESIGLIST:
23 case AST_ENUMLIST:
24 case AST_EXPRLIST:
25 case AST_FILE:
26 case AST_INITIALIZERLIST:
27 case AST_INITLIST:
28 case AST_PARAMLIST:
29 case AST_STRUCTDECLLIST:
30 case AST_STRUCTLIST:
31 case AST_STRUCTQUALLIST:
32 case AST_TYPEQUALLIST:
33 return 1;
34 default:
35 return 0;
39 static int list_size(struct node *node)
41 int result = 0;
42 struct node *cur = node;
43 int preorder;
44 if (!list_nodetype(node->type) || !node->count)
45 return 0;
46 preorder = cur->children[0]->type == node->type;
47 while (cur->type == node->type) {
48 result++;
49 if (cur->count != 2)
50 return result;
51 if (preorder)
52 cur = cur->children[0];
53 else
54 cur = cur->children[1];
56 return result;
59 static void node_free_base(struct node *node, int children)
61 if (children && node->children) {
62 int i;
63 for (i = 0; i < node->count; i++)
64 node_free(node->children[i]);
65 free(node->children);
67 if (node->data)
68 free(node->data);
69 free(node);
72 static void linear_lists(struct node *node)
74 int n = list_size(node);
75 int i;
76 if (n) {
77 struct node *cur = node;
78 struct node **newchildren = xmalloc(n * sizeof(struct node *));
79 int preorder = cur->children[0]->type == node->type;
80 for (i = 0; i < n; i++) {
81 struct node *old = cur;
82 if (preorder) {
83 if (cur->count > 1)
84 newchildren[n - i - 1] = cur->children[1];
85 else
86 newchildren[n - i - 1] = cur->children[0];
87 cur = cur->children[0];
88 } else {
89 newchildren[i] = cur->children[0];
90 cur = cur->children[cur->count - 1];
92 if (old != node && i < n - 1)
93 node_free_base(old, 0);
95 for (i = 0; i < n; i++)
96 newchildren[i]->parent = node;
97 free(node->children);
98 node->children = newchildren;
99 node->count = n;
101 for (i = 0; i < node->count; i++)
102 linear_lists(node->children[i]);
105 static void error_happened()
107 int i;
108 parse_error = 1;
109 for (i = 0; i < nodecount; i++)
110 node_free(nodestack[i]);
111 nodecount = 0;
114 struct node *parse(char *filename)
116 FILE *file = fopen(filename, "r");
117 if (!file)
118 return NULL;
119 parse_error = 0;
120 yyrestart(file);
121 yyparse();
122 fclose(file);
123 reset_tokenizer(filename);
124 if (parse_error || nodecount != 1) {
125 fprintf(stderr, "ERROR: %d nodes on the stack\n", nodecount);
126 error_happened();
127 return NULL;
129 linear_lists(nodestack[0]);
130 return nodestack[--nodecount];
133 struct node *push_node(enum nodetype type, long start, long end, int nchild)
135 struct node *node;
136 if (parse_error || nchild > nodecount) {
137 error_happened();
138 return NULL;
140 node = xmalloc(sizeof(struct node));
141 memset(node, 0, sizeof(struct node));
142 node->type = type;
143 node->start = start;
144 node->end = end;
145 if (nchild) {
146 int i;
147 node->count = nchild;
148 node->children = xmalloc(nchild * sizeof(struct node *));
149 for (i = nchild - 1; i >= 0; i--) {
150 struct node *child = nodestack[--nodecount];
151 node->children[i] = child;
152 child->parent = node;
155 nodestack[nodecount++] = node;
156 return node;
159 struct node *push_node_name(enum nodetype type, long start, long end, char *name)
161 struct node *node = push_node(type, start, end, 0);
162 if (parse_error || !node)
163 return NULL;
164 node->data = xmalloc(strlen(name) + 1);
165 strcpy(node->data, name);
166 return node;
169 struct node *push_decl(enum nodetype type, long start, long end,
170 int nchild, enum decltype decltype)
172 struct node *node = push_node(type, start, end, nchild);
173 if (parse_error || !node)
174 return NULL;
175 node->data = xmalloc(sizeof(decltype));
176 *(enum decltype *) node->data = decltype;
177 return node;
180 void node_free(struct node *node)
182 node_free_base(node, 1);