From 80888fdb8d67e3e974fc9368aae0e581fdae0e71 Mon Sep 17 00:00:00 2001 From: servostar Date: Fri, 10 May 2024 13:49:04 +0200 Subject: [PATCH] added function for removing and detaching a node --- src/ast/ast.c | 35 +++++++++++++++++++++++++++++++++++ src/ast/ast.h | 20 ++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/ast/ast.c b/src/ast/ast.c index 7bae47b..ca2442c 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -134,6 +134,33 @@ struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx) { return child; } +struct AST_Node_t* AST_remove_child(struct AST_Node_t* owner, const size_t idx) { + + struct AST_Node_t* child = owner->children[idx]; + + child->parent = NULL; + + owner->child_count--; + + // shift back every following element by one + for (size_t i = idx; i < owner->child_count; i++) { + owner->children[i] = owner->children[i + 1]; + } + + return child; +} + +struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner, const struct AST_Node_t* child) { + for (size_t i = 0; i < owner->child_count; i++) { + if (owner->children[i] == child) { + return AST_remove_child(owner, i); + } + } + + PANIC("Child to detach not a child of parent"); + return NULL; +} + void AST_delete_node(struct AST_Node_t *node) { DEBUG("Deleting AST node: %p", node); @@ -145,9 +172,17 @@ void AST_delete_node(struct AST_Node_t *node) { return; } + if (node->parent != NULL) { + AST_detach_child(node->parent, node); + } + for (size_t i = 0; i < node->child_count; i++) { + // prevent detach of children node + node->children[i]->parent = NULL; AST_delete_node(node->children[i]); } + + free(node); } static void __AST_visit_nodes_recurse2(struct AST_Node_t *root, diff --git a/src/ast/ast.h b/src/ast/ast.h index 767388b..40c9af2 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -130,6 +130,26 @@ void AST_delete_node(struct AST_Node_t * node); */ void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child); +/** + * @brief Remove the specified child from the owner. + * @attention The parent of the removed node is set to NULL. + * The returned pointer is still valid. It must be freed at some pointer later. + * @param owner Node to remove the child from + * @param idx the index of the child to remove + * @return a pointer to the child which was removed + */ +struct AST_Node_t* AST_remove_child(struct AST_Node_t* owner, size_t idx); + +/** + * @brief Detach a child from its parent. This involves removing the child from its parent + * and marking the parent of the child as NULL. + * @attention The returned pointer is still valid. It must be freed at some pointer later. + * @param owner the owner to remove the child from + * @param child the child to detach + * @return a pointer to child detached + */ +struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner, const struct AST_Node_t* child); + /** * @brief Return a pointer to the n-th child of a node * @attention Pointer to childen nodes will never change.