Add a recursive tree freeing function.

This commit is contained in:
Danila Fedorin 2018-02-17 19:20:10 -08:00
parent a52735f0b3
commit 811704be25
3 changed files with 35 additions and 11 deletions

View File

@ -80,5 +80,12 @@ typedef struct libab_tree_s libab_tree;
* @param tree the tree to free. * @param tree the tree to free.
*/ */
void libab_tree_free(libab_tree* tree); void libab_tree_free(libab_tree* tree);
/**
* Frees the given tree recursively,
* deleting the children first and the moving on
* to the parents.
* @param tree the tree to free.
*/
void libab_tree_free_recursive(libab_tree* tree);
#endif #endif

View File

@ -105,7 +105,7 @@ libab_result _parser_construct_op_node(struct parser_state* state, libab_lexer_m
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
result = libab_convert_ds_result(vec_init(&(*into)->children)); result = libab_convert_ds_result(vec_init(&(*into)->children));
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
(*into)->variant = OP; (*into)->variant = (match->type == TOKEN_OP_INFIX) ? OP : UNARY_OP;
} else { } else {
free((*into)->string_value); free((*into)->string_value);
free(*into); free(*into);
@ -188,7 +188,7 @@ libab_result _parser_append_atom(struct parser_state* state, ll* append_to) {
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
result = libab_convert_ds_result(ll_append(append_to, tree)); result = libab_convert_ds_result(ll_append(append_to, tree));
if(result != LIBAB_SUCCESS) { if(result != LIBAB_SUCCESS) {
libab_tree_free(tree); libab_tree_free_recursive(tree);
free(tree); free(tree);
} }
} }
@ -219,8 +219,8 @@ libab_result _parser_expression_tree(struct parser_state* state, ll* source, lib
} }
if(result != LIBAB_SUCCESS) { if(result != LIBAB_SUCCESS) {
if(left) libab_tree_free(left); if(left) libab_tree_free_recursive(left);
if(right) libab_tree_free(right); if(right) libab_tree_free_recursive(right);
libab_tree_free(top); libab_tree_free(top);
free(left); free(left);
free(right); free(right);
@ -241,7 +241,7 @@ libab_result _parser_expression_tree(struct parser_state* state, ll* source, lib
} }
if(result != LIBAB_SUCCESS) { if(result != LIBAB_SUCCESS) {
if(child) libab_tree_free(child); if(child) libab_tree_free_recursive(child);
libab_tree_free(top); libab_tree_free(top);
free(child); free(child);
free(top); free(top);
@ -339,7 +339,7 @@ libab_result _parse_expression(struct parser_state* state, libab_tree** store_in
} }
if(result == LIBAB_SUCCESS && out_stack.tail) { if(result == LIBAB_SUCCESS && out_stack.tail) {
libab_tree_free(*store_into); libab_tree_free_recursive(*store_into);
free(*store_into); free(*store_into);
*store_into = NULL; *store_into = NULL;
result = LIBAB_UNEXPECTED; result = LIBAB_UNEXPECTED;

View File

@ -1,15 +1,19 @@
#include "tree.h" #include "tree.h"
#include <stdlib.h> #include <stdlib.h>
void libab_tree_free(libab_tree* tree) { int _tree_has_vector(libab_tree* tree) {
int free_string = 0; return tree->variant == BASE || tree->variant == OP ||
int free_vector = 0;
if(tree->variant == BASE || tree->variant == OP ||
tree->variant == UNARY_OP || tree->variant == BLOCK || tree->variant == UNARY_OP || tree->variant == BLOCK ||
tree->variant == FUN || tree->variant == IF || tree->variant == FUN || tree->variant == IF ||
tree->variant == WHILE || tree->variant == DOWHILE || tree->variant == WHILE || tree->variant == DOWHILE ||
tree->variant == FOR || tree->variant == CALL || tree->variant == FOR || tree->variant == CALL ||
tree->variant == RETURN) { tree->variant == RETURN;
}
void libab_tree_free(libab_tree* tree) {
int free_string = 0;
int free_vector = 0;
if(_tree_has_vector(tree)) {
free_vector = 1; free_vector = 1;
} }
if(tree->variant == ID || tree->variant == STR || tree->variant == NUM || if(tree->variant == ID || tree->variant == STR || tree->variant == NUM ||
@ -20,3 +24,16 @@ void libab_tree_free(libab_tree* tree) {
if(free_string) free(tree->string_value); if(free_string) free(tree->string_value);
if(free_vector) vec_free(&tree->children); if(free_vector) vec_free(&tree->children);
} }
int _tree_foreach_free(void* data, va_list args) {
libab_tree_free_recursive(data);
return 0;
}
void libab_tree_free_recursive(libab_tree* tree) {
if(_tree_has_vector(tree)) {
vec_foreach(&tree->children, NULL, compare_always, _tree_foreach_free);
}
libab_tree_free(tree);
free(tree);
}