#include "node.h" #include "vec.h" GUX_ENUM_C(NodeType, NODE_TYPE); void node_init(struct node* self, enum NodeType type, char const* value, int line) { assert(self); self->type = type; self->value = strdup(value); vec_init(&self->children, 1); self->line = line; self->parent = NULL; } void node_free(struct node* self) { assert(self); free(self->value); for (size_t i=0; ichildren.size; i++) { node_free(self->children.data[i]); } vec_free_elements(&self->children); vec_free(&self->children); } struct node* node_add_new_child(struct node* self, enum NodeType type, char const* value) { assert(self); struct node* child = malloc(sizeof(struct node)); node_init(child, type, value, self->line); vec_push(&self->children, child); return child; } struct node* node_add_child(struct node* self, struct node* child) { assert(self); vec_push(&self->children, child); child->parent = self; return child; } size_t node_str(struct node* self, char* buffer, size_t size) { assert(self); assert(buffer); size_t sz = 0; sz += snprintf(buffer + sz, size - sz, "%s", NodeTypeStr[self->type] + strlen("NODE_")); if (strcmp(self->value, "") != 0) { sz += snprintf(buffer + sz, size - sz, "[%s]", self->value); } if (self->children.size > 0) { sz += snprintf(buffer + sz, size - sz, "("); for (size_t i=0; ichildren.size; i++) { if (i > 0) { sz += snprintf(buffer + sz, size - sz, ","); } sz += node_str(self->children.data[i], buffer + sz, size - sz); } sz += snprintf(buffer + sz, size - sz, ")"); } return sz; } int node_depth(struct node* self) { assert(self); struct node* itr = self; int depth = 0; while (itr != NULL) { if (itr->type == NODE_BLOCK) { depth++; } itr = itr->parent; } return depth; } struct node* node_try_find_parent(struct node* self, enum NodeType type) { assert(self); struct node* p = self; while (p != NULL && p->type != type) { p = p->parent; } return p; } size_t node_parent_index(struct node* self) { assert(self); struct node* parent = self->parent; if (parent == NULL) { return 0; } for (size_t i=0; ichildren.size; i++) { if (parent->children.data[i] == self) { return i; } } return 0; } size_t node_block_index(struct node* self) { assert(self); struct node* block = node_try_find_parent(self, NODE_BLOCK); if (block == NULL) { return 0; } if (self->parent == block) { return node_parent_index(self); } return node_block_index(self->parent); }