Merge branch 'tree_trav'
This commit is contained in:
@@ -5,7 +5,8 @@ int main(int argc, char *argv[]) {
|
|||||||
mpc_parser_t *Input = mpc_new("input");
|
mpc_parser_t *Input = mpc_new("input");
|
||||||
mpc_parser_t *Node = mpc_new("node");
|
mpc_parser_t *Node = mpc_new("node");
|
||||||
mpc_parser_t *Leaf = mpc_new("leaf");
|
mpc_parser_t *Leaf = mpc_new("leaf");
|
||||||
mpc_ast_t *ast, *tree, *child, *child_sub;
|
mpc_ast_t *ast, *tree, *child, *child_sub, *ast_next;
|
||||||
|
mpc_ast_trav_t *trav;
|
||||||
mpc_result_t r;
|
mpc_result_t r;
|
||||||
int index, lb;
|
int index, lb;
|
||||||
|
|
||||||
@@ -65,6 +66,32 @@ int main(int argc, char *argv[]) {
|
|||||||
child_sub = mpc_ast_get_child_lb(child, "node|leaf|regex", lb);
|
child_sub = mpc_ast_get_child_lb(child, "node|leaf|regex", lb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Traversal */
|
||||||
|
printf("Pre order tree traversal.\n");
|
||||||
|
trav = mpc_ast_traverse_start(ast, mpc_ast_trav_order_pre);
|
||||||
|
|
||||||
|
ast_next = mpc_ast_traverse_next(&trav);
|
||||||
|
|
||||||
|
while(ast_next != NULL) {
|
||||||
|
printf("Tag: %s; Contents: %s\n",
|
||||||
|
ast_next->tag,
|
||||||
|
ast_next->contents);
|
||||||
|
ast_next = mpc_ast_traverse_next(&trav);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Post order tree traversal.\n");
|
||||||
|
|
||||||
|
trav = mpc_ast_traverse_start(ast, mpc_ast_trav_order_post);
|
||||||
|
|
||||||
|
ast_next = mpc_ast_traverse_next(&trav);
|
||||||
|
|
||||||
|
while(ast_next != NULL) {
|
||||||
|
printf("Tag: %s; Contents: %s\n",
|
||||||
|
ast_next->tag,
|
||||||
|
ast_next->contents);
|
||||||
|
ast_next = mpc_ast_traverse_next(&trav);
|
||||||
|
}
|
||||||
|
|
||||||
/* Clean up and return */
|
/* Clean up and return */
|
||||||
mpc_cleanup(3, Node, Leaf, Input);
|
mpc_cleanup(3, Node, Leaf, Input);
|
||||||
mpc_ast_delete(ast);
|
mpc_ast_delete(ast);
|
||||||
|
125
mpc.c
125
mpc.c
@@ -2808,6 +2808,131 @@ mpc_ast_t *mpc_ast_get_child_lb(mpc_ast_t *ast, const char *tag, int lb) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mpc_ast_trav_t *mpc_ast_traverse_start(mpc_ast_t *ast,
|
||||||
|
mpc_ast_trav_order_t order)
|
||||||
|
{
|
||||||
|
mpc_ast_trav_t *trav, *n_trav;
|
||||||
|
mpc_ast_t *cnode = ast;
|
||||||
|
|
||||||
|
/* Create the traversal structure */
|
||||||
|
trav = malloc(sizeof(mpc_ast_trav_t));
|
||||||
|
trav->curr_node = cnode;
|
||||||
|
trav->parent = NULL;
|
||||||
|
trav->curr_child = 0;
|
||||||
|
trav->order = order;
|
||||||
|
|
||||||
|
/* Get start node */
|
||||||
|
switch(order) {
|
||||||
|
case mpc_ast_trav_order_pre:
|
||||||
|
/* Nothing else is needed for pre order start */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mpc_ast_trav_order_post:
|
||||||
|
while(cnode->children_num > 0) {
|
||||||
|
cnode = cnode->children[0];
|
||||||
|
|
||||||
|
n_trav = malloc(sizeof(mpc_ast_trav_t));
|
||||||
|
n_trav->curr_node = cnode;
|
||||||
|
n_trav->parent = trav;
|
||||||
|
n_trav->curr_child = 0;
|
||||||
|
n_trav->order = order;
|
||||||
|
|
||||||
|
trav = n_trav;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Unreachable, but compiler complaints */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return trav;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpc_ast_t *mpc_ast_traverse_next(mpc_ast_trav_t **trav) {
|
||||||
|
mpc_ast_trav_t *n_trav, *to_free;
|
||||||
|
mpc_ast_t *ret = NULL;
|
||||||
|
int cchild;
|
||||||
|
|
||||||
|
/* The end of traversal was reached */
|
||||||
|
if(*trav == NULL) return NULL;
|
||||||
|
|
||||||
|
switch((*trav)->order) {
|
||||||
|
case mpc_ast_trav_order_pre:
|
||||||
|
ret = (*trav)->curr_node;
|
||||||
|
|
||||||
|
/* If there aren't any more children, go up */
|
||||||
|
while(*trav != NULL &&
|
||||||
|
(*trav)->curr_child >= (*trav)->curr_node->children_num)
|
||||||
|
{
|
||||||
|
to_free = *trav;
|
||||||
|
*trav = (*trav)->parent;
|
||||||
|
free(to_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If trav is NULL, the end was reached */
|
||||||
|
if(*trav == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go to next child */
|
||||||
|
n_trav = malloc(sizeof(mpc_ast_trav_t));
|
||||||
|
|
||||||
|
cchild = (*trav)->curr_child;
|
||||||
|
n_trav->curr_node = (*trav)->curr_node->children[cchild];
|
||||||
|
n_trav->parent = *trav;
|
||||||
|
n_trav->curr_child = 0;
|
||||||
|
n_trav->order = (*trav)->order;
|
||||||
|
|
||||||
|
(*trav)->curr_child++;
|
||||||
|
*trav = n_trav;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mpc_ast_trav_order_post:
|
||||||
|
ret = (*trav)->curr_node;
|
||||||
|
|
||||||
|
/* Move up tree to the parent If the parent doesn't have any more nodes,
|
||||||
|
* then this is the current node. If it does, move down to its left most
|
||||||
|
* child. Also, free the previous traversal node */
|
||||||
|
to_free = *trav;
|
||||||
|
*trav = (*trav)->parent;
|
||||||
|
free(to_free);
|
||||||
|
|
||||||
|
if(*trav == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Next child */
|
||||||
|
(*trav)->curr_child++;
|
||||||
|
|
||||||
|
/* If there aren't any more children, this is the next node */
|
||||||
|
if((*trav)->curr_child >= (*trav)->curr_node->children_num) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there are still more children, find the leftmost child from this
|
||||||
|
* node */
|
||||||
|
while((*trav)->curr_node->children_num > 0) {
|
||||||
|
n_trav = malloc(sizeof(mpc_ast_trav_t));
|
||||||
|
|
||||||
|
cchild = (*trav)->curr_child;
|
||||||
|
n_trav->curr_node = (*trav)->curr_node->children[cchild];
|
||||||
|
n_trav->parent = *trav;
|
||||||
|
n_trav->curr_child = 0;
|
||||||
|
n_trav->order = (*trav)->order;
|
||||||
|
|
||||||
|
*trav = n_trav;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Unreachable, but compiler complaints */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
mpc_val_t *mpcf_fold_ast(int n, mpc_val_t **xs) {
|
mpc_val_t *mpcf_fold_ast(int n, mpc_val_t **xs) {
|
||||||
|
|
||||||
int i, j;
|
int i, j;
|
||||||
|
17
mpc.h
17
mpc.h
@@ -281,6 +281,23 @@ int mpc_ast_get_index_lb(mpc_ast_t *ast, const char *tag, int lb);
|
|||||||
mpc_ast_t *mpc_ast_get_child(mpc_ast_t *ast, const char *tag);
|
mpc_ast_t *mpc_ast_get_child(mpc_ast_t *ast, const char *tag);
|
||||||
mpc_ast_t *mpc_ast_get_child_lb(mpc_ast_t *ast, const char *tag, int lb);
|
mpc_ast_t *mpc_ast_get_child_lb(mpc_ast_t *ast, const char *tag, int lb);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
mpc_ast_trav_order_pre,
|
||||||
|
mpc_ast_trav_order_post
|
||||||
|
} mpc_ast_trav_order_t;
|
||||||
|
|
||||||
|
typedef struct mpc_ast_trav_t {
|
||||||
|
mpc_ast_t *curr_node;
|
||||||
|
struct mpc_ast_trav_t *parent;
|
||||||
|
int curr_child;
|
||||||
|
mpc_ast_trav_order_t order;
|
||||||
|
} mpc_ast_trav_t;
|
||||||
|
|
||||||
|
mpc_ast_trav_t *mpc_ast_traverse_start(mpc_ast_t *ast,
|
||||||
|
mpc_ast_trav_order_t order);
|
||||||
|
|
||||||
|
mpc_ast_t *mpc_ast_traverse_next(mpc_ast_trav_t **trav);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Warning: This function currently doesn't test for equality of the `state` member!
|
** Warning: This function currently doesn't test for equality of the `state` member!
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user