From 967be9e750221ab2ab783f95df79bb26d290a45e Mon Sep 17 00:00:00 2001 From: Martial Simon Date: Mon, 15 Sep 2025 01:07:58 +0200 Subject: add: added projects --- 42sh/src/ast/ast_pretty_print.c | 247 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 42sh/src/ast/ast_pretty_print.c (limited to '42sh/src/ast/ast_pretty_print.c') diff --git a/42sh/src/ast/ast_pretty_print.c b/42sh/src/ast/ast_pretty_print.c new file mode 100644 index 0000000..17c5b2a --- /dev/null +++ b/42sh/src/ast/ast_pretty_print.c @@ -0,0 +1,247 @@ +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809L + +#include +#include + +#include "ast/ast.h" +#include "ast/ast_accessors.h" +#include "ast/ast_redirect.h" +#include "lexer/token.h" + +#define BUFFER_SIZE 10000 + +static char *_type_to_string[] = { [AST_LOGICAL] = "logical block", + [AST_COMMAND] = "command", + [AST_IF] = "conditionnal block", + [AST_LIST] = "list", + [AST_PIPELINE] = "pipeline", + [AST_REDIRECTION] = "redirection", + [AST_WHILE] = "while", + [AST_ASSIGN] = "assign", + [AST_FOR] = "for" }; + +typedef char *(*tostring)(struct ast *); + +static char *_args_tostring(struct string **args) +{ + struct string *output = string_create(NULL); + size_t i = 0; + while (args[i]) + { + struct string *c = string_deepcopy(args[i++]); + string_catenate(output, c); + if (args[i]) + string_pushstr(output, " - "); + } + char *data = output->data; + free(output); + return data; +} + +static char *_ast_command_tostring(struct ast *ast) +{ + char buf[BUFFER_SIZE] = { 0 }; + char *args_to_string = _args_tostring(((struct ast_command *)ast)->args); + int len = snprintf(buf, BUFFER_SIZE, "%s\\nargs: %s", + _type_to_string[ast->type], args_to_string); + free(args_to_string); + char *str = malloc((len + 1) * sizeof(char)); + for (int i = 0; i < len; i++) + { + str[i] = buf[i]; + } + str[len] = 0; + return str; +} + +static char *_ast_if_tostring(struct ast *ast) +{ + char buf[BUFFER_SIZE] = { 0 }; + int len = snprintf(buf, BUFFER_SIZE, "%s\\n", _type_to_string[ast->type]); + char *str = malloc((len + 1) * sizeof(char)); + for (int i = 0; i < len; i++) + { + str[i] = buf[i]; + } + str[len] = 0; + return str; +} + +static char *_get_token_type_to_str(struct ast *ast) +{ + enum token_type t = ((struct ast_logical *)ast)->type; + switch (t) + { + case TOKEN_AND: + return "&&"; + case TOKEN_OR: + return "||"; + case TOKEN_NEG: + return "!"; + default: + return "unknown"; + } +} + +static char *_ast_logical_tostring(struct ast *ast) +{ + char buf[BUFFER_SIZE] = { 0 }; + int len = snprintf(buf, BUFFER_SIZE, "%s\\n%s", _type_to_string[ast->type], + _get_token_type_to_str(ast)); + char *str = malloc((len + 1) * sizeof(char)); + for (int i = 0; i < len; i++) + { + str[i] = buf[i]; + } + str[len] = 0; + return str; +} + +static char *_ast_list_tostring(struct ast *ast) +{ + char buf[BUFFER_SIZE] = { 0 }; + size_t nb_c = ((struct ast_list *)ast)->nb_children; + int len = snprintf(buf, BUFFER_SIZE, "%s\\n%lu child(ren)", + _type_to_string[ast->type], nb_c); + char *str = malloc((len + 1) * sizeof(char)); + for (int i = 0; i < len; i++) + { + str[i] = buf[i]; + } + str[len] = 0; + return str; +} + +static char *_ast_pipeline_tostring(struct ast *ast) +{ + char buf[BUFFER_SIZE] = { 0 }; + int len = snprintf(buf, BUFFER_SIZE, "%s\\nleft | right", + _type_to_string[ast->type]); + char *str = malloc((len + 1) * sizeof(char)); + for (int i = 0; i < len; i++) + { + str[i] = buf[i]; + } + str[len] = 0; + return str; +} + +static char *_ast_assign_tostring(struct ast *ast) +{ + char buf[BUFFER_SIZE] = { 0 }; + struct string *name = ((struct ast_assign *)ast)->name; + struct string *value = ((struct ast_assign *)ast)->val; + int len = snprintf(buf, BUFFER_SIZE, "%s\\n%s=%s", + _type_to_string[ast->type], name->data, value->data); + char *str = malloc((len + 1) * sizeof(char)); + for (int i = 0; i < len; i++) + { + str[i] = buf[i]; + } + str[len] = 0; + return str; +} + +static char *_ast_redirection_tostring(struct ast *ast) +{ + struct redirect r = ((struct ast_redirection *)ast)->redirect; + char buf[BUFFER_SIZE] = { 0 }; + int len = + snprintf(buf, BUFFER_SIZE, "%s\\n%s %s %s", _type_to_string[ast->type], + r.fd->data, r.redir->data, r.file->data); + char *str = malloc((len + 1) * sizeof(char)); + for (int i = 0; i < len; i++) + { + str[i] = buf[i]; + } + str[len] = 0; + return str; +} + +static char *_ast_while_tostring(struct ast *ast) +{ + char buf[BUFFER_SIZE] = { 0 }; + int len = snprintf(buf, BUFFER_SIZE, "%s\\nleft is cond\nright is body", + _type_to_string[ast->type]); + char *str = malloc((len + 1) * sizeof(char)); + for (int i = 0; i < len; i++) + { + str[i] = buf[i]; + } + str[len] = 0; + return str; +} + +static char *_ast_for_tostring(struct ast *ast) +{ + char buf[BUFFER_SIZE] = { 0 }; + int len = snprintf(buf, BUFFER_SIZE, "%s\\nleft is words\nright is body", + _type_to_string[ast->type]); + char *str = malloc((len + 1) * sizeof(char)); + for (int i = 0; i < len; i++) + { + str[i] = buf[i]; + } + str[len] = 0; + return str; +} + +static const tostring _node_to_string_ltable[] = { + [AST_LOGICAL] = _ast_logical_tostring, + [AST_COMMAND] = _ast_command_tostring, + [AST_IF] = _ast_if_tostring, + [AST_LIST] = _ast_list_tostring, + [AST_PIPELINE] = _ast_pipeline_tostring, + [AST_REDIRECTION] = _ast_redirection_tostring, + [AST_WHILE] = _ast_while_tostring, + [AST_ASSIGN] = _ast_assign_tostring, + [AST_FOR] = _ast_for_tostring +}; + +static char *_ast_to_string(struct ast *ast) +{ + return _node_to_string_ltable[ast->type](ast); +} + +static void _pretty_print_internal(struct ast *ast, FILE *f) +{ + if (!ast) + { + return; + } + char *format = _ast_to_string(ast); + fprintf(f, "\t%lu [label=\"%s\"];\n", (size_t)ast, format); + free(format); + size_t i = 0; + struct ast *child = NULL; + do + { + child = get_i(ast, i); + if (!child) + { + break; + } + i++; + fprintf(f, "\t%lu -- %lu;\n", (size_t)ast, (size_t)child); + _pretty_print_internal(child, f); + } while (child); +} + +void pretty_print(struct ast *ast) +{ + FILE *f = fopen("ast.dot", "w"); + if (!f) + { + fprintf(stderr, + "pretty_print: unable to open a file to write the DOT AST.\n"); + return; + } + + fprintf(f, "graph {\n"); + + _pretty_print_internal(ast, f); + + fprintf(f, "}\n"); + fclose(f); +} -- cgit v1.2.3