diff --git a/.gitignore b/.gitignore index 9cdb480..09e5b39 100644 --- a/.gitignore +++ b/.gitignore @@ -177,3 +177,4 @@ m4/ltversion.m4 m4/lt~obsolete.m4 Makefile +*.svg diff --git a/src/parser/parser.c b/src/parser/parser.c index 862c025..dbe3f72 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -51,4 +51,4 @@ struct ast *get_ast_str(char *command) { (void)command; return NULL; -} +} \ No newline at end of file diff --git a/src/utils/ast/ast.c b/src/utils/ast/ast.c index c4bece9..cd875e7 100644 --- a/src/utils/ast/ast.c +++ b/src/utils/ast/ast.c @@ -1,31 +1,119 @@ #include "ast.h" +#include #include +#include +#include -void ast_free(struct ast **node) +static void ast_print_dot_recursive(struct ast *node, FILE *out) { - if (*node == NULL) + if (!node) return; - // ast void does not need to be freed. - if (ast_is_if(*node)) - ast_free_if(ast_get_if(*node)); - else if (ast_is_command(*node)) - ast_free_command(ast_get_command(*node)); - else if (ast_is_list(*node)) - ast_free_list(ast_get_list(*node)); - else if (ast_is_and_or(*node)) - ast_free_and_or(ast_get_and_or(*node)); - else if (ast_is_redir(*node)) - ast_free_redir(ast_get_redir(*node)); - free(*node); - *node = NULL; + switch (node->type) + { + case AST_IF: { + struct ast_if *if_data = ast_get_if(node); + fprintf(out, " node%p [label=\"IF\"];\n", (void *)node); + + if (if_data->condition) + { + fprintf(out, " node%p -> node%p;\n", (void *)node, + (void *)if_data->condition); + fprintf(out, + " node%p [fillcolor=\"lightyellow\", style=\"filled\"];\n", + (void *)if_data->condition); + ast_print_dot_recursive(if_data->condition, out); + + if (if_data->then_clause) + { + fprintf(out, " node%p -> node%p [label=\"true\"];\n", + (void *)if_data->condition, + (void *)if_data->then_clause); + ast_print_dot_recursive(if_data->then_clause, out); + } + + if (if_data->else_clause) + { + fprintf(out, " node%p -> node%p [label=\"false\"];\n", + (void *)if_data->condition, + (void *)if_data->else_clause); + ast_print_dot_recursive(if_data->else_clause, out); + } + } + break; + } + case AST_CMD: { + struct ast_cmd *cmd_data = ast_get_cmd(node); + fprintf(out, " node%p [label=\"", (void *)node); + struct list *l = cmd_data->cmd; + while (l) + { + fprintf(out, "%s", (char *)l->data); + if (l->next) + fprintf(out, " "); + l = l->next; + } + fprintf(out, "\"];\n"); + break; + } + case AST_END: + fprintf(out, " node%p [label=\"END\"];\n", (void *)node); + break; + default: + break; + } } -struct ast *ast_create(enum ast_type type, void *data) +void ast_print_dot(struct ast *ast) +{ + if (!ast) + return; + + FILE *dot_pipe = popen("dot -Tsvg -o ast.svg", "w"); + if (!dot_pipe) + { + return; + } + + fprintf(dot_pipe, "digraph AST {\n"); + ast_print_dot_recursive(ast, dot_pipe); + fprintf(dot_pipe, "}\n"); + pclose(dot_pipe); + + system("open ast.svg"); +} + +bool ast_is_if(struct ast *node) +{ + assert(node != NULL); + return node->type == AST_IF; +} + +bool ast_is_cmd(struct ast *node) +{ + assert(node != NULL); + return node->type == AST_CMD; +} + +struct ast_if *ast_get_if(struct ast *node) +{ + assert(node != NULL); + assert(node->type == AST_IF); + return (struct ast_if *)node->data; +} + +struct ast_cmd *ast_get_cmd(struct ast *node) +{ + assert(node != NULL); + assert(node->type == AST_CMD); + return (struct ast_cmd *)node->data; +} + +static struct ast *ast_create(enum ast_type type, void *data) { struct ast *node = malloc(sizeof(struct ast)); - if (node == NULL) + if (!node) return NULL; node->type = type; @@ -33,3 +121,28 @@ struct ast *ast_create(enum ast_type type, void *data) return node; } + +struct ast *ast_create_if(struct ast *condition, struct ast *then_clause, + struct ast *else_clause) +{ + struct ast_if *if_data = malloc(sizeof(struct ast_if)); + if (!if_data) + return NULL; + + if_data->condition = condition; + if_data->then_clause = then_clause; + if_data->else_clause = else_clause; + + return ast_create(AST_IF, if_data); +} + +struct ast *ast_create_cmd(struct list *cmd) +{ + struct ast_cmd *cmd_data = malloc(sizeof(struct ast_cmd)); + if (!cmd_data) + return NULL; + + cmd_data->cmd = cmd; + + return ast_create(AST_CMD, cmd_data); +} diff --git a/src/utils/ast/ast.h b/src/utils/ast/ast.h index 187f748..a98d88b 100644 --- a/src/utils/ast/ast.h +++ b/src/utils/ast/ast.h @@ -10,4 +10,9 @@ #include "ast_redir.h" #include "ast_void.h" +/** + * Prints the Graphviz DOT representation of the given AST to stdout. + */ +void ast_print_dot(struct ast *ast); + #endif /* ! AST_H */