]> git.mdlowis.com Git - proto/sclpl.git/commitdiff
Added tree walking functionality to the tree module
authorMichael D. Lowis <mike@mdlowis.com>
Thu, 8 Jan 2015 19:13:42 +0000 (14:13 -0500)
committerMichael D. Lowis <mike@mdlowis.com>
Thu, 8 Jan 2015 19:13:42 +0000 (14:13 -0500)
source/libparse/tree.c
source/libparse/tree.h

index 63e1f9a17f3b6620480f9f0f592345eff58cbe62..77053fe9dbb589614f8006722313afa064be0b3a 100644 (file)
@@ -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;
+}
+
index e3374b0b1cfc618651fe3a7b79c86f66e05c1724..aa61f05dd515fe4adbfb517d287552d953cfdb1d 100644 (file)
@@ -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 */