From f6573d81f0e0b531baebad1be5f21188b501088d Mon Sep 17 00:00:00 2001 From: Jean Herail Date: Wed, 14 Jan 2026 20:42:31 +0100 Subject: [PATCH] feat(pretty-print): Just casually implemented the graphviz representation of parsed AST --- .gitignore | 1 + src/utils/ast/ast.c | 91 ++++++++++++++++++++++++++++++++++++++++++++- src/utils/ast/ast.h | 5 +++ 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 64c4a76..ab7c85c 100644 --- a/.gitignore +++ b/.gitignore @@ -175,3 +175,4 @@ m4/ltversion.m4 m4/lt~obsolete.m4 Makefile +*.svg diff --git a/src/utils/ast/ast.c b/src/utils/ast/ast.c index 40b42d7..4019e44 100644 --- a/src/utils/ast/ast.c +++ b/src/utils/ast/ast.c @@ -1,9 +1,96 @@ -#include "ast.h" - #include #include +#include #include +#include "ast.h" + +static void ast_print_dot_recursive(struct ast *node, FILE *out) +{ + if (!node) + return; + + 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; + } +} + +void ast_print_dot(struct ast *ast) +{ + // Always print to stdout so the user can see it in the terminal + printf("digraph AST {\n"); + if (ast) + { + ast_print_dot_recursive(ast, stdout); + } + printf("}\n"); + + 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); diff --git a/src/utils/ast/ast.h b/src/utils/ast/ast.h index 3247ba5..54fef4b 100644 --- a/src/utils/ast/ast.h +++ b/src/utils/ast/ast.h @@ -70,4 +70,9 @@ struct ast *ast_create_if(struct ast *condition, struct ast *then_clause, */ struct ast *ast_create_cmd(struct list *cmd); +/** + * Prints the Graphviz DOT representation of the given AST to stdout. + */ +void ast_print_dot(struct ast *ast); + #endif /* ! AST_H */