#ifndef __SCC_TREE_DUMP_H__ #define __SCC_TREE_DUMP_H__ #include #define SCC_TREE_DUMP_VERTICAL "| " #define SCC_TREE_DUMP_BRANCH "|-" #define SCC_TREE_DUMP_LAST_BRANCH "`-" #define SCC_TREE_DUMP_SPACE " " #define SCC_TREE_DUMP_NODE_COLOR ANSI_FG_BLUE #define SCC_TREE_DUMP_VALUE_COLOR ANSI_FG_GREEN #define SCC_TREE_DUMP_BRANCH_COLOR ANSI_FG_YELLOW #define SCC_TREE_DUMP_RESET_COLOR ANSI_NONE // #define ANSI_FMT typedef SCC_VEC(cbool) scc_ast_dump_stack_t; typedef void (*scc_tree_dump_output_t)(void *userdata, const char *fmt, ...); typedef struct { scc_ast_dump_stack_t stack; ///< 每层是否为最后子节点 cbool use_color; ///< 是否使用颜色输出 const char *vertical; const char *branch; const char *last_branch; const char *space; const char *node_color; ///< 节点类型颜色 const char *value_color; ///< 值颜色 const char *branch_color; ///< 分支符号颜色 const char *reset_color; ///< 重置颜色 scc_tree_dump_output_t output_func; void *output_userdata; } scc_tree_dump_ctx_t; static inline void scc_tree_dump_ctx_init(scc_tree_dump_ctx_t *ctx, cbool use_color, scc_tree_dump_output_t output_func, void *output_userdata) { ctx->use_color = use_color; scc_vec_init(ctx->stack); ctx->vertical = SCC_TREE_DUMP_VERTICAL; ctx->branch = SCC_TREE_DUMP_BRANCH; ctx->last_branch = SCC_TREE_DUMP_LAST_BRANCH; ctx->space = SCC_TREE_DUMP_SPACE; ctx->node_color = use_color ? SCC_TREE_DUMP_NODE_COLOR : ""; ctx->value_color = use_color ? SCC_TREE_DUMP_VALUE_COLOR : ""; ctx->branch_color = use_color ? SCC_TREE_DUMP_BRANCH_COLOR : ""; ctx->reset_color = use_color ? SCC_TREE_DUMP_RESET_COLOR : ""; ctx->output_func = output_func; ctx->output_userdata = output_userdata; } #define scc_tree_dump_printf(ctx, fmt, ...) \ (ctx)->output_func((ctx)->output_userdata, fmt, ##__VA_ARGS__) static inline void scc_tree_dump_ctx_drop(scc_tree_dump_ctx_t *ctx) { scc_vec_free(ctx->stack); } // 打印缩进 static void scc_tree_print_indent(scc_tree_dump_ctx_t *ctx) { scc_vec_foreach(ctx->stack, i) { cbool last_child = scc_vec_at(ctx->stack, i); const char *data = null; if (i + 1 == scc_vec_size(ctx->stack)) { // 最后一层打印分支符号 data = last_child ? ctx->last_branch : ctx->branch; } else { data = last_child ? ctx->space : ctx->vertical; } Assert(data != null); if (ctx->use_color) { ctx->output_func(ctx->output_userdata, "%s%s%s", ctx->branch_color, data, ctx->reset_color); } else { ctx->output_func(ctx->output_userdata, "%s", data); } } } #define SCC_TREE_DUMP_PRINT_COLORED(ctx, color, before_str, fmt, after_str, \ ...) \ (ctx)->output_func((ctx)->output_userdata, \ before_str "%s" fmt "%s" after_str, \ (ctx)->use_color ? color : "", ##__VA_ARGS__, \ (ctx)->use_color ? ANSI_NONE : ""); #define SCC_TREE_DUMP_PRINT_AROUND(ctx, color, around_str, fmt, ...) \ SCC_TREE_DUMP_PRINT_COLORED(ctx, color, around_str, fmt, around_str, \ ##__VA_ARGS__) #define SCC_TREE_DUMP_PRINT_PURE(ctx, color, fmt, ...) \ SCC_TREE_DUMP_PRINT_COLORED(ctx, color, "", fmt, "", ##__VA_ARGS__) // 推入新的层级到栈中 static inline void scc_tree_dump_push_level(scc_tree_dump_ctx_t *ctx, cbool is_last_child) { scc_vec_push(ctx->stack, is_last_child); } // 弹出当前层级 static inline void scc_tree_dump_pop_level(scc_tree_dump_ctx_t *ctx) { (void)scc_vec_pop(ctx->stack); } // 获取当前层级深度 static inline usize scc_tree_dump_depth(scc_tree_dump_ctx_t *ctx) { return scc_vec_size(ctx->stack); } #endif /* __SCC_TREE_DUMP_H__ */