baum

view baum.c @ 46:22305a6e128d

added deep copy and fixed so node times
author meillo@marmaro.de
date Sun, 02 Mar 2008 10:29:55 +0100
parents 0b82169d4129
children c31b5bb6d493
line source
1 /*
2 * baum - an esoteric programming language
3 *
4 * (c) markus schnalke <meillo@marmaro.de>
5 * and julian forster
6 *
7 */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
14 #include "baum.h"
15 #include "actions.h"
17 #define VERSION "0.3"
20 void printNode(struct Node* node, int level);
21 void printTree(struct Node* root, int level);
22 struct Node* lastNode(struct Node* node);
23 void delete(struct Node* node);
26 struct Stackitem {
27 struct Node* node;
28 struct Stackitem* next;
29 };
33 struct Node* root = 0;
34 struct Stackitem* stack = NULL;
37 void logit(char* text) {
38 if (option_verbose) {
39 fprintf(stderr, "[%s]\n", text);
40 }
41 }
44 /* new */
45 struct Node* newNode(char* name, unsigned char value) {
46 struct Node* node;
47 node = (struct Node*) malloc(sizeof(struct Node));
48 strcpy(node->name, name);
49 node->value = value;
50 node->right = 0;
51 node->down = 0;
52 return node;
53 }
57 struct Node* lastNode(struct Node* node) {
58 while (node->right != NULL) {
59 node = node->right;
60 }
61 return node;
62 }
64 struct Node* insertLast(struct Node* node, struct Node* insert) {
65 node = lastNode(node);
66 node->right = insert;
67 return insert;
68 }
70 struct Node* copyTree(struct Node* node) {
71 if (node == NULL) {
72 return NULL;
73 }
74 struct Node* tmp;
75 tmp = newNode(node->name, node->value);
76 tmp->down = copyTree(node->down);
77 tmp->right = copyTree(node->right);
78 return tmp;
79 }
82 /* delete */
83 void delete(struct Node* node) {
84 if (node == NULL) {
85 return;
86 }
87 delete(node->down);
88 delete(node->right);
89 free(node); node=0;
90 }
93 /* print */
94 void printNode(struct Node* node, int level) {
95 if (node != NULL) {
96 while (level-- > 0) {
97 fprintf(stderr, "\t");
98 }
99 fprintf(stderr, "%s (%d|%c)\n", node->name, node->value, node->value);
100 }
101 }
103 void printTree(struct Node* root, int level) {
104 if (root == NULL) {
105 return;
106 }
107 printNode(root, level);
108 printTree(root->down, level+1);
109 printTree(root->right, level);
110 }
116 /* stack for read_input */
117 void push(struct Node* node) {
118 struct Stackitem* tmp;
119 struct Stackitem* new;
120 new = (struct Stackitem*) malloc(sizeof(struct Stackitem));
121 new->node = node;
122 tmp = stack;
123 stack = new;
124 stack->next = tmp;
125 }
126 struct Node* pull() {
127 if (stack == NULL) {
128 return NULL;
129 }
130 struct Stackitem* tmp;
131 struct Node* node;
132 tmp = stack;
133 stack = stack->next;
134 node = tmp->node;
135 free(tmp); tmp=0;
136 return node;
137 }
141 /* read input */
142 void read_input(char* filename) {
143 int c;
144 int indent;
145 char name[256];
146 int value;
147 int last_indent;
148 struct Node* last_node;
149 struct Node* node;
150 FILE* file;
152 indent = 0;
153 strcpy(name, "");
154 value = 0;
155 last_indent = -1;
156 last_node = NULL;
157 file = fopen(filename, "r");
159 while ((c = getc(file)) != EOF) {
160 if (c == '#') { /* comment */
161 while ((c = getc(file)) != '\n') {
162 }
163 }
165 if (c == ' ' || c == '\t') { /* indent if at start of line */
166 if (strlen(name) == 0) {
167 indent++;
168 }
169 }
171 if (c == '\n') { /* end of line: create node */
172 if (strlen(name) > 0) {
173 /* create node */
174 node = newNode((char*) name, value);
175 if (indent > last_indent) { /* down */
176 /* if it goes more than one level down -> error */
177 if (indent > last_indent + 1) {
178 fprintf(stderr, "error: Indention over more than one level. Only indent by one!\n");
179 exit(5);
180 }
181 if (last_node == NULL) {
182 root = node;
183 last_node = root;
184 } else {
185 last_node->down = node;
186 }
187 push(last_node);
188 } else if (indent == last_indent) { /* right */
189 last_node->right = node;
190 } else if (indent < last_indent) { /* up */
191 /* handle if it goes more than one level up */
192 while (indent < last_indent) {
193 last_node = pull();
194 last_indent--;
195 }
196 last_node->right = node;
197 }
198 last_indent = indent;
199 last_node = node;
200 }
201 indent = 0;
202 strcpy(name, "");
203 value = 0;
204 }
206 if (c >= 'a' && c <= 'z') { /* name */
207 int i = 1;
208 name[0] = (char) c;
209 while ((c = getc(file)) != '(') {
210 name[i] = (char) c;
211 i++;
212 if (i > 255) {
213 fprintf(stderr, "error: node name too long, or no value given\n");
214 exit(6);
215 }
216 }
217 name[i] = '\0';
218 }
220 if (c == '(') { /* value */
221 fscanf(file, "%d)", &value);
222 }
224 }
226 /* clear stack */
227 while (stack != NULL) {
228 pull();
229 }
231 fclose(file);
232 }
236 /* main */
237 int main(int argc, char* argv[]) {
238 unsigned char shell_return = 0;
240 option_verbose = 0;
242 while (--argc > 0 && (*++argv)[0] == '-') {
243 if (strcmp(argv[0], "--version") == 0) {
244 printf("\
245 baum %s\n\
246 an esoteric programming language\n\
247 by markus schnalke and julian forster\n\
248 http://prog.marmaro.de/baum\n\
249 ", VERSION);
250 exit(0);
251 } else if (strcmp(argv[0], "--help") == 0) {
252 printf("\
253 baum --version print version information and exit\n\
254 baum --help print this output\n\
255 baum [-v] <file> (verbosly) run file\n\
256 ");
257 exit(0);
258 } else if (strcmp(argv[0], "-v") == 0) {
259 option_verbose = 1;
260 /*
261 } else if (strcmp(argv[0], "-W") == 0) {
262 / * TODO: catch if no value given * /
263 iDWarn = atoi((++argv)[0]);
264 argc--;
265 */
266 } else {
267 fprintf(stderr, "unknown option: %s\n", argv[0]);
268 exit(126);
269 }
270 }
272 if (argc != 1) {
273 fprintf(stderr, "%d source files given, please specify one.\n", argc);
274 exit(3);
275 }
277 read_input(argv[0]);
279 if (option_verbose) {
280 fprintf(stderr, "\n\ntree read from input\n(should be the same without comments and empty lines)\n\n");
281 printTree(root, 0);
282 }
284 shell_return = action(root);
285 fflush(stdout);
287 if (option_verbose) {
288 fprintf(stderr, "\n\ntree after execution of the program\n\n");
289 printTree(root, 0);
290 }
292 delete(root);
293 exit(shell_return);
294 }