feat(ast): 添加AST定义和dump工具头文件
新增libs/ast模块的基础定义文件,包括: - AST节点类型枚举定义,涵盖声明、语句、表达式、类型等各类节点 - AST操作符枚举,定义所有二元、一元、逻辑、算术等操作符 - AST节点结构体定义,包含表达式、语句、声明、类型等具体实现 - AST dump工具接口,支持树形结构输出和颜色显示 - 语义分析回调函数类型定义,为后续语义分析提供基础
This commit is contained in:
803
libs/ast/src/ast_dump.c
Normal file
803
libs/ast/src/ast_dump.c
Normal file
@@ -0,0 +1,803 @@
|
||||
/**
|
||||
* @file ast_dump.c
|
||||
* @brief AST dump 实现
|
||||
*/
|
||||
|
||||
#include <ast_dump.h>
|
||||
|
||||
#define VERTICAL "| "
|
||||
#define BRANCH "|-"
|
||||
#define LAST_BRANCH "`-"
|
||||
#define SPACE " "
|
||||
|
||||
// 默认颜色配置
|
||||
#define DEFAULT_NODE_COLOR ANSI_FG_BLUE
|
||||
#define DEFAULT_VALUE_COLOR ANSI_FG_GREEN
|
||||
#define DEFAULT_BRANCH_COLOR ANSI_FG_YELLOW
|
||||
#define DEFAULT_RESET_COLOR ANSI_NONE
|
||||
|
||||
// 通用宏定义
|
||||
#define PRINT_COLORED(ctx, color_field, fmt, ...) \
|
||||
do { \
|
||||
if (ctx->use_color) { \
|
||||
scc_printf("%s" fmt "%s", ctx->color_field, ##__VA_ARGS__, \
|
||||
ctx->reset_color); \
|
||||
} else { \
|
||||
scc_printf(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PRINT_VALUE(ctx, fmt, ...) \
|
||||
PRINT_COLORED(ctx, value_color, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define PRINT_NODE_TYPE(ctx, node) \
|
||||
PRINT_COLORED(ctx, node_color, "%s", get_node_type_str(node->type))
|
||||
|
||||
#define PRINT_QUOTED_VALUE(ctx, value) \
|
||||
do { \
|
||||
PRINT_VALUE(ctx, "'%s'", value); \
|
||||
} while (0)
|
||||
|
||||
// 扩展上下文深度
|
||||
static void ensure_context_depth(scc_ast_dump_ctx_t *ctx, int new_depth) {
|
||||
if ((size_t)new_depth >= ctx->max_depth) {
|
||||
size_t old_size = ctx->max_depth * sizeof(cbool);
|
||||
ctx->max_depth = new_depth + 16; // 预分配更多空间
|
||||
ctx->is_last_child = (cbool *)scc_realloc(
|
||||
ctx->is_last_child, ctx->max_depth * sizeof(cbool));
|
||||
scc_memset((char *)ctx->is_last_child + old_size, 0,
|
||||
ctx->max_depth * sizeof(cbool) - old_size);
|
||||
}
|
||||
}
|
||||
|
||||
// 打印缩进
|
||||
static void print_indent(scc_ast_dump_ctx_t *ctx) {
|
||||
for (int i = 0; i < ctx->depth; i++) {
|
||||
if (i == ctx->depth - 1) {
|
||||
// 最后一层打印分支符号
|
||||
if (ctx->use_color) {
|
||||
scc_printf("%s%s%s", ctx->branch_color,
|
||||
ctx->is_last_child[i] ? LAST_BRANCH : BRANCH,
|
||||
ctx->reset_color);
|
||||
} else {
|
||||
scc_printf("%s", ctx->is_last_child[i] ? LAST_BRANCH : BRANCH);
|
||||
}
|
||||
} else {
|
||||
// 中间层根据是否是最后一个子节点决定是否打印垂直线
|
||||
if (ctx->use_color) {
|
||||
scc_printf("%s%s%s", ctx->branch_color,
|
||||
ctx->is_last_child[i] ? SPACE : VERTICAL,
|
||||
ctx->reset_color);
|
||||
} else {
|
||||
scc_printf("%s", ctx->is_last_child[i] ? SPACE : VERTICAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取节点类型的字符串表示
|
||||
static const char *get_node_type_str(scc_ast_node_type_t type) {
|
||||
switch (type) {
|
||||
// 声明类型
|
||||
case SCC_AST_DECL_VAR:
|
||||
return "VarDecl";
|
||||
case SCC_AST_DECL_FUNC:
|
||||
return "FuncDecl";
|
||||
case SCC_AST_DECL_PARAM:
|
||||
return "ParamDecl";
|
||||
case SCC_AST_DECL_STRUCT:
|
||||
return "StructDecl";
|
||||
case SCC_AST_DECL_UNION:
|
||||
return "UnionDecl";
|
||||
case SCC_AST_DECL_ENUM:
|
||||
return "EnumDecl";
|
||||
case SCC_AST_DECL_TYPEDEF:
|
||||
return "TypedefDecl";
|
||||
|
||||
// 语句类型
|
||||
case SCC_AST_STMT_COMPOUND:
|
||||
return "CompoundStmt";
|
||||
case SCC_AST_STMT_EXPR:
|
||||
return "ExprStmt";
|
||||
case SCC_AST_STMT_IF:
|
||||
return "IfStmt";
|
||||
case SCC_AST_STMT_WHILE:
|
||||
return "WhileStmt";
|
||||
case SCC_AST_STMT_DO_WHILE:
|
||||
return "DoStmt";
|
||||
case SCC_AST_STMT_FOR:
|
||||
return "ForStmt";
|
||||
case SCC_AST_STMT_SWITCH:
|
||||
return "SwitchStmt";
|
||||
case SCC_AST_STMT_CASE:
|
||||
return "CaseStmt";
|
||||
case SCC_AST_STMT_DEFAULT:
|
||||
return "DefaultStmt";
|
||||
case SCC_AST_STMT_BREAK:
|
||||
return "BreakStmt";
|
||||
case SCC_AST_STMT_CONTINUE:
|
||||
return "ContinueStmt";
|
||||
case SCC_AST_STMT_RETURN:
|
||||
return "ReturnStmt";
|
||||
case SCC_AST_STMT_GOTO:
|
||||
return "GotoStmt";
|
||||
case SCC_AST_STMT_LABEL:
|
||||
return "LabelStmt";
|
||||
|
||||
// 表达式类型
|
||||
case SCC_AST_EXPR_BINARY:
|
||||
return "BinaryOperator";
|
||||
case SCC_AST_EXPR_UNARY:
|
||||
return "UnaryOperator";
|
||||
case SCC_AST_EXPR_COND:
|
||||
return "ConditionalOperator";
|
||||
case SCC_AST_EXPR_CALL:
|
||||
return "CallExpr";
|
||||
case SCC_AST_EXPR_ARRAY_SUBSCRIPT:
|
||||
return "ArraySubscriptExpr";
|
||||
case SCC_AST_EXPR_MEMBER:
|
||||
return "MemberExpr";
|
||||
case SCC_AST_EXPR_PTR_MEMBER:
|
||||
return "PtrMemberExpr";
|
||||
case SCC_AST_EXPR_CAST:
|
||||
return "CastExpr";
|
||||
case SCC_AST_EXPR_SIZE_OF:
|
||||
return "SizeOfExpr";
|
||||
case SCC_AST_EXPR_ALIGN_OF:
|
||||
return "AlignOfExpr";
|
||||
case SCC_AST_EXPR_COMPOUND_LITERAL:
|
||||
return "CompoundLiteralExpr";
|
||||
case SCC_AST_EXPR_INT_LITERAL:
|
||||
return "IntegerLiteral";
|
||||
case SCC_AST_EXPR_FLOAT_LITERAL:
|
||||
return "FloatingLiteral";
|
||||
case SCC_AST_EXPR_CHAR_LITERAL:
|
||||
return "CharacterLiteral";
|
||||
case SCC_AST_EXPR_STRING_LITERAL:
|
||||
return "StringLiteral";
|
||||
case SCC_AST_EXPR_IDENTIFIER:
|
||||
return "DeclRefExpr";
|
||||
|
||||
// 类型类型
|
||||
case SCC_AST_TYPE_BUILTIN:
|
||||
return "BuiltinType";
|
||||
case SCC_AST_TYPE_POINTER:
|
||||
return "PointerType";
|
||||
case SCC_AST_TYPE_ARRAY:
|
||||
return "ArrayType";
|
||||
case SCC_AST_TYPE_FUNCTION:
|
||||
return "FunctionType";
|
||||
case SCC_AST_TYPE_STRUCT:
|
||||
return "RecordType";
|
||||
case SCC_AST_TYPE_UNION:
|
||||
return "RecordType";
|
||||
case SCC_AST_TYPE_ENUM:
|
||||
return "EnumType";
|
||||
case SCC_AST_TYPE_TYPEDEF:
|
||||
return "TypedefType";
|
||||
|
||||
// 根节点
|
||||
case SCC_AST_TRANSLATION_UNIT:
|
||||
return "TranslationUnitDecl";
|
||||
|
||||
default:
|
||||
return "UnknownNode";
|
||||
}
|
||||
}
|
||||
|
||||
// 获取内置类型名称
|
||||
static const char *get_builtin_type_str(scc_ast_builtin_type_t type) {
|
||||
switch (type) {
|
||||
case TYPE_VOID:
|
||||
return "void";
|
||||
case TYPE_CHAR:
|
||||
return "char";
|
||||
case TYPE_SHORT:
|
||||
return "short";
|
||||
case TYPE_INT:
|
||||
return "int";
|
||||
case TYPE_LONG:
|
||||
return "long";
|
||||
case TYPE_LONG_LONG:
|
||||
return "long long";
|
||||
case TYPE_FLOAT:
|
||||
return "float";
|
||||
case TYPE_DOUBLE:
|
||||
return "double";
|
||||
case TYPE_LONG_DOUBLE:
|
||||
return "long double";
|
||||
case TYPE_BOOL:
|
||||
return "_Bool";
|
||||
case TYPE_COMPLEX_FLOAT:
|
||||
return "float _Complex";
|
||||
case TYPE_COMPLEX_DOUBLE:
|
||||
return "double _Complex";
|
||||
case TYPE_COMPLEX_LONG_DOUBLE:
|
||||
return "long double _Complex";
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
// 获取操作符字符串
|
||||
static const char *get_op_str(scc_ast_expr_op_t op) {
|
||||
switch (op) {
|
||||
case SCC_AST_OP_ASSIGN:
|
||||
return "=";
|
||||
case SCC_AST_OP_ASSIGN_ADD:
|
||||
return "+=";
|
||||
case SCC_AST_OP_ASSIGN_SUB:
|
||||
return "-=";
|
||||
case SCC_AST_OP_ASSIGN_MUL:
|
||||
return "*=";
|
||||
case SCC_AST_OP_ASSIGN_DIV:
|
||||
return "/=";
|
||||
case SCC_AST_OP_ASSIGN_MOD:
|
||||
return "%=";
|
||||
case SCC_AST_OP_ASSIGN_AND:
|
||||
return "&=";
|
||||
case SCC_AST_OP_ASSIGN_XOR:
|
||||
return "^=";
|
||||
case SCC_AST_OP_ASSIGN_OR:
|
||||
return "|=";
|
||||
case SCC_AST_OP_ASSIGN_LSHIFT:
|
||||
return "<<=";
|
||||
case SCC_AST_OP_ASSIGN_RSHIFT:
|
||||
return ">>=";
|
||||
case SCC_AST_OP_CONDITIONAL:
|
||||
return "? :";
|
||||
case SCC_AST_OP_LOGICAL_OR:
|
||||
return "||";
|
||||
case SCC_AST_OP_LOGICAL_AND:
|
||||
return "&&";
|
||||
case SCC_AST_OP_BITWISE_OR:
|
||||
return "|";
|
||||
case SCC_AST_OP_BITWISE_XOR:
|
||||
return "^";
|
||||
case SCC_AST_OP_BITWISE_AND:
|
||||
return "&";
|
||||
case SCC_AST_OP_EQUAL:
|
||||
return "==";
|
||||
case SCC_AST_OP_NOT_EQUAL:
|
||||
return "!=";
|
||||
case SCC_AST_OP_LESS:
|
||||
return "<";
|
||||
case SCC_AST_OP_GREATER:
|
||||
return ">";
|
||||
case SCC_AST_OP_LESS_EQUAL:
|
||||
return "<=";
|
||||
case SCC_AST_OP_GREATER_EQUAL:
|
||||
return ">=";
|
||||
case SCC_AST_OP_LEFT_SHIFT:
|
||||
return "<<";
|
||||
case SCC_AST_OP_RIGHT_SHIFT:
|
||||
return ">>";
|
||||
case SCC_AST_OP_ADD:
|
||||
return "+";
|
||||
case SCC_AST_OP_SUB:
|
||||
return "-";
|
||||
case SCC_AST_OP_MUL:
|
||||
return "*";
|
||||
case SCC_AST_OP_DIV:
|
||||
return "/";
|
||||
case SCC_AST_OP_MOD:
|
||||
return "%";
|
||||
case SCC_AST_OP_UNARY_PLUS:
|
||||
return "+";
|
||||
case SCC_AST_OP_UNARY_MINUS:
|
||||
return "-";
|
||||
case SCC_AST_OP_ADDRESS_OF:
|
||||
return "&";
|
||||
case SCC_AST_OP_INDIRECTION:
|
||||
return "*";
|
||||
case SCC_AST_OP_BITWISE_NOT:
|
||||
return "~";
|
||||
case SCC_AST_OP_LOGICAL_NOT:
|
||||
return "!";
|
||||
case SCC_AST_OP_PREFIX_INCREMENT:
|
||||
return "++";
|
||||
case SCC_AST_OP_PREFIX_DECREMENT:
|
||||
return "--";
|
||||
case SCC_AST_OP_POSTFIX_INCREMENT:
|
||||
return "++";
|
||||
case SCC_AST_OP_POSTFIX_DECREMENT:
|
||||
return "--";
|
||||
case SCC_AST_OP_MEMBER_ACCESS:
|
||||
return ".";
|
||||
case SCC_AST_OP_PTR_MEMBER_ACCESS:
|
||||
return "->";
|
||||
default:
|
||||
return "<op>";
|
||||
}
|
||||
}
|
||||
|
||||
// 通用的开始节点打印函数
|
||||
static inline void start_node_dump(scc_ast_node_t *node,
|
||||
scc_ast_dump_ctx_t *ctx) {
|
||||
print_indent(ctx);
|
||||
PRINT_NODE_TYPE(ctx, node);
|
||||
}
|
||||
|
||||
// 通用的结束节点打印函数
|
||||
static inline void end_node_dump(scc_ast_dump_ctx_t *ctx) { scc_printf("\n"); }
|
||||
|
||||
// 通用的递归转储辅助函数
|
||||
static inline void dump_child_node(scc_ast_node_t *child,
|
||||
scc_ast_dump_ctx_t *ctx, cbool is_last) {
|
||||
if (!child)
|
||||
return;
|
||||
|
||||
ctx->depth++;
|
||||
ensure_context_depth(ctx, ctx->depth);
|
||||
ctx->is_last_child[ctx->depth - 1] = is_last;
|
||||
|
||||
scc_ast_dump_node(child, ctx);
|
||||
|
||||
ctx->depth--;
|
||||
}
|
||||
|
||||
// 用于构建复合类型名称的宏
|
||||
#define BUILD_TYPE_NAME(ctx, prefix, name) \
|
||||
do { \
|
||||
if (ctx->use_color) { \
|
||||
scc_printf("%s'%s%s%s'%s", ctx->value_color, prefix, name, \
|
||||
ctx->reset_color, ctx->reset_color); \
|
||||
} else { \
|
||||
scc_printf("'%s%s'", prefix, name); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// 递归转储类型
|
||||
static void dump_type_impl(scc_ast_type_t *type, scc_ast_dump_ctx_t *ctx) {
|
||||
if (!type)
|
||||
return;
|
||||
|
||||
start_node_dump(&type->base, ctx);
|
||||
|
||||
// 根据类型输出特定信息
|
||||
switch (type->base.type) {
|
||||
case SCC_AST_TYPE_BUILTIN:
|
||||
PRINT_QUOTED_VALUE(ctx, get_builtin_type_str(type->builtin.builtin));
|
||||
break;
|
||||
case SCC_AST_TYPE_POINTER:
|
||||
if (type->pointer.pointee &&
|
||||
type->pointer.pointee->base.type == SCC_AST_TYPE_BUILTIN) {
|
||||
const char *base_type =
|
||||
get_builtin_type_str(type->pointer.pointee->builtin.builtin);
|
||||
if (ctx->use_color) {
|
||||
scc_printf("%s'%s *'%s", ctx->value_color, base_type,
|
||||
ctx->reset_color);
|
||||
} else {
|
||||
scc_printf("'%s *'", base_type);
|
||||
}
|
||||
} else {
|
||||
PRINT_QUOTED_VALUE(ctx, "pointer");
|
||||
}
|
||||
break;
|
||||
case SCC_AST_TYPE_ARRAY:
|
||||
PRINT_QUOTED_VALUE(ctx, "array");
|
||||
break;
|
||||
case SCC_AST_TYPE_FUNCTION:
|
||||
PRINT_QUOTED_VALUE(ctx, "function");
|
||||
break;
|
||||
case SCC_AST_TYPE_STRUCT:
|
||||
if (type->record.name) {
|
||||
BUILD_TYPE_NAME(ctx, "struct ", type->record.name);
|
||||
} else {
|
||||
PRINT_QUOTED_VALUE(ctx, "anonymous struct");
|
||||
}
|
||||
break;
|
||||
case SCC_AST_TYPE_UNION:
|
||||
if (type->record.name) {
|
||||
BUILD_TYPE_NAME(ctx, "union ", type->record.name);
|
||||
} else {
|
||||
PRINT_QUOTED_VALUE(ctx, "anonymous union");
|
||||
}
|
||||
break;
|
||||
case SCC_AST_TYPE_ENUM:
|
||||
if (type->enumeration.name) {
|
||||
BUILD_TYPE_NAME(ctx, "enum ", type->enumeration.name);
|
||||
} else {
|
||||
PRINT_QUOTED_VALUE(ctx, "anonymous enum");
|
||||
}
|
||||
break;
|
||||
case SCC_AST_TYPE_TYPEDEF:
|
||||
PRINT_QUOTED_VALUE(ctx, type->typedef_type.name);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
end_node_dump(ctx);
|
||||
|
||||
// 递归转储子节点
|
||||
switch (type->base.type) {
|
||||
case SCC_AST_TYPE_POINTER:
|
||||
dump_child_node((scc_ast_node_t *)type->pointer.pointee, ctx, true);
|
||||
break;
|
||||
case SCC_AST_TYPE_ARRAY:
|
||||
dump_child_node((scc_ast_node_t *)type->array.element, ctx,
|
||||
type->array.size == NULL);
|
||||
if (type->array.size) {
|
||||
dump_child_node((scc_ast_node_t *)type->array.size, ctx, true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 递归转储表达式
|
||||
static void dump_expr_impl(scc_ast_expr_t *expr, scc_ast_dump_ctx_t *ctx) {
|
||||
if (!expr)
|
||||
return;
|
||||
|
||||
start_node_dump(&expr->base, ctx);
|
||||
|
||||
// 根据表达式类型输出特定信息
|
||||
switch (expr->base.type) {
|
||||
case SCC_AST_EXPR_BINARY:
|
||||
PRINT_QUOTED_VALUE(ctx, get_op_str(expr->binary.op));
|
||||
break;
|
||||
case SCC_AST_EXPR_UNARY:
|
||||
PRINT_QUOTED_VALUE(ctx, get_op_str(expr->unary.op));
|
||||
break;
|
||||
case SCC_AST_EXPR_INT_LITERAL:
|
||||
PRINT_VALUE(ctx, " %lld", expr->literal.value.i);
|
||||
break;
|
||||
case SCC_AST_EXPR_FLOAT_LITERAL:
|
||||
PRINT_VALUE(ctx, " %f", expr->literal.value.f);
|
||||
break;
|
||||
case SCC_AST_EXPR_CHAR_LITERAL:
|
||||
PRINT_VALUE(ctx, " '%c'", (char)expr->literal.value.ch);
|
||||
break;
|
||||
case SCC_AST_EXPR_STRING_LITERAL:
|
||||
PRINT_VALUE(ctx, " \"%s\"", expr->literal.value.cstr.data);
|
||||
break;
|
||||
case SCC_AST_EXPR_IDENTIFIER:
|
||||
if (expr->identifier.name) {
|
||||
PRINT_QUOTED_VALUE(ctx, expr->identifier.name);
|
||||
}
|
||||
break;
|
||||
case SCC_AST_EXPR_SIZE_OF:
|
||||
case SCC_AST_EXPR_ALIGN_OF:
|
||||
PRINT_QUOTED_VALUE(ctx, (expr->base.type == SCC_AST_EXPR_SIZE_OF)
|
||||
? "sizeof"
|
||||
: "alignof");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
end_node_dump(ctx);
|
||||
|
||||
// 使用辅助函数处理子节点转储
|
||||
switch (expr->base.type) {
|
||||
case SCC_AST_EXPR_BINARY:
|
||||
dump_child_node((scc_ast_node_t *)expr->binary.lhs, ctx, false);
|
||||
dump_child_node((scc_ast_node_t *)expr->binary.rhs, ctx, true);
|
||||
break;
|
||||
|
||||
case SCC_AST_EXPR_UNARY:
|
||||
dump_child_node((scc_ast_node_t *)expr->unary.operand, ctx, true);
|
||||
break;
|
||||
|
||||
case SCC_AST_EXPR_COND:
|
||||
dump_child_node((scc_ast_node_t *)expr->cond.cond, ctx, false);
|
||||
dump_child_node((scc_ast_node_t *)expr->cond.then_expr, ctx, false);
|
||||
dump_child_node((scc_ast_node_t *)expr->cond.else_expr, ctx, true);
|
||||
break;
|
||||
|
||||
case SCC_AST_EXPR_CALL:
|
||||
dump_child_node((scc_ast_node_t *)expr->call.callee, ctx, false);
|
||||
// 转储参数
|
||||
for (size_t i = 0; i < expr->call.args.size; i++) {
|
||||
dump_child_node((scc_ast_node_t *)expr->call.args.data[i], ctx,
|
||||
i == expr->call.args.size - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCC_AST_EXPR_ARRAY_SUBSCRIPT:
|
||||
dump_child_node((scc_ast_node_t *)expr->subscript.array, ctx, false);
|
||||
dump_child_node((scc_ast_node_t *)expr->subscript.index, ctx, true);
|
||||
break;
|
||||
|
||||
case SCC_AST_EXPR_MEMBER:
|
||||
case SCC_AST_EXPR_PTR_MEMBER:
|
||||
dump_child_node((scc_ast_node_t *)expr->member.base, ctx, false);
|
||||
// 打印成员访问信息
|
||||
print_indent(ctx);
|
||||
PRINT_COLORED(ctx, node_color, "Member [\"%s\"]",
|
||||
expr->member.member_name);
|
||||
scc_printf("\n");
|
||||
break;
|
||||
|
||||
case SCC_AST_EXPR_CAST:
|
||||
dump_child_node((scc_ast_node_t *)expr->cast.type, ctx, false);
|
||||
dump_child_node((scc_ast_node_t *)expr->cast.expr, ctx, true);
|
||||
break;
|
||||
|
||||
case SCC_AST_EXPR_SIZE_OF:
|
||||
case SCC_AST_EXPR_ALIGN_OF:
|
||||
if (expr->attr_of.expr) {
|
||||
dump_child_node((scc_ast_node_t *)expr->attr_of.expr, ctx, true);
|
||||
} else if (expr->attr_of.type) {
|
||||
dump_child_node((scc_ast_node_t *)expr->attr_of.type, ctx, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCC_AST_EXPR_COMPOUND_LITERAL:
|
||||
dump_child_node((scc_ast_node_t *)expr->compound_literal.type, ctx,
|
||||
false);
|
||||
// 初始化列表
|
||||
for (size_t i = 0; i < expr->compound_literal.init_list.size; i++) {
|
||||
dump_child_node(
|
||||
(scc_ast_node_t *)expr->compound_literal.init_list.data[i], ctx,
|
||||
i == expr->compound_literal.init_list.size - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 递归转储语句
|
||||
static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_ast_dump_ctx_t *ctx) {
|
||||
if (!stmt)
|
||||
return;
|
||||
|
||||
start_node_dump(&stmt->base, ctx);
|
||||
|
||||
// 根据语句类型输出特定信息
|
||||
switch (stmt->base.type) {
|
||||
case SCC_AST_STMT_IF:
|
||||
scc_printf("\n"); // if语句总是换行显示子节点
|
||||
dump_child_node((scc_ast_node_t *)stmt->if_stmt.cond, ctx, false);
|
||||
dump_child_node((scc_ast_node_t *)stmt->if_stmt.then_stmt, ctx,
|
||||
!stmt->if_stmt.opt_else_stmt);
|
||||
if (stmt->if_stmt.opt_else_stmt) {
|
||||
dump_child_node((scc_ast_node_t *)stmt->if_stmt.opt_else_stmt, ctx,
|
||||
true);
|
||||
}
|
||||
return;
|
||||
case SCC_AST_STMT_WHILE:
|
||||
scc_printf("\n"); // 循环和switch语句换行显示子节点
|
||||
dump_child_node((scc_ast_node_t *)stmt->while_stmt.cond, ctx, false);
|
||||
dump_child_node((scc_ast_node_t *)stmt->while_stmt.body, ctx, true);
|
||||
return;
|
||||
case SCC_AST_STMT_DO_WHILE:
|
||||
scc_printf("\n"); // 循环和switch语句换行显示子节点
|
||||
dump_child_node((scc_ast_node_t *)stmt->do_while_stmt.body, ctx, false);
|
||||
dump_child_node((scc_ast_node_t *)stmt->do_while_stmt.cond, ctx, true);
|
||||
return;
|
||||
case SCC_AST_STMT_SWITCH:
|
||||
scc_printf("\n"); // 循环和switch语句换行显示子节点
|
||||
dump_child_node((scc_ast_node_t *)stmt->switch_stmt.cond, ctx, false);
|
||||
dump_child_node((scc_ast_node_t *)stmt->switch_stmt.body, ctx, true);
|
||||
return;
|
||||
case SCC_AST_STMT_FOR:
|
||||
scc_printf("\n"); // for语句换行显示子节点
|
||||
if (stmt->for_stmt.init) {
|
||||
dump_child_node((scc_ast_node_t *)stmt->for_stmt.init, ctx, false);
|
||||
}
|
||||
if (stmt->for_stmt.cond) {
|
||||
dump_child_node((scc_ast_node_t *)stmt->for_stmt.cond, ctx, false);
|
||||
}
|
||||
if (stmt->for_stmt.iter) {
|
||||
dump_child_node((scc_ast_node_t *)stmt->for_stmt.iter, ctx, false);
|
||||
}
|
||||
dump_child_node((scc_ast_node_t *)stmt->for_stmt.body, ctx, true);
|
||||
return;
|
||||
case SCC_AST_STMT_RETURN:
|
||||
if (stmt->return_stmt.expr) {
|
||||
scc_printf("\n");
|
||||
dump_child_node((scc_ast_node_t *)stmt->return_stmt.expr, ctx,
|
||||
true);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case SCC_AST_STMT_GOTO:
|
||||
if (stmt->goto_stmt.label) {
|
||||
PRINT_VALUE(ctx, " Label: %s", stmt->goto_stmt.label);
|
||||
}
|
||||
break;
|
||||
case SCC_AST_STMT_LABEL:
|
||||
if (stmt->label_stmt.label) {
|
||||
PRINT_VALUE(ctx, " %s", stmt->label_stmt.label);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
end_node_dump(ctx);
|
||||
|
||||
// 递归转储其他子节点
|
||||
switch (stmt->base.type) {
|
||||
case SCC_AST_STMT_COMPOUND:
|
||||
for (size_t i = 0; i < stmt->compound.block_items.size; i++) {
|
||||
scc_ast_node_t *item =
|
||||
(scc_ast_node_t *)stmt->compound.block_items.data[i];
|
||||
dump_child_node(item, ctx,
|
||||
i == stmt->compound.block_items.size - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCC_AST_STMT_EXPR:
|
||||
if (stmt->expr.expr) {
|
||||
dump_child_node((scc_ast_node_t *)stmt->expr.expr, ctx, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCC_AST_STMT_CASE:
|
||||
dump_child_node((scc_ast_node_t *)stmt->case_stmt.expr, ctx, false);
|
||||
dump_child_node((scc_ast_node_t *)stmt->case_stmt.stmt, ctx, true);
|
||||
break;
|
||||
|
||||
case SCC_AST_STMT_DEFAULT:
|
||||
dump_child_node((scc_ast_node_t *)stmt->default_stmt.stmt, ctx, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 递归转储声明
|
||||
static void dump_decl_impl(scc_ast_decl_t *decl, scc_ast_dump_ctx_t *ctx) {
|
||||
if (!decl)
|
||||
return;
|
||||
|
||||
start_node_dump(&decl->base, ctx);
|
||||
|
||||
// 根据声明类型输出特定信息
|
||||
switch (decl->base.type) {
|
||||
case SCC_AST_DECL_VAR:
|
||||
if (decl->var.name) {
|
||||
PRINT_QUOTED_VALUE(ctx, decl->var.name);
|
||||
}
|
||||
break;
|
||||
case SCC_AST_DECL_FUNC:
|
||||
if (decl->func.name) {
|
||||
PRINT_QUOTED_VALUE(ctx, decl->func.name);
|
||||
}
|
||||
break;
|
||||
case SCC_AST_DECL_PARAM:
|
||||
if (decl->param.name) {
|
||||
PRINT_QUOTED_VALUE(ctx, decl->param.name);
|
||||
}
|
||||
break;
|
||||
case SCC_AST_DECL_STRUCT:
|
||||
if (decl->record.name) {
|
||||
PRINT_QUOTED_VALUE(ctx, decl->record.name);
|
||||
}
|
||||
break;
|
||||
case SCC_AST_DECL_UNION:
|
||||
if (decl->record.name) {
|
||||
PRINT_QUOTED_VALUE(ctx, decl->record.name);
|
||||
}
|
||||
break;
|
||||
case SCC_AST_DECL_ENUM:
|
||||
if (decl->enumeration.name) {
|
||||
PRINT_QUOTED_VALUE(ctx, decl->enumeration.name);
|
||||
}
|
||||
break;
|
||||
case SCC_AST_DECL_TYPEDEF:
|
||||
if (decl->typedef_decl.name) {
|
||||
PRINT_QUOTED_VALUE(ctx, decl->typedef_decl.name);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
end_node_dump(ctx);
|
||||
|
||||
// 递归转储子节点
|
||||
switch (decl->base.type) {
|
||||
case SCC_AST_DECL_VAR:
|
||||
if (decl->var.type) {
|
||||
dump_child_node((scc_ast_node_t *)decl->var.type, ctx,
|
||||
decl->var.init == NULL);
|
||||
if (decl->var.init) {
|
||||
dump_child_node((scc_ast_node_t *)decl->var.init, ctx, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SCC_AST_DECL_FUNC:
|
||||
if (decl->func.type) {
|
||||
dump_child_node((scc_ast_node_t *)decl->func.type, ctx,
|
||||
decl->func.body == NULL);
|
||||
if (decl->func.body) {
|
||||
dump_child_node((scc_ast_node_t *)decl->func.body, ctx, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SCC_AST_DECL_PARAM:
|
||||
if (decl->param.type) {
|
||||
dump_child_node((scc_ast_node_t *)decl->param.type, ctx, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCC_AST_DECL_STRUCT:
|
||||
case SCC_AST_DECL_UNION:
|
||||
for (size_t i = 0; i < decl->record.fields.size; i++) {
|
||||
dump_child_node((scc_ast_node_t *)decl->record.fields.data[i], ctx,
|
||||
i == decl->record.fields.size - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCC_AST_DECL_ENUM:
|
||||
for (size_t i = 0; i < decl->enumeration.enumerators.size; i++) {
|
||||
dump_child_node(
|
||||
(scc_ast_node_t *)decl->enumeration.enumerators.data[i], ctx,
|
||||
i == decl->enumeration.enumerators.size - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCC_AST_DECL_TYPEDEF:
|
||||
if (decl->typedef_decl.type) {
|
||||
dump_child_node((scc_ast_node_t *)decl->typedef_decl.type, ctx,
|
||||
true);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 递归转储翻译单元
|
||||
static void dump_unit_impl(scc_ast_translation_unit_t *unit,
|
||||
scc_ast_dump_ctx_t *ctx) {
|
||||
if (!unit)
|
||||
return;
|
||||
|
||||
start_node_dump(&unit->base, ctx);
|
||||
scc_printf("\n");
|
||||
|
||||
for (size_t i = 0; i < unit->declarations.size; i++) {
|
||||
dump_child_node((scc_ast_node_t *)unit->declarations.data[i], ctx,
|
||||
i == unit->declarations.size - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 实现上下文管理函数
|
||||
void scc_ast_dump_ctx_init(scc_ast_dump_ctx_t *ctx, cbool use_color) {
|
||||
scc_memset(ctx, 0, sizeof(*ctx));
|
||||
ctx->use_color = use_color;
|
||||
ctx->node_color = use_color ? DEFAULT_NODE_COLOR : "";
|
||||
ctx->value_color = use_color ? DEFAULT_VALUE_COLOR : "";
|
||||
ctx->branch_color = use_color ? DEFAULT_BRANCH_COLOR : "";
|
||||
ctx->reset_color = use_color ? DEFAULT_RESET_COLOR : "";
|
||||
|
||||
ensure_context_depth(ctx, 0);
|
||||
ctx->is_last_child[0] = true;
|
||||
}
|
||||
|
||||
void scc_ast_dump_ctx_drop(scc_ast_dump_ctx_t *ctx) {
|
||||
if (ctx->is_last_child) {
|
||||
scc_free(ctx->is_last_child);
|
||||
ctx->is_last_child = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void scc_ast_dump_node(scc_ast_node_t *node, scc_ast_dump_ctx_t *ctx) {
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
if (SCC_AST_IS_A(scc_ast_expr_t, node)) {
|
||||
dump_expr_impl(SCC_AST_CAST_TO(scc_ast_expr_t, node), ctx);
|
||||
} else if (SCC_AST_IS_A(scc_ast_stmt_t, node)) {
|
||||
dump_stmt_impl(SCC_AST_CAST_TO(scc_ast_stmt_t, node), ctx);
|
||||
} else if (SCC_AST_IS_A(scc_ast_decl_t, node)) {
|
||||
dump_decl_impl(SCC_AST_CAST_TO(scc_ast_decl_t, node), ctx);
|
||||
} else if (SCC_AST_IS_A(scc_ast_type_t, node)) {
|
||||
dump_type_impl(SCC_AST_CAST_TO(scc_ast_type_t, node), ctx);
|
||||
} else if (SCC_AST_IS_A(scc_ast_translation_unit_t, node)) {
|
||||
dump_unit_impl(SCC_AST_CAST_TO(scc_ast_translation_unit_t, node), ctx);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user