From: Michael D. Lowis Date: Thu, 8 Jan 2015 19:13:42 +0000 (-0500) Subject: Added tree walking functionality to the tree module X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=e38e41cd352406f4cf7479ee814ca477654433cf;p=proto%2Fsclpl.git Added tree walking functionality to the tree module --- diff --git a/source/libparse/tree.c b/source/libparse/tree.c index 63e1f9a..77053fe 100644 --- a/source/libparse/tree.c +++ b/source/libparse/tree.c @@ -96,3 +96,33 @@ bool tree_is_formtype(tree_t* p_tree, const char* val) { return ret; } + +tree_t* tree_walk(tree_t* tree, tree_walker_t* walker) +{ + size_t idx; + tree_t* new_node; + new_node = walker->fn(walker->env, tree, PRE_NODE); + if (tree->tag == TREE) { + walker->fn(walker->env, tree, PRE_CHILDREN); + for (idx = 0; idx < vec_size(tree->ptr.vec); idx++) { + tree_t* child = vec_at(tree->ptr.vec, idx); + walker->fn(walker->env, tree, PRE_CHILD); + tree_t* new_child = tree_walk( child, walker ); + walker->fn(walker->env, tree, POST_CHILD); + if ((NULL != new_node) && (new_node->tag == TREE) && (NULL != new_child)) { + vec_push_back(new_node->ptr.vec, new_child); + } + } + walker->fn(walker->env, tree, POST_CHILDREN); + } + return new_node; +} + +tree_walker_t* tree_walker(void* env, tree_walk_fn_t fn) +{ + tree_walker_t* p_walker = (tree_walker_t*)mem_allocate(sizeof(tree_walker_t),NULL); + p_walker->env = env; + p_walker->fn = fn; + return p_walker; +} + diff --git a/source/libparse/tree.h b/source/libparse/tree.h index e3374b0..aa61f05 100644 --- a/source/libparse/tree.h +++ b/source/libparse/tree.h @@ -20,11 +20,29 @@ typedef struct { } ptr; } tree_t; +typedef enum { + PRE_NODE, + POST_NODE, + PRE_CHILDREN, + POST_CHILDREN, + PRE_CHILD, + POST_CHILD, +} tree_walk_pos_t; + +typedef tree_t* (*tree_walk_fn_t)(void* env, tree_t* node, tree_walk_pos_t pos); + +typedef struct { + void* env; + tree_walk_fn_t fn; +} tree_walker_t; + tree_t* tree_convert(tree_t* p_tree); tree_t* tree_new(tree_tag_t tag, void* p_obj); tree_t* tree_get_child(tree_t* p_tree, size_t idx); void* tree_get_val(tree_t* p_tree); void* tree_get_child_val(tree_t* p_tree, size_t idx); bool tree_is_formtype(tree_t* p_tree, const char* val); +tree_t* tree_walk(tree_t* tree, tree_walker_t* walker); +tree_walker_t* tree_walker(void* env, tree_walk_fn_t fn); #endif /* TREE_H */