added detach function
This commit is contained in:
parent
a3f5bc1fe6
commit
4322797eae
|
@ -3,11 +3,12 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
struct AST_Node_t *AST_new_node(enum AST_SyntaxElement_t kind, const char* value) {
|
AST_NODE_PTR AST_new_node(enum AST_SyntaxElement_t kind, const char* value) {
|
||||||
DEBUG("creating new AST node: %d \"%s\"", kind, value);
|
DEBUG("creating new AST node: %d \"%s\"", kind, value);
|
||||||
|
|
||||||
struct AST_Node_t *node = malloc(sizeof(struct AST_Node_t));
|
AST_NODE_PTR node = malloc(sizeof(struct AST_Node_t));
|
||||||
|
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
PANIC("failed to allocate AST node");
|
PANIC("failed to allocate AST node");
|
||||||
|
@ -17,6 +18,7 @@ struct AST_Node_t *AST_new_node(enum AST_SyntaxElement_t kind, const char* value
|
||||||
node->parent = NULL;
|
node->parent = NULL;
|
||||||
node->children = NULL;
|
node->children = NULL;
|
||||||
node->child_count = 0;
|
node->child_count = 0;
|
||||||
|
node->child_cap = 0;
|
||||||
node->kind = kind;
|
node->kind = kind;
|
||||||
node->value = value;
|
node->value = value;
|
||||||
|
|
||||||
|
@ -25,7 +27,7 @@ struct AST_Node_t *AST_new_node(enum AST_SyntaxElement_t kind, const char* value
|
||||||
|
|
||||||
static const char* lookup_table[AST_ELEMENT_COUNT] = { "__UNINIT__" };
|
static const char* lookup_table[AST_ELEMENT_COUNT] = { "__UNINIT__" };
|
||||||
|
|
||||||
void AST_init() {
|
void AST_init(void) {
|
||||||
DEBUG("initializing global syntax tree...");
|
DEBUG("initializing global syntax tree...");
|
||||||
|
|
||||||
INFO("filling lookup table...");
|
INFO("filling lookup table...");
|
||||||
|
@ -92,17 +94,24 @@ const char* AST_node_to_string(struct AST_Node_t* node) {
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) {
|
#define PRE_ALLOCATION_CNT 10
|
||||||
|
|
||||||
|
void AST_push_node(AST_NODE_PTR owner, AST_NODE_PTR child) {
|
||||||
DEBUG("Adding new node %p to %p", child, owner);
|
DEBUG("Adding new node %p to %p", child, owner);
|
||||||
|
|
||||||
|
assert(PRE_ALLOCATION_CNT >= 1);
|
||||||
|
|
||||||
// if there are no children for now
|
// if there are no children for now
|
||||||
if (owner->child_count == 0) {
|
if (owner->children == NULL) {
|
||||||
|
assert(owner->child_count == 0);
|
||||||
DEBUG("Allocating new children array");
|
DEBUG("Allocating new children array");
|
||||||
owner->children = malloc(sizeof(struct AST_Node_t *));
|
owner->children = malloc(sizeof(struct AST_Node_t *));
|
||||||
|
owner->child_cap = 1;
|
||||||
|
|
||||||
} else {
|
} else if (owner->child_count >= owner->child_cap) {
|
||||||
DEBUG("Rellocating old children array");
|
DEBUG("Reallocating old children array");
|
||||||
const size_t size = sizeof(struct AST_Node_t *) * (owner->child_count + 1);
|
owner->child_cap += PRE_ALLOCATION_CNT;
|
||||||
|
const size_t size = sizeof(struct AST_Node_t *) * owner->child_cap;
|
||||||
owner->children = realloc(owner->children, size);
|
owner->children = realloc(owner->children, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,8 +122,8 @@ void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) {
|
||||||
owner->children[owner->child_count++] = child;
|
owner->children[owner->child_count++] = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx) {
|
AST_NODE_PTR AST_get_node(AST_NODE_PTR owner, size_t idx) {
|
||||||
DEBUG("retrvieng node %d from %p", idx, owner);
|
DEBUG("retrieving node %d from %p", idx, owner);
|
||||||
|
|
||||||
if (owner == NULL) {
|
if (owner == NULL) {
|
||||||
PANIC("AST owner node is NULL");
|
PANIC("AST owner node is NULL");
|
||||||
|
@ -124,7 +133,7 @@ struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx) {
|
||||||
PANIC("AST owner node has no children");
|
PANIC("AST owner node has no children");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AST_Node_t *child = owner->children[idx];
|
AST_NODE_PTR child = owner->children[idx];
|
||||||
|
|
||||||
if (child == NULL) {
|
if (child == NULL) {
|
||||||
PANIC("child node is NULL");
|
PANIC("child node is NULL");
|
||||||
|
@ -133,20 +142,48 @@ struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx) {
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AST_delete_node(struct AST_Node_t *node) {
|
void AST_delete_node(AST_NODE_PTR node) {
|
||||||
DEBUG("Deleting AST node: %p", node);
|
DEBUG("Deleting AST node: %p", node);
|
||||||
|
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
PANIC("Node to free is NULL");
|
PANIC("Node to free is NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node->parent != NULL) {
|
||||||
|
AST_detach_node(node->parent, node);
|
||||||
|
}
|
||||||
|
|
||||||
if (node->children == NULL) {
|
if (node->children == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < node->child_count; i++) {
|
for (size_t i = 0; i < node->child_count; i++) {
|
||||||
|
if (node->children[i] != node) {
|
||||||
AST_delete_node(node->children[i]);
|
AST_delete_node(node->children[i]);
|
||||||
|
} else {
|
||||||
|
WARN("Circular dependency in AST: parent -> child -> parent -> child -> ...");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(node->children);
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
AST_NODE_PTR AST_detach_node(AST_NODE_PTR parent, AST_NODE_PTR child) {
|
||||||
|
assert(parent != NULL);
|
||||||
|
assert(child != NULL);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < parent->child_count; i++) {
|
||||||
|
if (child == parent->children[i]) {
|
||||||
|
memcpy(&parent->children[i], &parent->children[i + 1], parent->child_count - i - 1);
|
||||||
|
parent->child_count--;
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WARN("Node not a child of parent");
|
||||||
|
|
||||||
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __AST_visit_nodes_recurse2(struct AST_Node_t *root,
|
static void __AST_visit_nodes_recurse2(struct AST_Node_t *root,
|
||||||
|
|
|
@ -69,6 +69,7 @@ struct AST_Node_t {
|
||||||
// number of child nodes ownd by this node
|
// number of child nodes ownd by this node
|
||||||
// length of children array
|
// length of children array
|
||||||
size_t child_count;
|
size_t child_count;
|
||||||
|
size_t child_cap;
|
||||||
// variable amount of child nodes
|
// variable amount of child nodes
|
||||||
struct AST_Node_t **children;
|
struct AST_Node_t **children;
|
||||||
};
|
};
|
||||||
|
@ -90,6 +91,8 @@ void AST_delete_node(struct AST_Node_t *);
|
||||||
// add a new child node
|
// add a new child node
|
||||||
void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child);
|
void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child);
|
||||||
|
|
||||||
|
AST_NODE_PTR AST_detach_node(AST_NODE_PTR parent, AST_NODE_PTR child);
|
||||||
|
|
||||||
// get a specific child node
|
// get a specific child node
|
||||||
struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx);
|
struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue