From 9911f9a73c7dc46069199e52f2bc54082d10366c Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Wed, 3 Jan 2018 23:10:59 +0100 Subject: Initial --- node.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 node.c (limited to 'node.c') diff --git a/node.c b/node.c new file mode 100644 index 0000000..b20c38e --- /dev/null +++ b/node.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include "node.h" + + +struct node* node_make_0(enum node_type type) { + struct node *node = malloc(sizeof(struct node)); + node->type = type; + node->child1 = node->child2 = node->child3 = NULL; + node->rtype = NULL; + node->name = NULL; + node->value = 0; + return node; +} + +struct node* node_make_1(enum node_type type, struct node *c1) { + struct node *node = node_make_0(type); + node->child1 = c1; + return node; +} + +struct node* node_make_2(enum node_type type, struct node *c1, struct node *c2) { + struct node *node = node_make_1(type, c1); + node->child2 = c2; + return node; +} + +struct node* node_make_3(enum node_type type, struct node *c1, struct node *c2, struct node *c3) { + struct node *node = node_make_2(type, c1, c2); + node->child3 = c3; + return node; +} + +struct node* node_make_list_(struct node *first, ...) { + va_list ap; + va_start(ap, first); + struct node *cur = node_make_0(N_LIST_END); + struct node *root = node_make_2(N_LIST, first, cur); + struct node *next; + while ((next = va_arg(ap, struct node*))) { + cur->type = N_LIST; + cur->child1 = next; + cur->child2 = node_make_0(N_LIST_END); + cur = cur->child2; + } + return root; +} + +int node_list_length(struct node *node) { + if (node->type == N_LIST_END) return 0; + assert(node->type == N_LIST); + return 1 + node_list_length(node->child2); +} + +void node_delete_recursive(struct node *node) { + if (node->child1) node_delete_recursive(node->child1); + if (node->child2) node_delete_recursive(node->child2); + if (node->child3) node_delete_recursive(node->child3); + if (node->name) free(node->name); + free(node); +} + +static void write_spaces(int num, FILE *f) { + for (int i = 0; i < num; i++) fputc(' ', f); +} + +static const char* node_type_string(enum node_type type) { + switch (type) { + case N_LIST: return "N_LIST"; break; + case N_LIST_END: return "N_LIST_END"; break; + case N_BLOCK: return "N_BLOCK"; break; + case N_VAR_DECL_INIT: return "N_VAR_DECL_INIT"; break; + case N_VAR_DECL: return "N_VAR_DECL"; break; + case N_FUNC_DECL: return "N_FUNC_DECL"; break; + case N_NUM: return "N_NUM"; break; + case N_VAR: return "N_VAR"; break; + case N_IF: return "N_IF"; break; + case N_WHILE: return "N_WHILE"; break; + case N_RETURN: return "N_RETURN"; break; + case N_BINOP: return "N_BINOP"; break; + case N_UNOP: return "N_UNOP"; break; + case N_CALL: return "N_CALL"; break; + default: assert(false); + } +} + +static const char* oper_string(enum operator oper) { + switch (oper) { + case OP_ADD: return "OP_ADD"; + case OP_SUB: return "OP_SUB"; + case OP_MUL: return "OP_MUL"; + case OP_DIV: return "OP_DIV"; + case OP_MOD: return "OP_MOD"; + case OP_EQ: return "OP_EQ"; + case OP_NEQ: return "OP_NEQ"; + case OP_LT: return "OP_LT"; + case OP_GT: return "OP_GT"; + case OP_LEQ: return "OP_LEQ"; + case OP_GEQ: return "OP_GEQ"; + case OP_AND: return "OP_AND"; + case OP_OR: return "OP_OR"; + case OP_ASSIGN: return "OP_ASSIGN"; + case OP_NEG: return "OP_NEG"; + case OP_NOT: return "OP_NOT"; + default: assert(false); + } +} + +void node_print(const struct node *node, FILE *f, int indent) { + const char *t = node_type_string(node->type); + fprintf(f, "(%s", t); + if (node->rtype) { + fprintf(f, "[rtype="); + type_print(node->rtype, f); + fprintf(f, "]"); + } + if (node->name) fprintf(f, "[name=%s]", node->name); + if (node->type == N_NUM) fprintf(f, "[value=%d]", node->value); + if (node->type == N_BINOP || node->type == N_UNOP) { + fprintf(f, "[oper=%s]", oper_string(node->oper)); + } + if (node->child1) { + fprintf(f, "\n"); + write_spaces(2 * (indent + 1), f); + node_print(node->child1, f, indent + 1); + } + if (node->child2) { + fprintf(f, "\n"); + write_spaces(2 * (indent + 1), f); + node_print(node->child2, f, indent + 1); + } + if (node->child3) { + fprintf(f, "\n"); + write_spaces(2 * (indent + 1), f); + node_print(node->child3, f, indent + 1); + } + fprintf(f, ")"); +} -- cgit v1.2.3-54-g00ecf