diff --git a/examples/tree_traversal.c b/examples/tree_traversal.c new file mode 100644 index 0000000..3ec0299 --- /dev/null +++ b/examples/tree_traversal.c @@ -0,0 +1,73 @@ +#include "../mpc.h" + +int main(int argc, char *argv[]) { + + mpc_parser_t *Input = mpc_new("input"); + mpc_parser_t *Node = mpc_new("node"); + mpc_parser_t *Leaf = mpc_new("leaf"); + mpc_ast_t *ast, *tree, *child, *child_sub; + mpc_result_t r; + int index, lb; + + mpca_lang(MPCA_LANG_PREDICTIVE, + " node : '(' ',' /foo/ ',' ')' | ;" + " leaf : /bar/;" + " input : /^/ /$/;", + Node, Leaf, Input, NULL); + + if (argc > 1) { + + if (mpc_parse_contents(argv[1], Input, &r)) { + ast = r.output; + } else { + mpc_err_print(r.error); + mpc_err_delete(r.error); + mpc_cleanup(3, Node, Leaf, Input); + return EXIT_FAILURE; + } + + } else { + + if (mpc_parse_pipe("", stdin, Input, &r)) { + ast = r.output; + } else { + mpc_err_print(r.error); + mpc_err_delete(r.error); + mpc_cleanup(3, Node, Leaf, Input); + return EXIT_FAILURE; + } + + } + + /* Get index or child of tree */ + tree = ast->children[1]; + + index = mpc_ast_get_index(tree, "node|>"); + child = mpc_ast_get_child(tree, "node|>"); + + if(child == NULL) { + mpc_cleanup(3, Node, Leaf, Input); + mpc_ast_delete(ast); + return EXIT_FAILURE; + } + + printf("Index: %d; Child: \"%s\"\n", index, child->tag); + + /* Get multiple indexes or children of trees */ + index = mpc_ast_get_index_lb(child, "node|leaf|regex", 0); + child_sub = mpc_ast_get_child_lb(child, "node|leaf|regex", 0); + + while(index != -1) { + printf("-- Index: %d; Child: \"%s\"\n", index, child_sub->tag); + + lb = index + 1; + index = mpc_ast_get_index_lb(child, "node|leaf|regex", lb); + child_sub = mpc_ast_get_child_lb(child, "node|leaf|regex", lb); + } + + /* Clean up and return */ + mpc_cleanup(3, Node, Leaf, Input); + mpc_ast_delete(ast); + + return EXIT_SUCCESS; +} diff --git a/mpc.c b/mpc.c index 9e84a47..6c65255 100644 --- a/mpc.c +++ b/mpc.c @@ -2776,6 +2776,38 @@ void mpc_ast_print_to(mpc_ast_t *a, FILE *fp) { mpc_ast_print_depth(a, 0, fp); } +int mpc_ast_get_index(mpc_ast_t *ast, const char *tag) { + return mpc_ast_get_index_lb(ast, tag, 0); +} + +int mpc_ast_get_index_lb(mpc_ast_t *ast, const char *tag, int lb) { + int i; + + for(i=lb; ichildren_num; i++) { + if(strcmp(ast->children[i]->tag, tag) == 0) { + return i; + } + } + + return -1; +} + +mpc_ast_t *mpc_ast_get_child(mpc_ast_t *ast, const char *tag) { + return mpc_ast_get_child_lb(ast, tag, 0); +} + +mpc_ast_t *mpc_ast_get_child_lb(mpc_ast_t *ast, const char *tag, int lb) { + int i; + + for(i=lb; ichildren_num; i++) { + if(strcmp(ast->children[i]->tag, tag) == 0) { + return ast->children[i]; + } + } + + return NULL; +} + mpc_val_t *mpcf_fold_ast(int n, mpc_val_t **xs) { int i, j; diff --git a/mpc.h b/mpc.h index a9d8a72..82ee6ba 100644 --- a/mpc.h +++ b/mpc.h @@ -276,6 +276,11 @@ void mpc_ast_delete(mpc_ast_t *a); void mpc_ast_print(mpc_ast_t *a); void mpc_ast_print_to(mpc_ast_t *a, FILE *fp); +int mpc_ast_get_index(mpc_ast_t *ast, const char *tag); +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_lb(mpc_ast_t *ast, const char *tag, int lb); + /* ** Warning: This function currently doesn't test for equality of the `state` member! */