From 35a704a1cb86243ac4f3f9c2da7cdd48661f594d Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Sat, 21 Mar 2026 10:33:17 +0800 Subject: [PATCH] =?UTF-8?q?refactor(ast):=20=E7=BB=9F=E4=B8=80=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E7=B1=BB=E5=9E=8B=E7=BB=93=E6=9E=84=E5=B9=B6=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E6=88=90=E5=91=98=E8=AE=BF=E9=97=AE=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了枚举类型的独立结构定义,统一使用record结构 - 移除了成员访问操作符SCC_AST_OP_MEMBER_ACCESS和SCC_AST_OP_PTR_MEMBER_ACCESS - 更新了for循环语句中init字段的类型从scc_ast_type_t*到scc_ast_node_t* - 修改了声明初始化函数以支持统一的记录类型处理 fix(ast2ir): 完善二元表达式处理和for循环代码生成 - 重构了赋值操作符的处理逻辑,通过临时表达式实现复合赋值 - 添加了对for循环语句的完整IR代码生成功能 - 修复了if-else语句中错误的基本块跳转问题 - 改进了标识符未找到时的错误提示信息 chore: 清理代码和修复潜在问题 - 移除了未使用的自动标签生成功能 - 统一了IR基本块标签格式化输出 - 修复了机器码生成中的寄存器存储控制流问题 - 改进了词法分析器中十六进制数字的处理逻辑 --- libs/ast/include/ast_def.h | 15 +- libs/ast/include/scc_ast.h | 54 +- libs/ast/src/ast_dump.c | 29 +- libs/ast2ir/src/scc_ast2ir.c | 230 ++-- libs/ir/src/ir_builder.c | 25 +- libs/ir/src/ir_dump.c | 17 +- libs/ir2mcode/src/ir2amd64.c | 6 +- libs/lexer/src/lexer.c | 11 +- libs/lexer/tests/test_lexer.c | 11 +- libs/parser/src/parse_decl.c | 7 + libs/parser/src/parse_stmt.c | 6 +- libs/parser/src/parse_type.c | 86 +- libs/parser/src/scc_sema.c | 67 +- libs/parser/tests/parser_test.h | 2 +- libs/parser/tests/test_parse_type.c | 91 +- libs/parser/tests/test_parse_unit.c | 869 +++++++++++++ libs/parser/tests/test_parser_unit.c | 1806 -------------------------- libs/pproc/include/pproc_macro.h | 4 + libs/pproc/src/pproc_expand.c | 32 +- libs/pproc/src/scc_pproc.c | 22 +- libs/sccf/include/sccf_utils.h | 3 +- libs/sstream/src/scc_sstream.c | 6 +- libs/target/pe/include/scc_pe_def.h | 17 +- src/config.h | 13 + src/main.c | 1 + 25 files changed, 1335 insertions(+), 2095 deletions(-) create mode 100644 libs/parser/tests/test_parse_unit.c delete mode 100644 libs/parser/tests/test_parser_unit.c diff --git a/libs/ast/include/ast_def.h b/libs/ast/include/ast_def.h index 8ac74f6..8b54a77 100644 --- a/libs/ast/include/ast_def.h +++ b/libs/ast/include/ast_def.h @@ -186,10 +186,6 @@ struct scc_ast_type { const char *name; scc_ast_decl_t *decl; // can be null } record; - struct { - const char *name; - scc_ast_decl_t *decl; // can be null - } enumeration; struct { const char *name; scc_ast_decl_t *decl; @@ -255,9 +251,6 @@ typedef enum scc_ast_expr_op { SCC_AST_OP_PREFIX_DECREMENT, // -- (前缀) SCC_AST_OP_POSTFIX_INCREMENT, // ++ (后缀) SCC_AST_OP_POSTFIX_DECREMENT, // -- (后缀) - /* 成员访问 */ - SCC_AST_OP_MEMBER_ACCESS, // . - SCC_AST_OP_PTR_MEMBER_ACCESS, // -> } scc_ast_expr_op_t; typedef enum { @@ -371,7 +364,7 @@ struct scc_ast_stmt { } while_stmt; // for 语句 struct { - scc_ast_type_t *init; // expr or decl or null + scc_ast_node_t *init; // expr or decl or null scc_ast_expr_t *cond; // 可为 null scc_ast_expr_t *incr; // 可为 null scc_ast_stmt_t *body; @@ -435,14 +428,10 @@ struct scc_ast_decl { struct { scc_ast_type_t *type; } param; - // 结构体/联合声明 + // 结构体/联合/枚举声明 struct { scc_ast_decl_vec_t fields; } record; - // 枚举声明 - struct { - scc_ast_expr_vec_t enumerators; - } enumeration; // typedef 声明 struct { scc_ast_type_t *type; diff --git a/libs/ast/include/scc_ast.h b/libs/ast/include/scc_ast.h index 03e6b5b..9b3221c 100644 --- a/libs/ast/include/scc_ast.h +++ b/libs/ast/include/scc_ast.h @@ -82,14 +82,14 @@ static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl, decl->param.type = type; } -// name and fields can be null -static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl, - const char *name, - scc_ast_decl_vec_t *fields_move, - scc_pos_t loc) { +static inline void _scc_ast_decl_record_init(scc_ast_decl_t *decl, + scc_ast_node_type_t type, + const char *name, + scc_ast_decl_vec_t *fields_move, + scc_pos_t loc) { Assert(decl != null); decl->base.loc = loc; - decl->base.type = SCC_AST_DECL_STRUCT; + decl->base.type = type; decl->name = name; if (fields_move == null) { scc_vec_init(decl->record.fields); @@ -99,38 +99,29 @@ static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl, } } +// name and fields can be null +static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl, + const char *name, + scc_ast_decl_vec_t *fields_move, + scc_pos_t loc) { + _scc_ast_decl_record_init(decl, SCC_AST_DECL_STRUCT, name, fields_move, + loc); +} + // name and fields can be null static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl, const char *name, scc_ast_decl_vec_t *fields_move, scc_pos_t loc) { - Assert(decl != null); - decl->base.loc = loc; - decl->base.type = SCC_AST_DECL_UNION; - decl->name = name; - if (fields_move == null) { - scc_vec_init(decl->record.fields); - } else { - decl->record.fields = *fields_move; - scc_vec_init(*fields_move); - } + _scc_ast_decl_record_init(decl, SCC_AST_DECL_UNION, name, fields_move, loc); } // name and fields can be null static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl, const char *name, - scc_ast_expr_vec_t *fields_move, + scc_ast_decl_vec_t *fields_move, scc_pos_t loc) { - Assert(decl != null); - decl->base.loc = loc; - decl->base.type = SCC_AST_DECL_ENUM; - decl->name = name; - if (fields_move == null) { - scc_vec_init(decl->enumeration.enumerators); - } else { - decl->enumeration.enumerators = *fields_move; - scc_vec_init(*fields_move); - } + _scc_ast_decl_record_init(decl, SCC_AST_DECL_ENUM, name, fields_move, loc); } static inline void scc_ast_decl_typedef_init(scc_ast_decl_t *decl, @@ -205,7 +196,7 @@ static inline void scc_ast_stmt_do_while_init(scc_ast_stmt_t *stmt, // FIXME static inline void scc_ast_stmt_for_init(scc_ast_stmt_t *stmt, - scc_ast_type_t *init, + scc_ast_node_t *init, scc_ast_expr_t *cond, scc_ast_expr_t *incr, scc_ast_stmt_t *body, scc_pos_t loc) { @@ -591,12 +582,7 @@ static inline void scc_ast_type_union_init(scc_ast_type_t *type, static inline void scc_ast_type_enum_init(scc_ast_type_t *type, const char *name, scc_ast_decl_t *decl, scc_pos_t loc) { - Assert(type != null); - type->base.loc = loc; - type->base.type = SCC_AST_TYPE_ENUM; - type->quals = (scc_ast_decl_specifier_t){0}; // FIXME - type->enumeration.name = name; - type->enumeration.decl = decl; + _scc_ast_type_record_init(type, SCC_AST_TYPE_ENUM, name, decl, loc); } static inline void scc_ast_type_typedef_init(scc_ast_type_t *type, diff --git a/libs/ast/src/ast_dump.c b/libs/ast/src/ast_dump.c index 1e83304..4c42c8d 100644 --- a/libs/ast/src/ast_dump.c +++ b/libs/ast/src/ast_dump.c @@ -195,10 +195,6 @@ static const char *get_op_str(scc_ast_expr_op_t op) { 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 ""; } @@ -300,8 +296,8 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) { } break; case SCC_AST_TYPE_ENUM: - if (type->enumeration.name) { - BUILD_TYPE_NAME(ctx, "enum ", type->enumeration.name); + if (type->record.name) { + BUILD_TYPE_NAME(ctx, "enum ", type->record.name); } else { PRINT_QUOTED_VALUE(ctx, "anonymous enum"); } @@ -327,17 +323,6 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) { dump_child_node((scc_ast_node_t *)type->array.size, ctx, true); } break; - case SCC_AST_TYPE_STRUCT: - if (type->enumeration.decl) { - dump_child_node((scc_ast_node_t *)type->enumeration.decl, ctx, - true); - } - break; - case SCC_AST_TYPE_ENUM: - if (type->record.decl) { - dump_child_node((scc_ast_node_t *)type->record.decl, ctx, true); - } - break; case SCC_AST_TYPE_FUNCTION: scc_vec_push(ctx->stack, false); scc_tree_print_indent(ctx); @@ -585,6 +570,7 @@ static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_ctx_t *ctx) { case SCC_AST_STMT_BREAK: case SCC_AST_STMT_CONTINUE: + end_node_dump(ctx); break; case SCC_AST_STMT_DEFAULT: @@ -645,6 +631,7 @@ static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_ctx_t *ctx) { case SCC_AST_DECL_STRUCT: case SCC_AST_DECL_UNION: + case SCC_AST_DECL_ENUM: scc_vec_foreach(decl->record.fields, i) { dump_child_node( (scc_ast_node_t *)scc_vec_at(decl->record.fields, i), ctx, @@ -652,14 +639,6 @@ static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_ctx_t *ctx) { } break; - case SCC_AST_DECL_ENUM: - scc_vec_foreach(decl->enumeration.enumerators, i) { - dump_child_node( - (scc_ast_node_t *)scc_vec_at(decl->enumeration.enumerators, i), - ctx, i + 1 == scc_vec_size(decl->enumeration.enumerators)); - } - break; - case SCC_AST_DECL_TYPEDEF: if (decl->typedef_decl.type) { dump_child_node((scc_ast_node_t *)decl->typedef_decl.type, ctx, diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index d3d40f4..24b6a24 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -99,105 +99,123 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, return 0; } + cbool is_assign = true; switch (expr->base.type) { case SCC_AST_EXPR_BINARY: { + scc_ast_expr_t tmp_expr; scc_ir_node_ref_t lhs, rhs; - cbool is_assign = false; switch (expr->binary.op) { - case SCC_AST_OP_ASSIGN: // = - case SCC_AST_OP_ASSIGN_ADD: // += - case SCC_AST_OP_ASSIGN_SUB: // -= - case SCC_AST_OP_ASSIGN_MUL: // *= - case SCC_AST_OP_ASSIGN_DIV: // /= - case SCC_AST_OP_ASSIGN_MOD: // %= - case SCC_AST_OP_ASSIGN_AND: // &= - case SCC_AST_OP_ASSIGN_XOR: // ^= - case SCC_AST_OP_ASSIGN_OR: // |= + case SCC_AST_OP_ASSIGN: // = + rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false); + break; + case SCC_AST_OP_ASSIGN_ADD: // += + scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_ADD, + expr->binary.lhs, expr->binary.rhs, + expr->base.loc); + rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); + break; + case SCC_AST_OP_ASSIGN_SUB: // -= + scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_SUB, + expr->binary.lhs, expr->binary.rhs, + expr->base.loc); + rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); + break; + case SCC_AST_OP_ASSIGN_MUL: // *= + scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_MUL, + expr->binary.lhs, expr->binary.rhs, + expr->base.loc); + rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); + break; + case SCC_AST_OP_ASSIGN_DIV: // /= + scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_DIV, + expr->binary.lhs, expr->binary.rhs, + expr->base.loc); + rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); + break; + case SCC_AST_OP_ASSIGN_MOD: // %= + scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_MOD, + expr->binary.lhs, expr->binary.rhs, + expr->base.loc); + rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); + break; + case SCC_AST_OP_ASSIGN_AND: // &= + scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_BITWISE_AND, + expr->binary.lhs, expr->binary.rhs, + expr->base.loc); + rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); + break; + case SCC_AST_OP_ASSIGN_XOR: // ^= + scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_BITWISE_XOR, + expr->binary.lhs, expr->binary.rhs, + expr->base.loc); + rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); + break; + case SCC_AST_OP_ASSIGN_OR: // |= + scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_BITWISE_OR, + expr->binary.lhs, expr->binary.rhs, + expr->base.loc); + rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); + break; case SCC_AST_OP_ASSIGN_LSHIFT: // <<= + scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_LEFT_SHIFT, + expr->binary.lhs, expr->binary.rhs, + expr->base.loc); + rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); + break; case SCC_AST_OP_ASSIGN_RSHIFT: // >>= - is_assign = true; + scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_RIGHT_SHIFT, + expr->binary.lhs, expr->binary.rhs, + expr->base.loc); + rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; default: is_assign = false; break; } - lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, is_assign); - rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false); + if (is_assign) { + lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, true); + return scc_ir_builder_store(&ctx->builder, lhs, rhs); + } + rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false); + lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, false); // 映射操作符 scc_ir_op_type_t op; switch (expr->binary.op) { /* clang-format off */ - case SCC_AST_OP_ADD: op = SCC_IR_OP_ADD; break; - case SCC_AST_OP_SUB: op = SCC_IR_OP_SUB; break; - case SCC_AST_OP_MUL: op = SCC_IR_OP_MUL; break; - case SCC_AST_OP_DIV: op = SCC_IR_OP_DIV; break; - case SCC_AST_OP_MOD: op = SCC_IR_OP_MOD; break; - case SCC_AST_OP_LOGICAL_AND: op = SCC_IR_OP_AND; break; - case SCC_AST_OP_LOGICAL_OR: op = SCC_IR_OP_OR; break; - case SCC_AST_OP_BITWISE_XOR: op = SCC_IR_OP_XOR; break; - case SCC_AST_OP_LEFT_SHIFT: op = SCC_IR_OP_SHL; break; - case SCC_AST_OP_RIGHT_SHIFT: op = SCC_IR_OP_SHR; break; - case SCC_AST_OP_EQUAL: op = SCC_IR_OP_EQ; break; - case SCC_AST_OP_NOT_EQUAL: op = SCC_IR_OP_NEQ; break; - case SCC_AST_OP_LESS: op = SCC_IR_OP_LT; break; - case SCC_AST_OP_LESS_EQUAL: op = SCC_IR_OP_LE; break; - case SCC_AST_OP_GREATER: op = SCC_IR_OP_GT; break; - case SCC_AST_OP_GREATER_EQUAL: op = SCC_IR_OP_GE; break; - case SCC_AST_OP_ASSIGN: { - return scc_ir_builder_store(&ctx->builder, lhs, rhs); + case SCC_AST_OP_ADD: op = SCC_IR_OP_ADD; break; + case SCC_AST_OP_SUB: op = SCC_IR_OP_SUB; break; + case SCC_AST_OP_MUL: op = SCC_IR_OP_MUL; break; + case SCC_AST_OP_DIV: op = SCC_IR_OP_DIV; break; + case SCC_AST_OP_MOD: op = SCC_IR_OP_MOD; break; + case SCC_AST_OP_BITWISE_AND: op = SCC_IR_OP_AND; break; + case SCC_AST_OP_BITWISE_OR: op = SCC_IR_OP_OR; break; + case SCC_AST_OP_BITWISE_XOR: op = SCC_IR_OP_XOR; break; + case SCC_AST_OP_LEFT_SHIFT: op = SCC_IR_OP_SHL; break; + case SCC_AST_OP_RIGHT_SHIFT: { + op = SCC_IR_OP_SHR; + // FIXME op = SCC_IR_OP_SAR; + break; } - case SCC_AST_OP_ASSIGN_ADD: + case SCC_AST_OP_EQUAL: op = SCC_IR_OP_EQ; break; + case SCC_AST_OP_NOT_EQUAL: op = SCC_IR_OP_NEQ; break; + case SCC_AST_OP_LESS: op = SCC_IR_OP_LT; break; + case SCC_AST_OP_LESS_EQUAL: op = SCC_IR_OP_LE; break; + case SCC_AST_OP_GREATER: op = SCC_IR_OP_GT; break; + case SCC_AST_OP_GREATER_EQUAL: op = SCC_IR_OP_GE; break; + case SCC_AST_OP_COMMA: { + // 逗号运算符:计算左表达式,丢弃结果,返回右表达式 + return rhs; + } + /* 逻辑操作符 */ + case SCC_AST_OP_LOGICAL_OR: // || + case SCC_AST_OP_LOGICAL_AND: // && TODO(); - // /* 赋值操作符 */ - // /* 条件操作符 */ - // SCC_AST_OP_CONDITIONAL, // ?: - // /* 逗号操作符 */ - // SCC_AST_OP_COMMA, // , - // /* 逻辑操作符 */ - // SCC_AST_OP_LOGICAL_OR, // || - // SCC_AST_OP_LOGICAL_AND, // && - // /* 位操作符 */ - // SCC_AST_OP_BITWISE_OR, // | - // SCC_AST_OP_BITWISE_XOR, // ^ - // SCC_AST_OP_BITWISE_AND, // & - // /* 相等性操作符 */ - // SCC_AST_OP_EQUAL, // == - // SCC_AST_OP_NOT_EQUAL, // != - // /* 关系操作符 */ - // SCC_AST_OP_LESS, // < - // SCC_AST_OP_GREATER, // > - // SCC_AST_OP_LESS_EQUAL, // <= - // SCC_AST_OP_GREATER_EQUAL, // >= - // /* 移位操作符 */ - // SCC_AST_OP_LEFT_SHIFT, // << - // SCC_AST_OP_RIGHT_SHIFT, // >> - // /* 算术操作符 */ - // SCC_AST_OP_ADD, // + - // SCC_AST_OP_SUB, // - - // SCC_AST_OP_MUL, // * - // SCC_AST_OP_DIV, // / - // SCC_AST_OP_MOD, // % - // /* 一元操作符 */ - // SCC_AST_OP_UNARY_PLUS, // + (一元) - // SCC_AST_OP_UNARY_MINUS, // - (一元) - // SCC_AST_OP_ADDRESS_OF, // & - // SCC_AST_OP_INDIRECTION, // * - // SCC_AST_OP_BITWISE_NOT, // ~ - // SCC_AST_OP_LOGICAL_NOT, // ! - // SCC_AST_OP_PREFIX_INCREMENT, // ++ (前缀) - // SCC_AST_OP_PREFIX_DECREMENT, // -- (前缀) - // SCC_AST_OP_POSTFIX_INCREMENT, // ++ (后缀) - // SCC_AST_OP_POSTFIX_DECREMENT, // -- (后缀) - // /* 成员访问 */ - // SCC_AST_OP_MEMBER_ACCESS, // . - // SCC_AST_OP_PTR_MEMBER_ACCESS, // -> - /* clang-format on */ + /* clang-format on */ default: LOG_FATAL("Unsupported binary operator: %d", expr->binary.op); return 0; } - // 创建操作节点 return scc_ir_builder_binop(&ctx->builder, op, lhs, rhs); } @@ -205,10 +223,20 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, case SCC_AST_EXPR_UNARY: { scc_ir_node_ref_t operand = scc_ast2ir_expr(ctx, expr->unary.operand, is_lvalue); - + // /* 一元操作符 */ + // SCC_AST_OP_UNARY_PLUS, // + (一元) + // SCC_AST_OP_UNARY_MINUS, // - (一元) + // SCC_AST_OP_ADDRESS_OF, // & + // SCC_AST_OP_INDIRECTION, // * + // SCC_AST_OP_BITWISE_NOT, // ~ + // SCC_AST_OP_LOGICAL_NOT, // ! + // SCC_AST_OP_PREFIX_INCREMENT, // ++ (前缀) + // SCC_AST_OP_PREFIX_DECREMENT, // -- (前缀) + // SCC_AST_OP_POSTFIX_INCREMENT, // ++ (后缀) + // SCC_AST_OP_POSTFIX_DECREMENT, // -- (后缀) // 映射一元操作符 switch (expr->unary.op) { - case SCC_AST_OP_SUB: + case SCC_AST_OP_UNARY_MINUS: // 负号 // 实现为0 - operand return scc_ir_builder_binop( @@ -266,7 +294,7 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, // SCC_AST_EXPR_ALIGN_OF, // _Alignof // SCC_AST_EXPR_COMPOUND, // 复合字面量 // SCC_AST_EXPR_LVALUE, // 右值 - // SCC_AST_EXPR_BUILTIN, // 内置表达式 + // SCC_AST_EXPR_BUILTIN,// 内置表达式 ... directive map to ir builtin case SCC_AST_EXPR_INT_LITERAL: { // FIXME maybe using some array to int; @@ -284,7 +312,7 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, case SCC_AST_EXPR_IDENTIFIER: { if (expr->identifier._target == null) { - LOG_ERROR("unknown identifier"); + LOG_ERROR("unknown identifier %s", expr->identifier.name); } // FIXME hack hashtable scc_ir_node_ref_t in = (scc_ir_node_ref_t)(usize)scc_hashtable_get( @@ -365,7 +393,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) { // 生成false分支 if (stmt->if_stmt.opt_else_stmt) { - scc_ir_builder_set_current_bblock(&ctx->builder, true_block); + scc_ir_builder_set_current_bblock(&ctx->builder, false_block); scc_ast2ir_stmt(ctx, stmt->if_stmt.opt_else_stmt); scc_ir_builder_jump(&ctx->builder, merge_block); } @@ -421,13 +449,46 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) { } case SCC_AST_STMT_FOR: { - TODO(); scc_ir_bblock_ref_t cond_block = scc_ir_builder_bblock(&ctx->builder, "for_while_cond"); scc_ir_bblock_ref_t body_block = scc_ir_builder_bblock(&ctx->builder, "for_while_body"); scc_ir_bblock_ref_t exit_block = scc_ir_builder_bblock(&ctx->builder, "for_while_exit"); + + if (stmt->for_stmt.init) { + if (SCC_AST_IS_A(scc_ast_decl_t, stmt->for_stmt.init)) { + scc_ast2ir_decl( + ctx, SCC_AST_CAST_TO(scc_ast_decl_t, stmt->for_stmt.init)); + } else if (SCC_AST_IS_A(scc_ast_expr_t, stmt->for_stmt.init)) { + scc_ast2ir_expr( + ctx, SCC_AST_CAST_TO(scc_ast_expr_t, stmt->for_stmt.init), + false); + } else { + LOG_FATAL("invalid for init statement"); + } + } + + scc_ir_builder_jump(&ctx->builder, cond_block); + + scc_ir_builder_set_current_bblock(&ctx->builder, cond_block); + if (stmt->for_stmt.cond) { + scc_ir_node_ref_t cond_node = + scc_ast2ir_expr(ctx, stmt->for_stmt.cond, false); + scc_ir_builder_branch(&ctx->builder, cond_node, body_block, + exit_block); + } else { + scc_ir_builder_jump(&ctx->builder, body_block); + } + + scc_ir_builder_set_current_bblock(&ctx->builder, body_block); + scc_ast2ir_stmt(ctx, stmt->for_stmt.body); + if (stmt->for_stmt.incr) { + scc_ast2ir_expr(ctx, stmt->for_stmt.incr, false); + } + scc_ir_builder_jump(&ctx->builder, cond_block); + + scc_ir_builder_set_current_bblock(&ctx->builder, exit_block); break; } @@ -488,12 +549,12 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) { } case SCC_AST_DECL_FUNC: { - // TODO params name scc_ir_type_ref_t func_type = scc_ast2ir_type(ctx, decl->func.type); if (decl->func.body == null) { // function decl break; } + // TODO params name scc_ir_builder_begin_func(&ctx->builder, decl->name, func_type, null); scc_ir_builder_begin_bblock(&ctx->builder, "entry"); scc_ast2ir_stmt(ctx, decl->func.body); @@ -546,6 +607,5 @@ void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *abi) { Assert(ctx != null); ctx->abi = abi; scc_ir_builder_init(&ctx->builder); - scc_hashtable_init(&ctx->node2ir, scc_hash_node, scc_cmp_node); } diff --git a/libs/ir/src/ir_builder.c b/libs/ir/src/ir_builder.c index 810d175..117a4f4 100644 --- a/libs/ir/src/ir_builder.c +++ b/libs/ir/src/ir_builder.c @@ -83,23 +83,18 @@ scc_ir_func_ref_t scc_ir_builder_current_func(scc_ir_builder_t *builder) { scc_ir_bblock_ref_t scc_ir_builder_bblock(scc_ir_builder_t *builder, const char *label) { scc_ir_bblock_t bblock = {0}; - if (label) { bblock.label = label; - } else { - // TODO 自动生成标签 - char *auto_label = scc_malloc(sizeof(char) * 64); - if (auto_label) - LOG_FATAL("allocate memory failed"); - static int auto_counter = 0; - scc_snprintf(auto_label, sizeof(auto_label), ".BB%d", auto_counter++); - bblock.label = auto_label; } - scc_vec_init(bblock.instrs); - scc_ir_bblock_ref_t bblock_ref = scc_ir_ctx_new_bblock(&builder->ctx, &bblock); + + scc_ir_func_t *current_func = + scc_ir_ctx_get_func(&builder->ctx, builder->current_func); + if (current_func) { + scc_vec_push(current_func->bblocks, bblock_ref); + } return bblock_ref; } @@ -107,14 +102,6 @@ scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder, const char *label) { builder->current_bblock = scc_ir_builder_bblock(builder, label); - - // 将基本块添加到当前函数 - scc_ir_func_t *current_func = - scc_ir_ctx_get_func(&builder->ctx, builder->current_func); - if (current_func) { - scc_vec_push(current_func->bblocks, builder->current_bblock); - } - return builder->current_bblock; } diff --git a/libs/ir/src/ir_dump.c b/libs/ir/src/ir_dump.c index 0949a73..863df1a 100644 --- a/libs/ir/src/ir_dump.c +++ b/libs/ir/src/ir_dump.c @@ -679,11 +679,11 @@ void scc_ir_dump_node_linear(scc_ir_dump_ctx_t *ctx, char cond_buf[64]; format_node_ref_or_value(ctx, cond_buf, sizeof(cond_buf), node->data.branch.cond); - p += scc_snprintf(p, remaining, "br %s, label %%%u, label %%%u", + p += scc_snprintf(p, remaining, "br %s, label %%L%u, label %%L%u", cond_buf, node->data.branch.true_bblock, node->data.branch.false_bblock); } else { - p += scc_snprintf(p, remaining, "br label %%%u", + p += scc_snprintf(p, remaining, "br label %%L%u", node->data.branch.true_bblock); } break; @@ -694,6 +694,7 @@ void scc_ir_dump_node_linear(scc_ir_dump_ctx_t *ctx, break; case SCC_IR_NODE_CALL: { + char node_name[256] = ""; char args_buf[256] = ""; char *args_p = args_buf; usize args_remaining = sizeof(args_buf); @@ -712,8 +713,10 @@ void scc_ir_dump_node_linear(scc_ir_dump_ctx_t *ctx, args_remaining = sizeof(args_buf) - (args_p - args_buf); } - p += scc_snprintf(p, remaining, "call @%%%u(%s)", - node->data.call.callee, args_buf); + format_node_ref_or_value(ctx, node_name, sizeof(node_name), + node->data.call.callee); + + p += scc_snprintf(p, remaining, "call @%s(%s)", node_name, args_buf); break; } @@ -751,9 +754,11 @@ void scc_ir_dump_bblock_linear(scc_ir_dump_ctx_t *ctx, // 打印基本块标签 static char label_buff[128]; if (bblock->label && bblock->label[0] != '\0') { - scc_snprintf(label_buff, sizeof(label_buff), "%%%s:", bblock->label); + scc_snprintf(label_buff, sizeof(label_buff), "%%L%d %s:", bblock_ref, + bblock->label); } else { - scc_snprintf(label_buff, sizeof(label_buff), ":"); + scc_snprintf(label_buff, sizeof(label_buff), + "%%L%d :", bblock_ref); } PRINT_NODE(ctx->dump_ctx, label_buff); diff --git a/libs/ir2mcode/src/ir2amd64.c b/libs/ir2mcode/src/ir2amd64.c index 79e5d43..d39ba40 100644 --- a/libs/ir2mcode/src/ir2amd64.c +++ b/libs/ir2mcode/src/ir2amd64.c @@ -63,6 +63,7 @@ static void store_value_from_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc, if (loc->idx != reg) { scc_mcode_amd64_mov_r64_r64(mcode, loc->idx, reg); } + break; case SCC_REG_KIND_STACK: scc_mcode_amd64_mov_m64_disp32_r64(mcode, SCC_AMD64_RBP, -loc->idx, reg); @@ -72,6 +73,7 @@ static void store_value_from_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc, break; default: LOG_FATAL("unsupported location"); + break; } } @@ -87,7 +89,7 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, case SCC_IR_NODE_CONV: ///< 类型转换 case SCC_IR_NODE_FUNC_ARG_REF: ///< 函数参数引用 case SCC_IR_NODE_BLOCK_ARG_REF: ///< 基本块参数引用 - LOG_ERROR("Unsupported node type: %d", node->tag); + LOG_FATAL("Unsupported node type: %d", node->tag); break; case SCC_IR_NODE_ALLOC: ///< 分配内存(stack) case SCC_IR_NODE_GLOBAL_ALLOC: ///< 全局分配(bss) @@ -153,7 +155,7 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, case SCC_IR_NODE_BRANCH: ///< 有条件分支 case SCC_IR_NODE_JUMP: ///< 无条件跳转 case SCC_IR_NODE_CALL: ///< 调用函数 - LOG_ERROR("Unsupported node type: %d", node->tag); + LOG_FATAL("Unsupported node type: %d", node->tag); break; case SCC_IR_NODE_RET: ///< 函数返回 if (node->data.ret.ret_val) { diff --git a/libs/lexer/src/lexer.c b/libs/lexer/src/lexer.c index 0046bdc..862ab9b 100644 --- a/libs/lexer/src/lexer.c +++ b/libs/lexer/src/lexer.c @@ -173,6 +173,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { // 数字字面量(整数/浮点) token->type = SCC_TOK_INT_LITERAL; // 先假定整数 cbool maybe_float = false; + cbool is_hex = false; while (1) { next_char(lexer, &lex, &cur); // 消费当前数字 if (!peek_char(lexer, &cur)) @@ -185,12 +186,16 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { } if (ch == 'e' || ch == 'E' || ch == 'p' || ch == 'P') { maybe_float = true; - // 后面可能跟符号或数字 + continue; + } + if (is_hex && + ((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))) { continue; } if (ch == 'x' || ch == 'X') { - // 十六进制前缀,需特殊处理 - // 这里简化:将整个序列作为整数(保留前缀) + is_hex = true; + continue; + } else if (ch == 'b' || ch == 'B') { continue; } break; diff --git a/libs/lexer/tests/test_lexer.c b/libs/lexer/tests/test_lexer.c index 1cf00ab..ef60db1 100644 --- a/libs/lexer/tests/test_lexer.c +++ b/libs/lexer/tests/test_lexer.c @@ -17,10 +17,13 @@ static void free_token(scc_lexer_tok_t *tok) { scc_cstring_free(&tok->lexeme); } scc_lexer_init(&lexer, ref); \ scc_lexer_get_token(&lexer, &token); \ \ - TEST_CHECK(token.type == expected_type); \ + TEST_CHECK(token.type == expected_type && \ + scc_strcmp(input, scc_cstring_as_cstr(&token.lexeme)) == \ + 0); \ TEST_MSG("Input: '%s'", input); \ - TEST_MSG("Expected: %s", scc_get_tok_name(expected_type)); \ - TEST_MSG("Got: %s", scc_get_tok_name(token.type)); \ + TEST_MSG("Expected: %s `%s`", scc_get_tok_name(expected_type), input); \ + TEST_MSG("Got: %s `%s`", scc_get_tok_name(token.type), \ + scc_cstring_as_cstr(&token.lexeme)); \ \ free_token(&token); \ scc_sstream_drop_ring(ref); \ @@ -167,7 +170,7 @@ void test_literals() { TEST_TOKEN("0x1A3F", SCC_TOK_INT_LITERAL); TEST_TOKEN("0XABCDEF", SCC_TOK_INT_LITERAL); TEST_TOKEN("0x123abc", SCC_TOK_INT_LITERAL); - TEST_TOKEN("0XFF", SCC_TOK_INT_LITERAL); + TEST_TOKEN("0xFF", SCC_TOK_INT_LITERAL); TEST_CASE("Integer literals - octal"); TEST_TOKEN("0123", SCC_TOK_INT_LITERAL); diff --git a/libs/parser/src/parse_decl.c b/libs/parser/src/parse_decl.c index e3a080f..4e37d33 100644 --- a/libs/parser/src/parse_decl.c +++ b/libs/parser/src/parse_decl.c @@ -288,8 +288,15 @@ CONTINUE: scc_ast_expr_lvalue_init(lvalue, decl->var.type, decl->base.loc); decl->var.init = scc_parse_initializer(parser, lvalue); } else if (tok_ptr->type == SCC_TOK_L_BRACE) { + scc_parse_decl_sema(parser, decl); parser->sema_callbacks.on_decl(parser->sema_callbacks.context, scc_ast_decl_t_BEGIN, null); + scc_vec_foreach(decl->func.type->function.params, i) { + scc_ast_decl_t *param = + scc_vec_at(decl->func.type->function.params, i); + // Add params to decl + scc_parse_decl_sema(parser, param); + } scc_ast_stmt_t *body = scc_parse_statement(parser); parser->sema_callbacks.on_decl(parser->sema_callbacks.context, scc_ast_decl_t_END, null); diff --git a/libs/parser/src/parse_stmt.c b/libs/parser/src/parse_stmt.c index 76eb060..db8db2b 100644 --- a/libs/parser/src/parse_stmt.c +++ b/libs/parser/src/parse_stmt.c @@ -269,15 +269,15 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser, "Expected '(' before like `( expression )` ."); } - scc_ast_type_t *init = null; + scc_ast_node_t *init = null; scc_ast_expr_t *cond = null; scc_ast_expr_t *incr = null; scc_ast_stmt_t *body = null; // TODO use decl or expr - init = (scc_ast_type_t *)scc_parse_declaration(parser); + init = (scc_ast_node_t *)scc_parse_declaration(parser); if (init == null) { - init = (scc_ast_type_t *)scc_parse_expression(parser); + init = (scc_ast_node_t *)scc_parse_expression(parser); if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { SCC_ERROR(scc_parser_got_current_pos(parser), "Expected semicolon in for statement."); diff --git a/libs/parser/src/parse_type.c b/libs/parser/src/parse_type.c index e91c933..94b2ea7 100644 --- a/libs/parser/src/parse_type.c +++ b/libs/parser/src/parse_type.c @@ -508,22 +508,25 @@ static scc_ast_type_t *build_type_from_info(type_spec_info_t *info, if (info->is_unsigned) builtin = SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR; else if (!info->is_signed) - builtin = SCC_AST_BUILTIN_TYPE_CHAR; // plain char (可能区别于 - // signed char) + builtin = SCC_AST_BUILTIN_TYPE_CHAR; else builtin = SCC_AST_BUILTIN_TYPE_SIGNED_CHAR; } else if (info->is_short) { builtin = info->is_unsigned ? SCC_AST_BUILTIN_TYPE_UNSIGNED_SHORT + : info->is_signed ? SCC_AST_BUILTIN_TYPE_SIGNED_SHORT : SCC_AST_BUILTIN_TYPE_SHORT; } else if (info->is_long_long) { builtin = info->is_unsigned ? SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG - : SCC_AST_BUILTIN_TYPE_LONG_LONG; + : info->is_signed ? SCC_AST_BUILTIN_TYPE_SIGNED_LONG_LONG + : SCC_AST_BUILTIN_TYPE_LONG_LONG; } else if (info->is_long) { builtin = info->is_unsigned ? SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG + : info->is_signed ? SCC_AST_BUILTIN_TYPE_SIGNED_LONG : SCC_AST_BUILTIN_TYPE_LONG; - } else { // int + } else { builtin = info->is_unsigned ? SCC_AST_BUILTIN_TYPE_UNSIGNED_INT + : info->is_signed ? SCC_AST_BUILTIN_TYPE_SIGNED_INT : SCC_AST_BUILTIN_TYPE_INT; } } @@ -571,6 +574,10 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser, scc_lexer_tok_drop(&tok); const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); + if (tok_ptr == null) { + SCC_ERROR(scc_parser_got_current_pos(parser), "Unexpected EOF"); + return null; + } const char *name = null; scc_ast_decl_t *decl = null; scc_ast_decl_vec_t member; @@ -609,7 +616,7 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser, break; } else { SCC_ERROR(scc_parser_got_current_pos(parser), - "Unexpected token in enum specifier"); + "Unexpected token in struct/union specifier"); scc_parser_next_consume(parser, null); break; } @@ -663,9 +670,14 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { scc_lexer_tok_drop(&tok); const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); + if (tok_ptr == null) { + SCC_ERROR(scc_parser_got_current_pos(parser), "Unexpected EOF"); + return null; + } + scc_ast_type_t *type = ast_type_alloc(); const char *name = null; scc_ast_decl_t *decl = null; - scc_ast_expr_vec_t member; + scc_ast_decl_vec_t member; scc_vec_init(member); if (tok_ptr->type == SCC_TOK_IDENT) { @@ -684,20 +696,42 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { break; } - scc_ast_expr_t *expr = scc_parse_assignment_expression(parser); - if (expr != null) { - scc_vec_push(member, expr); - continue; + scc_parser_next_consume(parser, &tok); + if (tok.type != SCC_TOK_IDENT) { + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected identifier in enum specifier"); + break; } - if (tok_ptr->type == SCC_TOK_COMMA) { - // FIXME check comma + scc_ast_expr_t *enum_item_init = null; + if (scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) { + enum_item_init = scc_parser_constant_expression(parser); + } + + scc_ast_decl_t *enum_item_decl = scc_malloc(sizeof(scc_ast_decl_t)); + Assert(enum_item_decl != null); + scc_ast_decl_val_init(enum_item_decl, type, + scc_cstring_as_cstr(&tok.lexeme), + enum_item_init, tok.loc); + scc_vec_push(member, enum_item_decl); + + tok_ptr = scc_parser_peek(parser); + + cbool got_comma = false; + if (tok_ptr && tok_ptr->type == SCC_TOK_COMMA) { scc_parser_next_consume(parser, null); - } else if (tok_ptr->type == SCC_TOK_R_BRACE) { + tok_ptr = scc_parser_peek(parser); + got_comma = true; + } + if (tok_ptr && tok_ptr->type == SCC_TOK_R_BRACE) { scc_parser_next_consume(parser, null); break; } else { - SCC_ERROR(scc_parser_got_current_pos(parser), + if (got_comma) { + continue; + } + SCC_ERROR(tok_ptr != null ? tok_ptr->loc + : scc_parser_got_current_pos(parser), "Unexpected token in enum specifier"); scc_parser_next_consume(parser, null); break; @@ -716,7 +750,6 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { } } - scc_ast_type_t *type = ast_type_alloc(); scc_ast_type_enum_init(type, name, decl, pos); return type; } @@ -1071,7 +1104,10 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base, tok_ident); } else { ret = parse_declarator(parser, null, &delay_pointee, tok_ident); - Assert(ret != null); + if (ret == null) { + SCC_ERROR(tok_ident->loc, "parse_declarator failed"); + Panic("parse_declarator failed ret == null"); + } if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { SCC_ERROR(scc_parser_got_current_pos(parser), "expect ')'"); } @@ -1199,31 +1235,25 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser, if (decl_name_tok.type != SCC_TOK_IDENT) { if (decl_type->base.type == SCC_AST_TYPE_STRUCT || - decl_type->base.type == SCC_AST_TYPE_UNION) { + decl_type->base.type == SCC_AST_TYPE_UNION || + decl_type->base.type == SCC_AST_TYPE_ENUM) { if (decl_type->record.decl == null) { decl = scc_malloc(sizeof(scc_ast_decl_t)); Assert(decl != null); if (decl_type->base.type == SCC_AST_TYPE_STRUCT) { scc_ast_decl_struct_init(decl, decl_type->record.name, null, decl_type->base.loc); - } else { + } else if (decl_type->base.type == SCC_AST_TYPE_UNION) { scc_ast_decl_union_init(decl, decl_type->record.name, null, decl_type->base.loc); + } else { + scc_ast_decl_enum_init(decl, type->record.name, null, + decl_type->base.loc); } } else { decl = decl_type->record.decl; scc_free(decl_type); // FIXME } - } else if (decl_type->base.type == SCC_AST_TYPE_ENUM) { - if (decl_type->enumeration.decl == null) { - decl = scc_malloc(sizeof(scc_ast_decl_t)); - Assert(decl != null); - scc_ast_decl_enum_init(decl, type->enumeration.name, null, - decl_type->base.loc); - } else { - decl = type->enumeration.decl; - scc_free(decl_type); // FIXME - } } else { decl = scc_malloc(sizeof(scc_ast_decl_t)); scc_ast_decl_unsafe_val_init(decl, type, null, null, diff --git a/libs/parser/src/scc_sema.c b/libs/parser/src/scc_sema.c index d510419..7d033fa 100644 --- a/libs/parser/src/scc_sema.c +++ b/libs/parser/src/scc_sema.c @@ -23,10 +23,11 @@ static void expr_callback(void *context, scc_ast_node_type_t node_type, scc_ast_node_t *node = scc_sema_symtab_lookup_symbol(sema_symtab, expr->identifier.name); if (node == null) { - SCC_ERROR(expr->base.loc, "Identifier '%s' not found", + SCC_ERROR(expr->base.loc, "sema error: Identifier '%s' not found", expr->identifier.name); } else if (!SCC_AST_IS_A(scc_ast_decl_t, node)) { - SCC_ERROR(expr->base.loc, "Identifier '%s' is not a variable", + SCC_ERROR(expr->base.loc, + "sema error: Identifier '%s' is not a variable", expr->identifier.name); } else { expr->identifier._target = SCC_AST_CAST_TO(scc_ast_decl_t, node); @@ -72,34 +73,71 @@ static void decl_callback(void *context, scc_ast_node_type_t node_type, scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t)); Assert(type != null); - if (decl->name == null) { - return; - } + if (node_type == SCC_AST_DECL_STRUCT) { scc_ast_type_struct_init(type, decl->name, decl, decl->base.loc); + // FIXME memory leak scc_cstring_t name = scc_cstring_from_cstr("$S_"); + + if (decl->name == null) { + decl->name = ""; + } scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), &type->base); } else if (node_type == SCC_AST_DECL_UNION) { scc_ast_type_union_init(type, decl->name, decl, decl->base.loc); scc_cstring_t name = scc_cstring_from_cstr("$U_"); + if (decl->name == null) { + decl->name = ""; + } scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), &type->base); } else if (node_type == SCC_AST_DECL_ENUM) { scc_ast_type_enum_init(type, decl->name, decl, decl->base.loc); scc_cstring_t name = scc_cstring_from_cstr("$E_"); + if (decl->name == null) { + decl->name = ""; + } scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), &type->base); + + scc_vec_foreach(decl->record.fields, i) { + scc_ast_decl_t *enum_decl = scc_vec_at(decl->record.fields, i); + scc_sema_symtab_add_symbol(sema_symtab, enum_decl->name, + &enum_decl->base); + // LOG_INFO("enum added %s", enum_decl->name); + } } else if (node_type == SCC_AST_DECL_TYPEDEF) { + if (decl->name == null) { + SCC_ERROR(decl->base.loc, "typedef without name"); + return; + } scc_ast_type_typedef_init(type, decl->name, decl, decl->base.loc); scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base); } else if (node_type == SCC_AST_DECL_VAR) { scc_sema_symtab_add_symbol(sema_symtab, decl->name, &decl->base); } else if (node_type == SCC_AST_DECL_PARAM) { + if (decl->name == null) { + if (decl->param.type->base.type == SCC_AST_TYPE_BUILTIN && + (decl->param.type->builtin.type == + SCC_AST_BUILTIN_TYPE_VA_LIST || + decl->param.type->builtin.type == SCC_AST_BUILTIN_TYPE_VOID)) { + return; + } + SCC_ERROR(decl->base.loc, "sema error: Parameter must have a name"); + return; + } scc_sema_symtab_add_symbol(sema_symtab, decl->name, &decl->base); + } else if (node_type == SCC_AST_DECL_FUNC) { + if (decl->name == null) { + SCC_ERROR(decl->base.loc, "sema error: Function must have a name"); + } else { + // FIXME 重名函数... + scc_sema_symtab_add_symbol(sema_symtab, decl->name, &decl->base); + } } return; } @@ -136,6 +174,25 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) { scc_pos_create()); scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_list", &type->base); + + scc_ast_decl_t *decl = scc_malloc(sizeof(scc_ast_decl_t)); + scc_ast_decl_val_init(decl, type, "__scc_builtin__", null, + scc_pos_create()); + scc_sema_symtab_add_symbol(sema_symtab, "__func__", &decl->base); + + scc_ast_type_t *built_func_type = scc_malloc(sizeof(scc_ast_type_t)); + scc_ast_type_function_init(built_func_type, null, null, scc_pos_create()); + scc_ast_decl_t *builin_func = scc_malloc(sizeof(scc_ast_decl_t)); + scc_ast_decl_func_init(builin_func, built_func_type, "__scc_builtin_func", + null, scc_pos_create()); + scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_start", + &builin_func->base); + scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_end", + &builin_func->base); + scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_arg", + &builin_func->base); + scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_copy", + &builin_func->base); } void scc_sema_drop(scc_sema_callbacks_t *callbacks) {} diff --git a/libs/parser/tests/parser_test.h b/libs/parser/tests/parser_test.h index 6f3e76d..ac9a154 100644 --- a/libs/parser/tests/parser_test.h +++ b/libs/parser/tests/parser_test.h @@ -35,7 +35,7 @@ static scc_ast_node_t *process_input(const char *input, scc_ring_not_eof(*parser.ring, not_eof); if (not_eof == true) { // FIXME MAYBE free - LOG_ERROR("Didn't consume all tokens"); + LOG_FATAL("Didn't consume all tokens"); return null; } diff --git a/libs/parser/tests/test_parse_type.c b/libs/parser/tests/test_parse_type.c index 8e4217d..16ac651 100644 --- a/libs/parser/tests/test_parse_type.c +++ b/libs/parser/tests/test_parse_type.c @@ -46,6 +46,7 @@ static void test_builtin_type(void) { CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR, "unsigned char"); CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_SHORT, "unsigned short"); CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_INT, "unsigned int"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_INT, "unsigned"); CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG, "unsigned long"); CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG, "unsigned long int"); CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG, @@ -55,6 +56,7 @@ static void test_builtin_type(void) { CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_CHAR, "signed char"); CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_SHORT, "signed short"); CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_INT, "signed int"); + CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_INT, "signed"); CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_LONG, "signed long"); CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_LONG, "signed long int"); CHECK_BUILTIN_TYPE(SCC_AST_BUILTIN_TYPE_SIGNED_LONG_LONG, @@ -104,7 +106,7 @@ static void test_array_type(void) { { // int [] scc_ast_type_t array_unknown_int; - scc_ast_type_array_init(&array_unknown_int, &int_type, NULL, + scc_ast_type_array_init(&array_unknown_int, &int_type, null, scc_pos_create()); SCC_CHECK_AST(&array_unknown_int.base, "int []", scc_parse_type_name); } @@ -157,7 +159,7 @@ static void test_function_type(void) { { // int () scc_ast_type_t func_type; - scc_ast_type_function_init(&func_type, &int_type, NULL, + scc_ast_type_function_init(&func_type, &int_type, null, scc_pos_create()); SCC_CHECK_AST(&func_type.base, "int ()", scc_parse_type_name); } @@ -166,7 +168,7 @@ static void test_function_type(void) { { // int (void) scc_ast_decl_t void_param; - scc_ast_decl_param_init(&void_param, &void_type, NULL, + scc_ast_decl_param_init(&void_param, &void_type, null, scc_pos_create()); scc_ast_decl_vec_t params; @@ -187,8 +189,8 @@ static void test_function_type(void) { scc_pos_create()); scc_ast_decl_t param_int, param_float; - scc_ast_decl_param_init(¶m_int, &int_type, NULL, scc_pos_create()); - scc_ast_decl_param_init(¶m_float, &float_type, NULL, + scc_ast_decl_param_init(¶m_int, &int_type, null, scc_pos_create()); + scc_ast_decl_param_init(¶m_float, &float_type, null, scc_pos_create()); scc_ast_decl_vec_t params; @@ -210,7 +212,7 @@ static void test_function_type(void) { scc_pos_create()); scc_ast_decl_t param_int, param_var; - scc_ast_decl_param_init(¶m_int, &int_type, NULL, scc_pos_create()); + scc_ast_decl_param_init(¶m_int, &int_type, null, scc_pos_create()); scc_ast_decl_param_init(¶m_var, &va_list_type, "...", scc_pos_create()); @@ -229,7 +231,7 @@ static void test_function_type(void) { { // int *() scc_ast_type_t func_type; - scc_ast_type_function_init(&func_type, &pointer_int_type, NULL, + scc_ast_type_function_init(&func_type, &pointer_int_type, null, scc_pos_create()); SCC_CHECK_AST(&func_type.base, "int *()", scc_parse_type_name); } @@ -238,7 +240,7 @@ static void test_function_type(void) { { // int (*)(void) scc_ast_decl_t void_param; - scc_ast_decl_param_init(&void_param, &void_type, NULL, + scc_ast_decl_param_init(&void_param, &void_type, null, scc_pos_create()); scc_ast_decl_vec_t params; @@ -260,7 +262,7 @@ static void test_struct_union_type(void) { { // struct S scc_ast_type_t struct_type; - scc_ast_type_struct_init(&struct_type, "S", NULL, scc_pos_create()); + scc_ast_type_struct_init(&struct_type, "S", null, scc_pos_create()); SCC_CHECK_AST(&struct_type.base, "struct S", scc_parse_type_name); } @@ -268,7 +270,7 @@ static void test_struct_union_type(void) { { // union U scc_ast_type_t union_type; - scc_ast_type_union_init(&union_type, "U", NULL, scc_pos_create()); + scc_ast_type_union_init(&union_type, "U", null, scc_pos_create()); SCC_CHECK_AST(&union_type.base, "union U", scc_parse_type_name); } @@ -276,17 +278,17 @@ static void test_struct_union_type(void) { { // struct { int x; } scc_ast_decl_t field_x; - scc_ast_decl_val_init(&field_x, &int_type, "x", NULL, scc_pos_create()); + scc_ast_decl_val_init(&field_x, &int_type, "x", null, scc_pos_create()); scc_ast_decl_vec_t fields; scc_vec_init(fields); scc_vec_push(fields, &field_x); scc_ast_decl_t struct_decl; - scc_ast_decl_struct_init(&struct_decl, NULL, &fields, scc_pos_create()); + scc_ast_decl_struct_init(&struct_decl, null, &fields, scc_pos_create()); scc_ast_type_t struct_type; - scc_ast_type_struct_init(&struct_type, NULL, &struct_decl, + scc_ast_type_struct_init(&struct_type, null, &struct_decl, scc_pos_create()); SCC_CHECK_AST(&struct_type.base, "struct { int x; }", scc_parse_type_name); @@ -296,7 +298,7 @@ static void test_struct_union_type(void) { { // struct S { int x; } scc_ast_decl_t field_x; - scc_ast_decl_val_init(&field_x, &int_type, "x", NULL, scc_pos_create()); + scc_ast_decl_val_init(&field_x, &int_type, "x", null, scc_pos_create()); scc_ast_decl_vec_t fields; scc_vec_init(fields); @@ -320,8 +322,8 @@ static void test_struct_union_type(void) { scc_pos_create()); scc_ast_decl_t field_a, field_b; - scc_ast_decl_val_init(&field_a, &int_type, "a", NULL, scc_pos_create()); - scc_ast_decl_val_init(&field_b, &float_type, "b", NULL, + scc_ast_decl_val_init(&field_a, &int_type, "a", null, scc_pos_create()); + scc_ast_decl_val_init(&field_b, &float_type, "b", null, scc_pos_create()); scc_ast_decl_vec_t fields; @@ -330,10 +332,10 @@ static void test_struct_union_type(void) { scc_vec_push(fields, &field_b); scc_ast_decl_t union_decl; - scc_ast_decl_union_init(&union_decl, NULL, &fields, scc_pos_create()); + scc_ast_decl_union_init(&union_decl, null, &fields, scc_pos_create()); scc_ast_type_t union_type; - scc_ast_type_union_init(&union_type, NULL, &union_decl, + scc_ast_type_union_init(&union_type, null, &union_decl, scc_pos_create()); SCC_CHECK_AST(&union_type.base, "union { int a; float b; }", scc_parse_type_name); @@ -345,54 +347,61 @@ static void test_enum_type(void) { { // enum E scc_ast_type_t enum_type; - scc_ast_type_enum_init(&enum_type, "E", NULL, scc_pos_create()); + scc_ast_type_enum_init(&enum_type, "E", null, scc_pos_create()); SCC_CHECK_AST(&enum_type.base, "enum E", scc_parse_type_name); } TEST_CASE("anonymous enum definition"); { // enum { RED, GREEN, BLUE } - scc_ast_expr_t red, green, blue; - scc_ast_expr_identifier_init(&red, "RED", scc_pos_create()); - scc_ast_expr_identifier_init(&green, "GREEN", scc_pos_create()); - scc_ast_expr_identifier_init(&blue, "BLUE", scc_pos_create()); + scc_ast_type_t enum_type; - scc_ast_expr_vec_t enumerators; + scc_ast_decl_t red, green, blue; + scc_ast_decl_val_init(&red, &enum_type, "RED", null, scc_pos_create()); + scc_ast_decl_val_init(&green, &enum_type, "GREEN", null, + scc_pos_create()); + scc_ast_decl_val_init(&blue, &enum_type, "BLUE", null, + scc_pos_create()); + + scc_ast_decl_vec_t enumerators; scc_vec_init(enumerators); scc_vec_push(enumerators, &red); scc_vec_push(enumerators, &green); scc_vec_push(enumerators, &blue); scc_ast_decl_t enum_decl; - scc_ast_decl_enum_init(&enum_decl, NULL, &enumerators, + scc_ast_decl_enum_init(&enum_decl, null, &enumerators, scc_pos_create()); - scc_ast_type_t enum_type; - scc_ast_type_enum_init(&enum_type, NULL, &enum_decl, scc_pos_create()); + scc_ast_type_enum_init(&enum_type, null, &enum_decl, scc_pos_create()); SCC_CHECK_AST(&enum_type.base, "enum { RED, GREEN, BLUE }", scc_parse_type_name); } TEST_CASE("named enum definition"); { - // enum E { RED, GREEN, BLUE } - scc_ast_expr_t red, green, blue; - scc_ast_expr_identifier_init(&red, "RED", scc_pos_create()); - scc_ast_expr_identifier_init(&green, "GREEN", scc_pos_create()); - scc_ast_expr_identifier_init(&blue, "BLUE", scc_pos_create()); + // enum E { RED, GREEN, BLUE, } + scc_ast_type_t enum_type; - scc_ast_expr_vec_t enumerators; + scc_ast_decl_t red, green, blue; + scc_ast_decl_val_init(&red, &enum_type, "RED", null, scc_pos_create()); + scc_ast_decl_val_init(&green, &enum_type, "GREEN", null, + scc_pos_create()); + scc_ast_decl_val_init(&blue, &enum_type, "BLUE", null, + scc_pos_create()); + + scc_ast_decl_vec_t enumerators; scc_vec_init(enumerators); scc_vec_push(enumerators, &red); scc_vec_push(enumerators, &green); scc_vec_push(enumerators, &blue); scc_ast_decl_t enum_decl; - scc_ast_decl_enum_init(&enum_decl, "E", &enumerators, scc_pos_create()); + scc_ast_decl_enum_init(&enum_decl, null, &enumerators, + scc_pos_create()); - scc_ast_type_t enum_type; scc_ast_type_enum_init(&enum_type, "E", &enum_decl, scc_pos_create()); - SCC_CHECK_AST(&enum_type.base, "enum E { RED, GREEN, BLUE }", + SCC_CHECK_AST(&enum_type.base, "enum E { RED, GREEN, BLUE, }", scc_parse_type_name); } } @@ -476,7 +485,7 @@ static void test_hard_type(void) { { // 1) 函数类型 int (void) scc_ast_decl_t void_param; - scc_ast_decl_param_init(&void_param, &void_type, NULL, + scc_ast_decl_param_init(&void_param, &void_type, null, scc_pos_create()); scc_ast_decl_vec_t params; scc_vec_init(params); @@ -524,7 +533,7 @@ static void test_hard_type(void) { // 3) 函数类型,返回上述指针,无参数 scc_ast_decl_t void_param; - scc_ast_decl_param_init(&void_param, &void_type, NULL, + scc_ast_decl_param_init(&void_param, &void_type, null, scc_pos_create()); scc_ast_decl_vec_t params; scc_vec_init(params); @@ -547,7 +556,7 @@ static void test_hard_type(void) { { // 1) 函数类型 int (void) scc_ast_decl_t void_param; - scc_ast_decl_param_init(&void_param, &void_type, NULL, + scc_ast_decl_param_init(&void_param, &void_type, null, scc_pos_create()); scc_ast_decl_vec_t params; scc_vec_init(params); @@ -563,7 +572,7 @@ static void test_hard_type(void) { // 3) 外部函数类型,返回上述指针,无参数 scc_ast_type_t outer_func; - scc_ast_type_function_init(&outer_func, &ptr_to_func, NULL, + scc_ast_type_function_init(&outer_func, &ptr_to_func, null, scc_pos_create()); SCC_CHECK_AST(&outer_func.base, "int (*())(void)", scc_parse_type_name); @@ -579,5 +588,5 @@ TEST_LIST = { {"test_enum_type", test_enum_type}, {"test_specifier_type", test_specifier_type}, {"test_hard_type", test_hard_type}, - {NULL, NULL}, + {null, null}, }; diff --git a/libs/parser/tests/test_parse_unit.c b/libs/parser/tests/test_parse_unit.c new file mode 100644 index 0000000..8ab02e6 --- /dev/null +++ b/libs/parser/tests/test_parse_unit.c @@ -0,0 +1,869 @@ +void init_func(void); +#define TEST_INIT init_func() + +#include "parser_test.h" + +static scc_ast_type_t int_type; +static scc_ast_type_t char_type; +static scc_ast_type_t void_type; +static scc_ast_type_t pointer_int_type; +static scc_ast_type_t pointer_char_type; +static scc_ast_type_t pointer_void_type; +static scc_ast_type_t pointer_pointer_int_type; +static scc_ast_type_t va_list_type; + +void init_func(void) { + scc_ast_type_builtin_init(&int_type, SCC_AST_BUILTIN_TYPE_INT, + scc_pos_create()); + scc_ast_type_builtin_init(&char_type, SCC_AST_BUILTIN_TYPE_CHAR, + scc_pos_create()); + scc_ast_type_builtin_init(&void_type, SCC_AST_BUILTIN_TYPE_VOID, + scc_pos_create()); + scc_ast_type_pointer_init(&pointer_int_type, &int_type, scc_pos_create()); + scc_ast_type_pointer_init(&pointer_char_type, &char_type, scc_pos_create()); + scc_ast_type_pointer_init(&pointer_void_type, &void_type, scc_pos_create()); + scc_ast_type_pointer_init(&pointer_pointer_int_type, &pointer_int_type, + scc_pos_create()); + scc_ast_type_builtin_init(&va_list_type, SCC_AST_BUILTIN_TYPE_VA_LIST, + scc_pos_create()); +} + +static void test_parser_unit(void) { + // 1. 变量声明 int a; + { + scc_ast_decl_t int_decl; + scc_ast_decl_val_init(&int_decl, &int_type, "a", null, + scc_pos_create()); + SCC_CHECK_AST(&int_decl.base, "int a;", scc_parse_declaration); + } + + // 2. 函数声明 int main(void) {} + { + // 构造函数类型:返回 int,参数为空 + scc_ast_type_t func_type; + scc_ast_decl_vec_t func_params; + scc_ast_decl_t void_decl; + scc_ast_decl_param_init(&void_decl, &void_type, null, scc_pos_create()); + scc_ast_decl_t *array[] = {&void_decl}; + scc_vec_unsafe_from_static_array(func_params, array); + scc_ast_type_function_init(&func_type, &int_type, &func_params, + scc_pos_create()); + // 构造复合语句块(空) + scc_ast_stmt_t compound; + scc_ast_stmt_compound_init(&compound, null, scc_pos_create()); + + // 构造函数声明 + scc_ast_decl_t func_decl; + scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, + scc_pos_create()); + + SCC_CHECK_AST(&func_decl.base, "int main(void) {}", + scc_parse_declaration); + } + + // 3. 翻译单元包含一个函数定义 + { + scc_ast_type_t func_type; + scc_ast_decl_vec_t func_params; + scc_ast_decl_t void_decl; + scc_ast_decl_param_init(&void_decl, &void_type, null, scc_pos_create()); + scc_ast_decl_t *array[] = {&void_decl}; + scc_vec_unsafe_from_static_array(func_params, array); + scc_ast_type_function_init(&func_type, &int_type, &func_params, + scc_pos_create()); + + scc_ast_stmt_t compound; + scc_ast_stmt_compound_init(&compound, null, scc_pos_create()); + + scc_ast_decl_t func_decl; + scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, + scc_pos_create()); + + // 构造翻译单元 + scc_ast_decl_vec_t tu_decls; + scc_vec_init(tu_decls); + scc_vec_push(tu_decls, &func_decl); + + scc_ast_translation_unit_t tu; + scc_ast_translation_unit_init(&tu, &tu_decls, scc_pos_create()); + + SCC_CHECK_AST(&tu.base, "int main(void) {}", + scc_parse_translation_unit); + } + + // 4. 带返回语句的函数 int main(void) { return 65536; } + { + // 返回语句中的整数常量 + scc_ast_expr_t ret_val; + scc_ast_expr_literal_int_init(&ret_val, "65536", false, + scc_pos_create()); + + scc_ast_stmt_t ret_stmt; + scc_ast_stmt_return_init(&ret_stmt, &ret_val, scc_pos_create()); + + // 复合语句包含该返回语句 + scc_ast_block_item_vec_t items; + scc_vec_init(items); + scc_vec_push(items, (scc_ast_node_t *)&ret_stmt); + + scc_ast_stmt_t compound; + scc_ast_stmt_compound_init(&compound, &items, + scc_pos_create()); // items 被移动 + + // 函数类型 + scc_ast_type_t func_type; + scc_ast_decl_vec_t func_params; + scc_ast_decl_t void_decl; + scc_ast_decl_param_init(&void_decl, &void_type, null, scc_pos_create()); + scc_ast_decl_t *array[] = {&void_decl}; + scc_vec_unsafe_from_static_array(func_params, array); + scc_ast_type_function_init(&func_type, &int_type, &func_params, + scc_pos_create()); + + scc_ast_decl_t func_decl; + scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, + scc_pos_create()); + + scc_ast_decl_vec_t tu_decls; + scc_vec_init(tu_decls); + scc_vec_push(tu_decls, &func_decl); + + scc_ast_translation_unit_t tu; + scc_ast_translation_unit_init(&tu, &tu_decls, scc_pos_create()); + + SCC_CHECK_AST(&tu.base, "int main(void) { return 65536; }", + scc_parse_translation_unit); + } + + // 5. 多语句函数(复杂示例) + { + // 变量声明 int a; + scc_ast_decl_t a_decl; + scc_ast_decl_val_init(&a_decl, &int_type, "a", null, scc_pos_create()); + + // 变量声明 int b; + scc_ast_decl_t b_decl; + scc_ast_decl_val_init(&b_decl, &int_type, "b", null, scc_pos_create()); + + // 表达式 1 + 2 * 3 + scc_ast_expr_t lit1, lit2, lit3, mul, add; + scc_ast_expr_literal_int_init(&lit1, "1", false, scc_pos_create()); + scc_ast_expr_literal_int_init(&lit2, "2", false, scc_pos_create()); + scc_ast_expr_literal_int_init(&lit3, "3", false, scc_pos_create()); + scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &lit2, &lit3, + scc_pos_create()); + scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &lit1, &mul, + scc_pos_create()); + + // 赋值 a = 1 + 2 * 3; + scc_ast_expr_t a_ref1, assign1; + scc_ast_expr_identifier_init(&a_ref1, "a", scc_pos_create()); + scc_ast_expr_binary_init(&assign1, SCC_AST_OP_ASSIGN, &a_ref1, &add, + scc_pos_create()); + scc_ast_stmt_t assign1_stmt; + scc_ast_stmt_expr_init(&assign1_stmt, &assign1, scc_pos_create()); + + // 赋值 b = 7; + scc_ast_expr_t lit7; + scc_ast_expr_literal_int_init(&lit7, "7", false, scc_pos_create()); + scc_ast_expr_t b_ref1, assign2; + scc_ast_expr_identifier_init(&b_ref1, "b", scc_pos_create()); + scc_ast_expr_binary_init(&assign2, SCC_AST_OP_ASSIGN, &b_ref1, &lit7, + scc_pos_create()); + scc_ast_stmt_t assign2_stmt; + scc_ast_stmt_expr_init(&assign2_stmt, &assign2, scc_pos_create()); + + // 表达式 a - b + 1 + scc_ast_expr_t a_ref2, b_ref2, sub, add2, lit1_2; + scc_ast_expr_identifier_init(&a_ref2, "a", scc_pos_create()); + scc_ast_expr_identifier_init(&b_ref2, "b", scc_pos_create()); + scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &a_ref2, &b_ref2, + scc_pos_create()); + scc_ast_expr_literal_int_init(&lit1_2, "1", false, scc_pos_create()); + scc_ast_expr_binary_init(&add2, SCC_AST_OP_ADD, &sub, &lit1_2, + scc_pos_create()); + + // 赋值 a = a - b + 1; + scc_ast_expr_t a_ref3, assign3; + scc_ast_expr_identifier_init(&a_ref3, "a", scc_pos_create()); + scc_ast_expr_binary_init(&assign3, SCC_AST_OP_ASSIGN, &a_ref3, &add2, + scc_pos_create()); + scc_ast_stmt_t assign3_stmt; + scc_ast_stmt_expr_init(&assign3_stmt, &assign3, scc_pos_create()); + + // return a; + scc_ast_expr_t a_ref4; + scc_ast_expr_identifier_init(&a_ref4, "a", scc_pos_create()); + scc_ast_stmt_t ret_stmt; + scc_ast_stmt_return_init(&ret_stmt, &a_ref4, scc_pos_create()); + + // 复合语句块,按顺序放入 + scc_ast_block_item_vec_t items; + scc_vec_init(items); + scc_vec_push(items, (scc_ast_node_t *)&a_decl); + scc_vec_push(items, (scc_ast_node_t *)&b_decl); + scc_vec_push(items, (scc_ast_node_t *)&assign1_stmt); + scc_vec_push(items, (scc_ast_node_t *)&assign2_stmt); + scc_vec_push(items, (scc_ast_node_t *)&assign3_stmt); + scc_vec_push(items, (scc_ast_node_t *)&ret_stmt); + + scc_ast_stmt_t compound; + scc_ast_stmt_compound_init(&compound, &items, scc_pos_create()); + + // 函数类型 + scc_ast_type_t func_type; + scc_ast_type_function_init(&func_type, (scc_ast_type_t *)&int_type, + null, scc_pos_create()); + + scc_ast_decl_t func_decl; + scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, + scc_pos_create()); + + scc_ast_decl_vec_t tu_decls; + scc_vec_init(tu_decls); + scc_vec_push(tu_decls, &func_decl); + + scc_ast_translation_unit_t tu; + scc_ast_translation_unit_init(&tu, &tu_decls, scc_pos_create()); + + const char *input = "int main() {\n" + " int a;\n" + " int b;\n" + " a = 1 + 2 * 3;\n" + " b = 7;\n" + " a = a - b + 1;\n" + " return a;\n" + "}\n"; + + SCC_CHECK_AST(&tu.base, input, scc_parse_translation_unit); + } + + { + // 整数字面量 10 + scc_ast_expr_t lit10; + scc_ast_expr_literal_int_init(&lit10, "10", false, scc_pos_create()); + + // 变量声明 int x = 10; + scc_ast_decl_t x_decl; + scc_ast_decl_val_init(&x_decl, (scc_ast_type_t *)&int_type, "x", &lit10, + scc_pos_create()); + + // 表达式 x + 1 + scc_ast_expr_t x_ref1, lit1, add; + scc_ast_expr_identifier_init(&x_ref1, "x", scc_pos_create()); + scc_ast_expr_literal_int_init(&lit1, "1", false, scc_pos_create()); + scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &x_ref1, &lit1, + scc_pos_create()); + + // 赋值 x = x + 1 + scc_ast_expr_t x_ref2, assign; + scc_ast_expr_identifier_init(&x_ref2, "x", scc_pos_create()); + scc_ast_expr_binary_init(&assign, SCC_AST_OP_ASSIGN, &x_ref2, &add, + scc_pos_create()); + + // 表达式语句 + scc_ast_stmt_t assign_stmt; + scc_ast_stmt_expr_init(&assign_stmt, &assign, scc_pos_create()); + + // return x + scc_ast_expr_t x_ref3; + scc_ast_expr_identifier_init(&x_ref3, "x", scc_pos_create()); + scc_ast_stmt_t ret_stmt; + scc_ast_stmt_return_init(&ret_stmt, &x_ref3, scc_pos_create()); + + // 复合语句块 + scc_ast_block_item_vec_t items; + scc_vec_init(items); + scc_vec_push(items, (scc_ast_node_t *)&x_decl); + scc_vec_push(items, (scc_ast_node_t *)&assign_stmt); + scc_vec_push(items, (scc_ast_node_t *)&ret_stmt); + + scc_ast_stmt_t compound; + scc_ast_stmt_compound_init(&compound, &items, scc_pos_create()); + + // 函数类型(返回 int,无参数) + scc_ast_type_t func_type; + scc_ast_type_function_init(&func_type, (scc_ast_type_t *)&int_type, + null, + scc_pos_create()); // null 表示无参数 + + // 函数声明 int main() { ... } + scc_ast_decl_t func_decl; + scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, + scc_pos_create()); + + // 翻译单元 + scc_ast_decl_vec_t tu_decls; + scc_vec_init(tu_decls); + scc_vec_push(tu_decls, &func_decl); + + scc_ast_translation_unit_t tu; + scc_ast_translation_unit_init(&tu, &tu_decls, scc_pos_create()); + + // 输入源代码 + const char *input = "int main() {\n" + " int x = 10;\n" + " x = x + 1;\n" + " return x;\n" + "}\n"; + + // 比较解析结果与期望 AST + SCC_CHECK_AST(&tu.base, input, scc_parse_translation_unit); + } + + { + scc_ast_decl_vec_t params; + scc_ast_decl_t param0; + scc_ast_decl_param_init(¶m0, (scc_ast_type_t *)&int_type, "a", + scc_pos_create()); + scc_ast_decl_t param1; + scc_ast_decl_param_init(¶m1, (scc_ast_type_t *)&int_type, "b", + scc_pos_create()); + scc_ast_decl_t param2; + scc_ast_decl_param_init(¶m2, (scc_ast_type_t *)&va_list_type, null, + scc_pos_create()); + scc_ast_decl_t *params_array[] = {¶m0, ¶m1, ¶m2}; + scc_vec_unsafe_from_static_array(params, params_array); + scc_ast_type_t decl_func_type; + scc_ast_type_function_init(&decl_func_type, (scc_ast_type_t *)&int_type, + ¶ms, scc_pos_create()); + scc_ast_decl_t decl_func; + scc_ast_decl_func_init(&decl_func, &decl_func_type, "add", null, + scc_pos_create()); + SCC_CHECK_AST(&decl_func.base, "int add(int a, int b, ...);", + scc_parse_declaration); + } + + { + scc_ast_decl_t typedef_decl; + scc_ast_decl_typedef_init(&typedef_decl, "int32_t", &int_type, + scc_pos_create()); + scc_ast_type_t typedef_type; + scc_ast_type_typedef_init(&typedef_type, "int32_t", &typedef_decl, + scc_pos_create()); + + scc_ast_decl_t i32a_decl; + scc_ast_decl_val_init(&i32a_decl, &typedef_type, "a", null, + scc_pos_create()); + + scc_ast_node_t *array[] = {&typedef_decl.base, &i32a_decl.base}; + scc_ast_stmt_t stmt; + scc_ast_block_item_vec_t items; + scc_vec_unsafe_from_static_array(items, array); + scc_ast_stmt_compound_init(&stmt, &items, scc_pos_create()); + SCC_CHECK_AST_WITH_SEMA(&stmt.base, "{typedef int int32_t;int32_t a;}", + scc_parse_statement); + + scc_ast_type_t void_ptr; + scc_ast_type_pointer_init(&void_ptr, &void_type, scc_pos_create()); + scc_ast_decl_t void_ptr_decl; + scc_ast_decl_typedef_init(&void_ptr_decl, "void_ptr", &void_ptr, + scc_pos_create()); + scc_ast_type_t void_ptr_type; + scc_ast_type_typedef_init(&void_ptr_type, "void_ptr", &void_ptr_decl, + scc_pos_create()); + + scc_ast_decl_t void_ptr_a_decl; + scc_ast_decl_val_init(&void_ptr_a_decl, &void_ptr_type, "a", null, + scc_pos_create()); + + scc_ast_node_t *array2[] = {&void_ptr_decl.base, &void_ptr_a_decl.base}; + scc_vec_unsafe_from_static_array(items, array2); + scc_ast_stmt_compound_init(&stmt, &items, scc_pos_create()); + SCC_CHECK_AST_WITH_SEMA(&stmt.base, + "{typedef void* void_ptr; void_ptr a;}", + scc_parse_statement); + SCC_CHECK_AST_WITH_SEMA(&void_ptr_decl.base, + "typedef void * void_ptr; ", + scc_parse_declaration); + } + + { + // struct { int x; } (匿名结构体定义) + scc_ast_decl_t field; + scc_ast_decl_val_init(&field, (scc_ast_type_t *)&int_type, "x", null, + scc_pos_create()); + scc_ast_decl_vec_t fields; + scc_vec_init(fields); + scc_vec_push(fields, &field); + + scc_ast_decl_t struct_def; + scc_ast_decl_struct_init(&struct_def, null, &fields, scc_pos_create()); + SCC_CHECK_AST(&struct_def.base, "struct { int x;};", + scc_parse_declaration); + + scc_ast_type_t struct_type; + scc_ast_type_struct_init(&struct_type, null, &struct_def, + scc_pos_create()); + scc_ast_type_t typedef_type; + scc_ast_type_typedef_init(&typedef_type, "struct_t", &struct_def, + scc_pos_create()); + scc_ast_decl_t typedef_decl; + scc_ast_decl_typedef_init(&typedef_decl, "struct_t", &struct_type, + scc_pos_create()); + SCC_CHECK_AST_WITH_SEMA(&typedef_decl.base, + "typedef struct { int x; } struct_t;", + scc_parse_declaration); + + scc_ast_decl_t typedef_impl_decl; + scc_ast_decl_val_init(&typedef_impl_decl, &typedef_type, "a", null, + scc_pos_create()); + scc_ast_node_t *array[] = {&typedef_decl.base, &typedef_impl_decl.base}; + scc_ast_stmt_t stmt; + scc_ast_block_item_vec_t items; + scc_vec_unsafe_from_static_array(items, array); + scc_ast_stmt_compound_init(&stmt, &items, scc_pos_create()); + SCC_CHECK_AST_WITH_SEMA( + &stmt.base, "{typedef struct { int x; } struct_t; struct_t a;}", + scc_parse_statement); + } + + { + scc_ast_decl_t type_decl; + scc_ast_decl_typedef_init(&type_decl, "size_t", &int_type, + scc_pos_create()); + scc_ast_type_t type_type; + scc_ast_type_typedef_init(&type_type, "size_t", &type_decl, + scc_pos_create()); + + scc_ast_decl_t param1; + scc_ast_decl_param_init(¶m1, &type_type, "a", scc_pos_create()); + scc_ast_decl_t param2; + scc_ast_decl_param_init(¶m2, &int_type, "b", scc_pos_create()); + scc_ast_decl_t param3; + scc_ast_decl_param_init(¶m3, &va_list_type, null, scc_pos_create()); + scc_ast_decl_t *params_array[] = {¶m1, ¶m2, ¶m3}; + scc_ast_decl_vec_t func_params; + scc_vec_unsafe_from_static_array(func_params, params_array); + scc_ast_type_t func_type; + + scc_ast_type_t return_type; + + scc_ast_type_pointer_init(&return_type, &void_type, scc_pos_create()); + scc_ast_type_function_init(&func_type, &return_type, &func_params, + scc_pos_create()); + scc_ast_decl_t func_decl; + scc_ast_decl_func_init(&func_decl, &func_type, "func", null, + scc_pos_create()); + + scc_ast_decl_t *decls_array[] = {&type_decl, &func_decl}; + scc_ast_translation_unit_t tu; + scc_ast_decl_vec_t decls; + scc_vec_unsafe_from_static_array(decls, decls_array); + scc_ast_translation_unit_init(&tu, &decls, scc_pos_create()); + SCC_CHECK_AST_WITH_SEMA(&tu.base, + "typedef int size_t;" + "void *func(size_t a, int b, ...);", + scc_parse_translation_unit); + + scc_ast_type_t type_func_ptr_type; + scc_ast_type_pointer_init(&type_func_ptr_type, &func_type, + scc_pos_create()); + scc_ast_decl_t type_func_ptr_decl; + scc_ast_decl_typedef_init(&type_func_ptr_decl, "func_t", + &type_func_ptr_type, scc_pos_create()); + scc_ast_decl_t *decls_array2[] = {&type_decl, &type_func_ptr_decl}; + scc_vec_unsafe_from_static_array(decls, decls_array2); + scc_ast_translation_unit_init(&tu, &decls, scc_pos_create()); + SCC_CHECK_AST_WITH_SEMA( + &tu.base, + "typedef int size_t;" + "typedef void *(*func_t)(size_t a, int b, ...);", + scc_parse_translation_unit); + } + + { + // 1. 构造参数类型:volatile const char *restrict,并附加 register + // 存储类 + scc_ast_type_t char_type; + scc_ast_type_builtin_init(&char_type, SCC_AST_BUILTIN_TYPE_CHAR, + scc_pos_create()); + char_type.quals.is_const = true; // const + char_type.quals.is_volatile = true; // volatile + + scc_ast_type_t ptr_to_char; + scc_ast_type_pointer_init(&ptr_to_char, &char_type, scc_pos_create()); + ptr_to_char.quals.is_restrict = true; // restrict限定指针 + ptr_to_char.quals.is_register = true; // register存储类(作用于参数) + + // 2. 参数声明 + scc_ast_decl_t param_decl; + scc_ast_decl_param_init(¶m_decl, &ptr_to_char, "fmt", + scc_pos_create()); + + // 3. 返回类型:void * + scc_ast_type_t void_type; + scc_ast_type_builtin_init(&void_type, SCC_AST_BUILTIN_TYPE_VOID, + scc_pos_create()); + scc_ast_type_t ptr_to_void; + scc_ast_type_pointer_init(&ptr_to_void, &void_type, scc_pos_create()); + + // 4. 参数列表 + scc_ast_decl_vec_t params; + scc_vec_init(params); + scc_vec_push(params, ¶m_decl); + + // 5. 函数类型(包含 static 和 inline) + scc_ast_type_t func_type; + scc_ast_type_function_init(&func_type, &ptr_to_void, ¶ms, + scc_pos_create()); + func_type.quals.is_static = true; + func_type.quals.is_inline = true; + + // 6. 函数声明 + scc_ast_decl_t decl; + scc_ast_decl_func_init(&decl, &func_type, "call", null, + scc_pos_create()); + + // 7. 与解析结果比较 + SCC_CHECK_AST_WITH_SEMA(&decl.base, + "static inline void *call(volatile register " + "const char *restrict fmt);", + scc_parse_declaration); + } + + { + scc_ast_expr_t lvalue; + scc_ast_expr_lvalue_init(&lvalue, &void_type, scc_pos_create()); + + scc_ast_expr_t lhs1; + scc_ast_expr_member_init(&lhs1, &lvalue, "data", scc_pos_create()); + scc_ast_expr_t lhs2; + scc_ast_expr_member_init(&lhs2, &lvalue, "size", scc_pos_create()); + scc_ast_expr_t lhs3; + scc_ast_expr_member_init(&lhs3, &lvalue, "cap", scc_pos_create()); + + scc_ast_expr_t rl0; + scc_ast_expr_literal_int_init(&rl0, "0", false, scc_pos_create()); + scc_ast_type_t void_ptr; + scc_ast_type_pointer_init(&void_ptr, &void_type, scc_pos_create()); + scc_ast_expr_t rhs1; + scc_ast_expr_cast_init(&rhs1, &void_ptr, &rl0, scc_pos_create()); + scc_ast_expr_t rhs2; + scc_ast_expr_literal_int_init(&rhs2, "0", false, scc_pos_create()); + scc_ast_expr_t rhs3; + scc_ast_expr_literal_int_init(&rhs3, "0", false, scc_pos_create()); + + scc_ast_expr_vec_t lhs_exprs; + scc_ast_expr_t *lhs_array[] = {&lhs1, &lhs2, &lhs3}; + scc_vec_unsafe_from_static_array(lhs_exprs, lhs_array); + + scc_ast_expr_vec_t rhs_exprs; + scc_ast_expr_t *rhs_array[] = {&rhs1, &rhs2, &rhs3}; + scc_vec_unsafe_from_static_array(rhs_exprs, rhs_array); + + scc_ast_expr_t expr; + scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs, + scc_pos_create()); + + // FIXME use real records type + SCC_CHECK_AST(&expr.base, + "(void){.data = ((void *)0), .size = 0, .cap = 0}", + scc_parse_expression); + + scc_ast_stmt_t stmt; + scc_ast_stmt_return_init(&stmt, &expr, scc_pos_create()); + SCC_CHECK_AST( + &stmt.base, + "return (void){.data = (void *)0, .size = 0, .cap = 0 }; ", + scc_parse_statement); + + scc_ast_expr_t lhs4; + scc_ast_expr_t lhs5; + scc_ast_expr_member_init(&lhs4, &lvalue, "a", scc_pos_create()); + scc_ast_expr_member_init(&lhs5, &lhs4, "b", scc_pos_create()); + scc_ast_expr_t lhs6; + scc_ast_expr_t lhs7; + scc_ast_expr_member_init(&lhs6, &lvalue, "c", scc_pos_create()); + scc_ast_expr_array_subscript_init(&lhs7, &lhs6, &rl0, scc_pos_create()); + + scc_ast_expr_t *lhs_array_hard[] = {&lhs5, &lhs7}; + scc_vec_unsafe_from_static_array(lhs_exprs, lhs_array_hard); + scc_ast_expr_t *rhs_array_hard[] = {&rhs2, &rhs3}; + scc_vec_unsafe_from_static_array(rhs_exprs, rhs_array_hard); + scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs, + scc_pos_create()); + SCC_CHECK_AST(&expr.base, "(void){.a.b = 0, .c[0] = 0}", + scc_parse_expression); + } + + { + // 测试 struct S; 仅标记声明 + { + scc_ast_decl_t struct_decl; + scc_ast_decl_vec_t empty_members; + scc_vec_init(empty_members); + scc_ast_decl_struct_init(&struct_decl, "S", &empty_members, + scc_pos_create()); + SCC_CHECK_AST(&struct_decl.base, "struct S;", + scc_parse_declaration); + } + + // 测试 union U; 仅标记声明 + { + scc_ast_decl_t union_decl; + scc_ast_decl_vec_t empty_members; + scc_vec_init(empty_members); + scc_ast_decl_union_init(&union_decl, "U", &empty_members, + scc_pos_create()); + SCC_CHECK_AST(&union_decl.base, "union U;", scc_parse_declaration); + } + + // 测试 enum E; 仅标记声明 + { + scc_ast_decl_t enum_decl; + scc_ast_decl_vec_t empty_enumerators; + scc_vec_init(empty_enumerators); + scc_ast_decl_enum_init(&enum_decl, "E", &empty_enumerators, + scc_pos_create()); + SCC_CHECK_AST(&enum_decl.base, "enum E;", scc_parse_declaration); + } + } + + { + scc_ast_stmt_t continue_stmt; + scc_ast_stmt_continue_init(&continue_stmt, scc_pos_create()); + scc_ast_stmt_t stmt; + scc_ast_stmt_label_init(&stmt, "NEXT", &continue_stmt, + scc_pos_create()); + SCC_CHECK_AST(&stmt.base, "NEXT: continue;", scc_parse_statement); + } + + { + // 测试 int a = *(int*)b; + { + // 构造类型 int* + scc_ast_type_t ptr_to_int; + scc_ast_type_pointer_init(&ptr_to_int, (scc_ast_type_t *)&int_type, + scc_pos_create()); + + // 标识符 b + scc_ast_expr_t b_expr; + scc_ast_expr_identifier_init(&b_expr, "b", scc_pos_create()); + + // 类型转换 (int*)b + scc_ast_expr_t cast_expr; + scc_ast_expr_cast_init(&cast_expr, &ptr_to_int, &b_expr, + scc_pos_create()); + + // 解引用 *(int*)b + scc_ast_expr_t deref_expr; + scc_ast_expr_unary_init(&deref_expr, SCC_AST_OP_INDIRECTION, + &cast_expr, scc_pos_create()); + + // 声明 int a = *(int*)b; + scc_ast_decl_t decl; + scc_ast_decl_val_init(&decl, (scc_ast_type_t *)&int_type, "a", + &deref_expr, scc_pos_create()); + + SCC_CHECK_AST(&decl.base, "int a = *(int*)b;", + scc_parse_declaration); + } + + // 测试 int a, b; + { + scc_ast_decl_t decl_a, decl_b; + scc_ast_decl_val_init(&decl_a, (scc_ast_type_t *)&int_type, "a", + null, scc_pos_create()); + scc_ast_decl_val_init(&decl_b, (scc_ast_type_t *)&int_type, "b", + null, scc_pos_create()); + + scc_ast_decl_vec_t decl_vec; + scc_vec_init(decl_vec); + scc_vec_push(decl_vec, &decl_a); + scc_vec_push(decl_vec, &decl_b); + + scc_ast_decl_t decl_list; + scc_ast_decl_list_init(&decl_list, &decl_vec, + scc_pos_create()); // 假设存在该函数 + + SCC_CHECK_AST(&decl_list.base, "int a, b;", scc_parse_declaration); + } + + // 测试 int a = 1, b = 2; + { + scc_ast_expr_t lit1, lit2; + scc_ast_expr_literal_int_init(&lit1, "1", false, scc_pos_create()); + scc_ast_expr_literal_int_init(&lit2, "2", false, scc_pos_create()); + + scc_ast_decl_t decl_a, decl_b; + scc_ast_decl_val_init(&decl_a, (scc_ast_type_t *)&int_type, "a", + &lit1, scc_pos_create()); + scc_ast_decl_val_init(&decl_b, (scc_ast_type_t *)&int_type, "b", + &lit2, scc_pos_create()); + + scc_ast_decl_vec_t decl_vec; + scc_vec_init(decl_vec); + scc_vec_push(decl_vec, &decl_a); + scc_vec_push(decl_vec, &decl_b); + + scc_ast_decl_t decl_list; + scc_ast_decl_list_init(&decl_list, &decl_vec, + scc_pos_create()); // 假设存在该函数 + + SCC_CHECK_AST(&decl_list.base, "int a = 1, b = 2;", + scc_parse_declaration); + } + // 测试 "struct list_head *next, *prev;" + { + // 构造 struct list_head 类型(不完整) + scc_ast_type_t struct_list_head; + scc_ast_type_struct_init(&struct_list_head, "list_head", null, + scc_pos_create()); + + // 构造两个指针类型(分别用于 next 和 prev,指向同一结构体) + scc_ast_type_t ptr_to_struct1, ptr_to_struct2; + scc_ast_type_pointer_init(&ptr_to_struct1, &struct_list_head, + scc_pos_create()); + scc_ast_type_pointer_init(&ptr_to_struct2, &struct_list_head, + scc_pos_create()); + + // 构造变量声明 next 和 prev + scc_ast_decl_t next_decl, prev_decl; + scc_ast_decl_val_init(&next_decl, &ptr_to_struct1, "next", null, + scc_pos_create()); + scc_ast_decl_val_init(&prev_decl, &ptr_to_struct2, "prev", null, + scc_pos_create()); + + // 构造声明列表 + scc_ast_decl_vec_t decl_vec; + scc_vec_init(decl_vec); + scc_vec_push(decl_vec, &next_decl); + scc_vec_push(decl_vec, &prev_decl); + scc_ast_decl_t decl_list; + scc_ast_decl_list_init(&decl_list, &decl_vec, scc_pos_create()); + + SCC_CHECK_AST(&decl_list.base, "struct list_head *next, *prev;", + scc_parse_declaration); + } + + // 测试 "typedef struct { int a; } struct_t, *struct_ptr_t;" + { + // 构造字段 int a; + scc_ast_decl_t field_a; + scc_ast_decl_val_init(&field_a, (scc_ast_type_t *)&int_type, "a", + null, scc_pos_create()); + + scc_ast_decl_vec_t fields; + scc_vec_init(fields); + scc_vec_push(fields, &field_a); + + // 构造匿名结构体定义声明 + scc_ast_decl_t struct_def; + scc_ast_decl_struct_init(&struct_def, null, &fields, + scc_pos_create()); // fields 被移动 + + // 构造匿名结构体类型 + scc_ast_type_t anon_struct_type; + scc_ast_type_struct_init(&anon_struct_type, null, &struct_def, + scc_pos_create()); + + // 构造指针类型指向该匿名结构体 + scc_ast_type_t ptr_to_anon; + scc_ast_type_pointer_init(&ptr_to_anon, &anon_struct_type, + scc_pos_create()); + + // 构造 typedef 声明 struct_t + scc_ast_decl_t typedef_struct_t; + scc_ast_decl_typedef_init(&typedef_struct_t, "struct_t", + &anon_struct_type, scc_pos_create()); + + // 构造 typedef 声明 struct_ptr_t + scc_ast_decl_t typedef_struct_ptr_t; + scc_ast_decl_typedef_init(&typedef_struct_ptr_t, "struct_ptr_t", + &ptr_to_anon, scc_pos_create()); + + // 构造声明列表 + scc_ast_decl_vec_t typedef_vec; + scc_vec_init(typedef_vec); + scc_vec_push(typedef_vec, &typedef_struct_t); + scc_vec_push(typedef_vec, &typedef_struct_ptr_t); + scc_ast_decl_t decl_list; + scc_ast_decl_list_init(&decl_list, &typedef_vec, scc_pos_create()); + + SCC_CHECK_AST(&decl_list.base, + "typedef struct { int a; } struct_t, *struct_ptr_t;", + scc_parse_declaration); + } + "__scc_builtin_va_arg(ag, int)"; + "__scc_builtin_va_arg(ag, long long)"; + "typedef struct a;int a;struct a b;"; + } + + { + // int (*(*)(void))[5] (指向函数的指针,该函数返回指向数组的指针) + // 步骤: + // 1) 数组类型:int [5] + scc_ast_expr_t size_5; + scc_ast_expr_literal_int_init(&size_5, "5", false, scc_pos_create()); + scc_ast_type_t array_of_5_int; + scc_ast_type_array_init(&array_of_5_int, (scc_ast_type_t *)&int_type, + &size_5, scc_pos_create()); + + // 2) 函数类型:返回指向数组的指针,无参数 + scc_ast_type_t ptr_to_array; + scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int, + scc_pos_create()); + scc_ast_type_t func_type; + scc_ast_decl_vec_t func_params; + scc_ast_decl_t void_decl; + scc_ast_decl_param_init(&void_decl, &void_type, null, scc_pos_create()); + scc_ast_decl_t *array[] = {&void_decl}; + scc_vec_unsafe_from_static_array(func_params, array); + scc_ast_type_function_init(&func_type, &ptr_to_array, &func_params, + scc_pos_create()); // 无参数 + + // 3) 指向该函数的指针 + scc_ast_type_t ptr_to_func; + scc_ast_type_pointer_init(&ptr_to_func, &func_type, scc_pos_create()); + + scc_ast_decl_t ptr_to_func_decl; + scc_ast_decl_val_init(&ptr_to_func_decl, &ptr_to_func, "foo", null, + scc_pos_create()); + SCC_CHECK_AST(&ptr_to_func_decl.base, "int (*(*foo)(void))[5];", + scc_parse_declaration); + + scc_ast_decl_t typedef_func_decl; + scc_ast_decl_typedef_init(&typedef_func_decl, "func_t", &ptr_to_func, + scc_pos_create()); + scc_ast_type_t typedef_func_type; + scc_ast_type_typedef_init(&typedef_func_type, "func_t", + &typedef_func_decl, scc_pos_create()); + scc_ast_decl_t func_hard_decl; + scc_ast_type_t func_hard_type; + + scc_ast_decl_t param1; + scc_ast_decl_param_init(¶m1, &ptr_to_func, "bar", scc_pos_create()); + scc_ast_decl_t param2; + scc_ast_decl_param_init(¶m2, &typedef_func_type, "a", + scc_pos_create()); + scc_ast_decl_t param3; + scc_ast_decl_param_init(¶m1, &va_list_type, null, scc_pos_create()); + scc_ast_decl_t *func_hard_array[] = {¶m1, ¶m2, ¶m3}; + scc_ast_decl_vec_t func_hard_params; + scc_vec_unsafe_from_static_array(func_hard_params, func_hard_array); + scc_ast_type_function_init(&func_hard_type, &ptr_to_array, + &func_hard_params, scc_pos_create()); + scc_ast_decl_func_init(&func_hard_decl, &func_hard_type, "bar", null, + scc_pos_create()); + + scc_ast_decl_vec_t decls; + scc_ast_decl_t *decls_array[] = { + &typedef_func_decl, + &func_hard_decl, + }; + scc_vec_unsafe_from_static_array(decls, decls_array); + scc_ast_translation_unit_t tu; + scc_ast_translation_unit_init(&tu, &decls, scc_pos_create()); + // SCC_CHECK_AST_WITH_SEMA( + // &tu.base, + // "typedef int (*(*func_t)(void))[5];" + // "int (*(*(bar)(int(*(*foo)(void))[5], func_t a, + // ...))(void))[5];", scc_parse_translation_unit); + } +} + +TEST_LIST = { + {"parser_unit", test_parser_unit}, + {null, null}, +}; diff --git a/libs/parser/tests/test_parser_unit.c b/libs/parser/tests/test_parser_unit.c deleted file mode 100644 index 38be178..0000000 --- a/libs/parser/tests/test_parser_unit.c +++ /dev/null @@ -1,1806 +0,0 @@ -#include -#include -#include -#include -#include -#include - -typedef scc_ast_node_t *(*scc_parse_node_func)(scc_parser_t *parser); - -static scc_ast_node_t *process_input(const char *input, - scc_parse_node_func parse_func, - cbool need_sema) { - int res = 0; - scc_sstream_t mem_stream; - res = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false, - 16); - Assert(res == 0); - - scc_lexer_t lexer; - scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream)); - - scc_lexer_tok_ring_t *tok_ring = scc_lexer_to_ring(&lexer, 64, false); - - scc_parser_t parser; - if (need_sema) { - scc_sema_callbacks_t sema_callbacks; - scc_sema_init(&sema_callbacks); - scc_parser_init(&parser, tok_ring, &sema_callbacks); - } else { - scc_parser_init(&parser, tok_ring, null); - } - - scc_ast_node_t *ret = parse_func(&parser); - - cbool not_eof = false; - scc_ring_not_eof(*parser.ring, not_eof); - if (not_eof == true) { - // FIXME MAYBE free - LOG_ERROR("Didn't consume all tokens"); - return null; - } - - scc_lexer_drop_ring(parser.ring); - scc_parser_drop(&parser); - scc_lexer_drop(&lexer); - scc_sstream_drop(&mem_stream); - return ret; -} - -typedef void (*scc_tree_dump_output_t)(void *userdata, const char *fmt, ...); - -#define BUFFER_SIZE (4096) -char expect_buffer[BUFFER_SIZE]; -char output_buffer[BUFFER_SIZE]; - -static void dump2buffer(void *_buffer, const char *fmt, ...) { - char *buffer = _buffer; - va_list args; - va_start(args, fmt); - int res = scc_vsnprintf(buffer + strlen(buffer), - BUFFER_SIZE - strlen(buffer) - 1, fmt, args); - Assert(res > 0); - va_end(args); -} - -static void _scc_check_ast(scc_ast_node_t *expect_node_ptr, const char *str, - scc_parse_node_func parse_func, cbool need_sema) { - scc_ast_node_t *output_node_ptr = process_input(str, parse_func, need_sema); - scc_tree_dump_ctx_t ctx; - expect_buffer[0] = '\n', expect_buffer[1] = '\0'; - scc_tree_dump_ctx_init(&ctx, true, dump2buffer, expect_buffer); - scc_ast_dump_node(&ctx, expect_node_ptr); - scc_tree_dump_ctx_drop(&ctx); - output_buffer[0] = '\n', output_buffer[1] = '\0'; - scc_tree_dump_ctx_init(&ctx, true, dump2buffer, output_buffer); - scc_ast_dump_node(&ctx, output_node_ptr); - scc_tree_dump_ctx_drop(&ctx); -} - -#define SCC_CHECK_AST_WITH_SEMA(expect_node_ptr, str, parse_func) \ - do { \ - _scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func, \ - true); \ - TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \ - TEST_MSG("Expected: %s", expect_buffer); \ - TEST_MSG("Produced: %s", output_buffer); \ - } while (0); - -#define SCC_CHECK_AST(expect_node_ptr, str, parse_func) \ - do { \ - _scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func, \ - false); \ - TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \ - TEST_MSG("Expected: %s", expect_buffer); \ - TEST_MSG("Produced: %s", output_buffer); \ - } while (0); - -static void test_parser_unit(void) { - // 1. 变量声明 int a; - { - scc_ast_decl_t int_decl; - scc_ast_decl_val_init(&int_decl, &scc_ast_builtin_type_int, "a", null, - scc_pos_create()); - SCC_CHECK_AST(&int_decl.base, "int a;", scc_parse_declaration); - } - - // 2. 函数声明 int main(void) {} - { - // 构造函数类型:返回 int,参数为空 - scc_ast_type_t func_type; - scc_ast_decl_vec_t func_params; - scc_ast_decl_t void_decl; - scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null, - scc_pos_create()); - scc_ast_decl_t *array[] = {&void_decl}; - scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, - &func_params, scc_pos_create()); - // 构造复合语句块(空) - scc_ast_stmt_t compound; - scc_ast_stmt_compound_init(&compound, null, scc_pos_create()); - - // 构造函数声明 - scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, - scc_pos_create()); - - SCC_CHECK_AST(&func_decl.base, "int main(void) {}", - scc_parse_declaration); - } - - // 3. 翻译单元包含一个函数定义 - { - scc_ast_type_t func_type; - scc_ast_decl_vec_t func_params; - scc_ast_decl_t void_decl; - scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null, - scc_pos_create()); - scc_ast_decl_t *array[] = {&void_decl}; - scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, - &func_params, scc_pos_create()); - - scc_ast_stmt_t compound; - scc_ast_stmt_compound_init(&compound, null, scc_pos_create()); - - scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, - scc_pos_create()); - - // 构造翻译单元 - scc_ast_decl_vec_t tu_decls; - scc_vec_init(tu_decls); - scc_vec_push(tu_decls, &func_decl); - - scc_ast_translation_unit_t tu; - scc_ast_translation_unit_init(&tu, &tu_decls, scc_pos_create()); - - SCC_CHECK_AST(&tu.base, "int main(void) {}", - scc_parse_translation_unit); - } - - // 4. 带返回语句的函数 int main(void) { return 65536; } - { - // 返回语句中的整数常量 - scc_ast_expr_t ret_val; - scc_ast_expr_literal_int_init(&ret_val, "65536", false, - scc_pos_create()); - - scc_ast_stmt_t ret_stmt; - scc_ast_stmt_return_init(&ret_stmt, &ret_val, scc_pos_create()); - - // 复合语句包含该返回语句 - scc_ast_block_item_vec_t items; - scc_vec_init(items); - scc_vec_push(items, (scc_ast_node_t *)&ret_stmt); - - scc_ast_stmt_t compound; - scc_ast_stmt_compound_init(&compound, &items, - scc_pos_create()); // items 被移动 - - // 函数类型 - scc_ast_type_t func_type; - scc_ast_decl_vec_t func_params; - scc_ast_decl_t void_decl; - scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null, - scc_pos_create()); - scc_ast_decl_t *array[] = {&void_decl}; - scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, - &func_params, scc_pos_create()); - - scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, - scc_pos_create()); - - scc_ast_decl_vec_t tu_decls; - scc_vec_init(tu_decls); - scc_vec_push(tu_decls, &func_decl); - - scc_ast_translation_unit_t tu; - scc_ast_translation_unit_init(&tu, &tu_decls, scc_pos_create()); - - SCC_CHECK_AST(&tu.base, "int main(void) { return 65536; }", - scc_parse_translation_unit); - } - - // 5. 多语句函数(复杂示例) - { - // 变量声明 int a; - scc_ast_decl_t a_decl; - scc_ast_decl_val_init(&a_decl, &scc_ast_builtin_type_int, "a", null, - scc_pos_create()); - - // 变量声明 int b; - scc_ast_decl_t b_decl; - scc_ast_decl_val_init(&b_decl, &scc_ast_builtin_type_int, "b", null, - scc_pos_create()); - - // 表达式 1 + 2 * 3 - scc_ast_expr_t lit1, lit2, lit3, mul, add; - scc_ast_expr_literal_int_init(&lit1, "1", false, scc_pos_create()); - scc_ast_expr_literal_int_init(&lit2, "2", false, scc_pos_create()); - scc_ast_expr_literal_int_init(&lit3, "3", false, scc_pos_create()); - scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &lit2, &lit3, - scc_pos_create()); - scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &lit1, &mul, - scc_pos_create()); - - // 赋值 a = 1 + 2 * 3; - scc_ast_expr_t a_ref1, assign1; - scc_ast_expr_identifier_init(&a_ref1, "a", scc_pos_create()); - scc_ast_expr_binary_init(&assign1, SCC_AST_OP_ASSIGN, &a_ref1, &add, - scc_pos_create()); - scc_ast_stmt_t assign1_stmt; - scc_ast_stmt_expr_init(&assign1_stmt, &assign1, scc_pos_create()); - - // 赋值 b = 7; - scc_ast_expr_t lit7; - scc_ast_expr_literal_int_init(&lit7, "7", false, scc_pos_create()); - scc_ast_expr_t b_ref1, assign2; - scc_ast_expr_identifier_init(&b_ref1, "b", scc_pos_create()); - scc_ast_expr_binary_init(&assign2, SCC_AST_OP_ASSIGN, &b_ref1, &lit7, - scc_pos_create()); - scc_ast_stmt_t assign2_stmt; - scc_ast_stmt_expr_init(&assign2_stmt, &assign2, scc_pos_create()); - - // 表达式 a - b + 1 - scc_ast_expr_t a_ref2, b_ref2, sub, add2, lit1_2; - scc_ast_expr_identifier_init(&a_ref2, "a", scc_pos_create()); - scc_ast_expr_identifier_init(&b_ref2, "b", scc_pos_create()); - scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &a_ref2, &b_ref2, - scc_pos_create()); - scc_ast_expr_literal_int_init(&lit1_2, "1", false, scc_pos_create()); - scc_ast_expr_binary_init(&add2, SCC_AST_OP_ADD, &sub, &lit1_2, - scc_pos_create()); - - // 赋值 a = a - b + 1; - scc_ast_expr_t a_ref3, assign3; - scc_ast_expr_identifier_init(&a_ref3, "a", scc_pos_create()); - scc_ast_expr_binary_init(&assign3, SCC_AST_OP_ASSIGN, &a_ref3, &add2, - scc_pos_create()); - scc_ast_stmt_t assign3_stmt; - scc_ast_stmt_expr_init(&assign3_stmt, &assign3, scc_pos_create()); - - // return a; - scc_ast_expr_t a_ref4; - scc_ast_expr_identifier_init(&a_ref4, "a", scc_pos_create()); - scc_ast_stmt_t ret_stmt; - scc_ast_stmt_return_init(&ret_stmt, &a_ref4, scc_pos_create()); - - // 复合语句块,按顺序放入 - scc_ast_block_item_vec_t items; - scc_vec_init(items); - scc_vec_push(items, (scc_ast_node_t *)&a_decl); - scc_vec_push(items, (scc_ast_node_t *)&b_decl); - scc_vec_push(items, (scc_ast_node_t *)&assign1_stmt); - scc_vec_push(items, (scc_ast_node_t *)&assign2_stmt); - scc_vec_push(items, (scc_ast_node_t *)&assign3_stmt); - scc_vec_push(items, (scc_ast_node_t *)&ret_stmt); - - scc_ast_stmt_t compound; - scc_ast_stmt_compound_init(&compound, &items, scc_pos_create()); - - // 函数类型 - scc_ast_type_t func_type; - scc_ast_type_function_init(&func_type, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - null, scc_pos_create()); - - scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound, - scc_pos_create()); - - scc_ast_decl_vec_t tu_decls; - scc_vec_init(tu_decls); - scc_vec_push(tu_decls, &func_decl); - - scc_ast_translation_unit_t tu; - scc_ast_translation_unit_init(&tu, &tu_decls, scc_pos_create()); - - const char *input = "int main() {\n" - " int a;\n" - " int b;\n" - " a = 1 + 2 * 3;\n" - " b = 7;\n" - " a = a - b + 1;\n" - " return a;\n" - "}\n"; - - SCC_CHECK_AST(&tu.base, input, scc_parse_translation_unit); - } - - { - // 整数字面量 10 - scc_ast_expr_t lit10; - scc_ast_expr_literal_int_init(&lit10, "10", false, scc_pos_create()); - - // 变量声明 int x = 10; - scc_ast_decl_t x_decl; - scc_ast_decl_val_init(&x_decl, - (scc_ast_type_t *)&scc_ast_builtin_type_int, "x", - &lit10, scc_pos_create()); - - // 表达式 x + 1 - scc_ast_expr_t x_ref1, lit1, add; - scc_ast_expr_identifier_init(&x_ref1, "x", scc_pos_create()); - scc_ast_expr_literal_int_init(&lit1, "1", false, scc_pos_create()); - scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &x_ref1, &lit1, - scc_pos_create()); - - // 赋值 x = x + 1 - scc_ast_expr_t x_ref2, assign; - scc_ast_expr_identifier_init(&x_ref2, "x", scc_pos_create()); - scc_ast_expr_binary_init(&assign, SCC_AST_OP_ASSIGN, &x_ref2, &add, - scc_pos_create()); - - // 表达式语句 - scc_ast_stmt_t assign_stmt; - scc_ast_stmt_expr_init(&assign_stmt, &assign, scc_pos_create()); - - // return x - scc_ast_expr_t x_ref3; - scc_ast_expr_identifier_init(&x_ref3, "x", scc_pos_create()); - scc_ast_stmt_t ret_stmt; - scc_ast_stmt_return_init(&ret_stmt, &x_ref3, scc_pos_create()); - - // 复合语句块 - scc_ast_block_item_vec_t items; - scc_vec_init(items); - scc_vec_push(items, (scc_ast_node_t *)&x_decl); - scc_vec_push(items, (scc_ast_node_t *)&assign_stmt); - scc_vec_push(items, (scc_ast_node_t *)&ret_stmt); - - scc_ast_stmt_t compound; - scc_ast_stmt_compound_init(&compound, &items); - - // 函数类型(返回 int,无参数) - scc_ast_type_t func_type; - scc_ast_type_function_init(&func_type, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - null); // null 表示无参数 - - // 函数声明 int main() { ... } - scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound); - - // 翻译单元 - scc_ast_decl_vec_t tu_decls; - scc_vec_init(tu_decls); - scc_vec_push(tu_decls, &func_decl); - - scc_ast_translation_unit_t tu; - scc_ast_translation_unit_init(&tu, &tu_decls); - - // 输入源代码 - const char *input = "int main() {\n" - " int x = 10;\n" - " x = x + 1;\n" - " return x;\n" - "}\n"; - - // 比较解析结果与期望 AST - SCC_CHECK_AST(&tu.base, input, scc_parse_translation_unit); - } - - { - scc_ast_decl_vec_t params; - scc_ast_decl_t param0; - scc_ast_decl_param_init( - ¶m0, (scc_ast_type_t *)&scc_ast_builtin_type_int, "a"); - scc_ast_decl_t param1; - scc_ast_decl_param_init( - ¶m1, (scc_ast_type_t *)&scc_ast_builtin_type_int, "b"); - scc_ast_decl_t param2; - scc_ast_decl_param_init( - ¶m2, (scc_ast_type_t *)&scc_ast_builtin_type_va_list, null); - scc_ast_decl_t *params_array[] = {¶m0, ¶m1, ¶m2}; - scc_vec_unsafe_from_static_array(params, params_array); - scc_ast_type_t decl_func_type; - scc_ast_type_function_init(&decl_func_type, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - ¶ms); - scc_ast_decl_t decl_func; - scc_ast_decl_func_init(&decl_func, &decl_func_type, "add", null); - SCC_CHECK_AST(&decl_func.base, "int add(int a, int b, ...);", - scc_parse_declaration); - } - - { - scc_ast_decl_t typedef_decl; - scc_ast_decl_typedef_init(&typedef_decl, "int32_t", - &scc_ast_builtin_type_int); - scc_ast_type_t typedef_type; - scc_ast_type_typedef_init(&typedef_type, "int32_t", &typedef_decl); - - scc_ast_decl_t i32a_decl; - scc_ast_decl_val_init(&i32a_decl, &typedef_type, "a", null); - - scc_ast_node_t *array[] = {&typedef_decl.base, &i32a_decl.base}; - scc_ast_stmt_t stmt; - scc_ast_block_item_vec_t items; - scc_vec_unsafe_from_static_array(items, array); - scc_ast_stmt_compound_init(&stmt, &items); - SCC_CHECK_AST_WITH_SEMA(&stmt.base, "{typedef int int32_t;int32_t a;}", - scc_parse_statement); - - scc_ast_type_t void_ptr; - scc_ast_type_pointer_init(&void_ptr, &scc_ast_builtin_type_void); - scc_ast_decl_t void_ptr_decl; - scc_ast_decl_typedef_init(&void_ptr_decl, "void_ptr", &void_ptr); - scc_ast_type_t void_ptr_type; - scc_ast_type_typedef_init(&void_ptr_type, "void_ptr", &void_ptr_decl); - - scc_ast_decl_t void_ptr_a_decl; - scc_ast_decl_val_init(&void_ptr_a_decl, &void_ptr_type, "a", null); - - scc_ast_node_t *array2[] = {&void_ptr_decl.base, &void_ptr_a_decl.base}; - scc_vec_unsafe_from_static_array(items, array2); - scc_ast_stmt_compound_init(&stmt, &items); - SCC_CHECK_AST_WITH_SEMA(&stmt.base, - "{typedef void* void_ptr; void_ptr a;}", - scc_parse_statement); - SCC_CHECK_AST_WITH_SEMA(&void_ptr_decl.base, "typedef void *void_ptr;", - scc_parse_declaration); - } - - { - // struct { int x; } (匿名结构体定义) - scc_ast_decl_t field; - scc_ast_decl_val_init( - &field, (scc_ast_type_t *)&scc_ast_builtin_type_int, "x", null); - scc_ast_decl_vec_t fields; - scc_vec_init(fields); - scc_vec_push(fields, &field); - - scc_ast_decl_t struct_def; - scc_ast_decl_struct_init(&struct_def, null, &fields); - SCC_CHECK_AST(&struct_def.base, "struct { int x; };", - scc_parse_declaration); - - scc_ast_type_t struct_type; - scc_ast_type_struct_init(&struct_type, null, &struct_def); - scc_ast_type_t typedef_type; - scc_ast_type_typedef_init(&typedef_type, "struct_t", &struct_def); - scc_ast_decl_t typedef_decl; - scc_ast_decl_typedef_init(&typedef_decl, "struct_t", &struct_type); - SCC_CHECK_AST_WITH_SEMA(&typedef_decl.base, - "typedef struct { int x; } struct_t;", - scc_parse_declaration); - - scc_ast_decl_t typedef_impl_decl; - scc_ast_decl_val_init(&typedef_impl_decl, &typedef_type, "a", null); - scc_ast_node_t *array[] = {&typedef_decl.base, &typedef_impl_decl.base}; - scc_ast_stmt_t stmt; - scc_ast_block_item_vec_t items; - scc_vec_unsafe_from_static_array(items, array); - scc_ast_stmt_compound_init(&stmt, &items); - SCC_CHECK_AST_WITH_SEMA( - &stmt.base, "{typedef struct { int x; } struct_t; struct_t a;}", - scc_parse_statement); - } - - { - scc_ast_decl_t type_decl; - scc_ast_decl_typedef_init(&type_decl, "size_t", - &scc_ast_builtin_type_long_long); - scc_ast_type_t type_type; - scc_ast_type_typedef_init(&type_type, "size_t", &type_decl); - - scc_ast_decl_t param1; - scc_ast_decl_param_init(¶m1, &type_type, "a"); - scc_ast_decl_t param2; - scc_ast_decl_param_init(¶m2, &scc_ast_builtin_type_int, "b"); - scc_ast_decl_t param3; - scc_ast_decl_param_init(¶m3, &scc_ast_builtin_type_va_list, null); - scc_ast_decl_t *params_array[] = {¶m1, ¶m2, ¶m3}; - scc_ast_decl_vec_t func_params; - scc_vec_unsafe_from_static_array(func_params, params_array); - scc_ast_type_t func_type; - - scc_ast_type_t return_type; - - scc_ast_type_pointer_init(&return_type, &scc_ast_builtin_type_void); - scc_ast_type_function_init(&func_type, &return_type, &func_params); - scc_ast_decl_t func_decl; - scc_ast_decl_func_init(&func_decl, &func_type, "func", null); - - scc_ast_decl_t *decls_array[] = {&type_decl, &func_decl}; - scc_ast_translation_unit_t tu; - scc_ast_decl_vec_t decls; - scc_vec_unsafe_from_static_array(decls, decls_array); - scc_ast_translation_unit_init(&tu, &decls); - SCC_CHECK_AST_WITH_SEMA(&tu.base, - "typedef long long size_t;" - "void *func(size_t a, int b, ...);", - scc_parse_translation_unit); - - scc_ast_type_t type_func_ptr_type; - scc_ast_type_pointer_init(&type_func_ptr_type, &func_type); - scc_ast_decl_t type_func_ptr_decl; - scc_ast_decl_typedef_init(&type_func_ptr_decl, "func_t", - &type_func_ptr_type); - scc_ast_decl_t *decls_array2[] = {&type_decl, &type_func_ptr_decl}; - scc_vec_unsafe_from_static_array(decls, decls_array2); - scc_ast_translation_unit_init(&tu, &decls); - SCC_CHECK_AST_WITH_SEMA( - &tu.base, - "typedef long long size_t;" - "typedef void *(*func_t)(size_t a, int b, ...);", - scc_parse_translation_unit); - } - - { - // 1. 构造参数类型:volatile const char *restrict,并附加 register - // 存储类 - scc_ast_type_t char_type; - _scc_ast_type_builtin_init(&char_type, SCC_AST_BUILTIN_TYPE_CHAR); - char_type.quals.is_const = true; // const - char_type.quals.is_volatile = true; // volatile - - scc_ast_type_t ptr_to_char; - scc_ast_type_pointer_init(&ptr_to_char, &char_type); - ptr_to_char.quals.is_restrict = true; // restrict 限定指针 - ptr_to_char.quals.is_register = true; // register 存储类(作用于参数) - - // 2. 参数声明 - scc_ast_decl_t param_decl; - scc_ast_decl_param_init(¶m_decl, &ptr_to_char, "fmt"); - - // 3. 返回类型:void * - scc_ast_type_t void_type; - _scc_ast_type_builtin_init(&void_type, SCC_AST_BUILTIN_TYPE_VOID); - scc_ast_type_t ptr_to_void; - scc_ast_type_pointer_init(&ptr_to_void, &void_type); - - // 4. 参数列表 - scc_ast_decl_vec_t params; - scc_vec_init(params); - scc_vec_push(params, ¶m_decl); - - // 5. 函数类型(包含 static 和 inline) - scc_ast_type_t func_type; - scc_ast_type_function_init(&func_type, &ptr_to_void, ¶ms); - func_type.quals.is_static = true; - func_type.quals.is_inline = true; - - // 6. 函数声明 - scc_ast_decl_t decl; - scc_ast_decl_func_init(&decl, &func_type, "call", null); - - // 7. 与解析结果比较 - SCC_CHECK_AST_WITH_SEMA(&decl.base, - "static inline void *call(volatile register " - "const char *restrict fmt);", - scc_parse_declaration); - } - - { - scc_ast_expr_t lvalue; - scc_ast_expr_lvalue_init(&lvalue, &scc_ast_builtin_type_void); - - scc_ast_expr_t lhs1; - scc_ast_expr_member_init(&lhs1, &lvalue, "data"); - scc_ast_expr_t lhs2; - scc_ast_expr_member_init(&lhs2, &lvalue, "size"); - scc_ast_expr_t lhs3; - scc_ast_expr_member_init(&lhs3, &lvalue, "cap"); - - scc_ast_expr_t rl0; - scc_ast_expr_literal_int_init(&rl0, "0", false); - scc_ast_type_t void_ptr; - scc_ast_type_pointer_init(&void_ptr, &scc_ast_builtin_type_void); - scc_ast_expr_t rhs1; - scc_ast_expr_cast_init(&rhs1, &void_ptr, &rl0); - scc_ast_expr_t rhs2; - scc_ast_expr_literal_int_init(&rhs2, "0", false); - scc_ast_expr_t rhs3; - scc_ast_expr_literal_int_init(&rhs3, "0", false); - - scc_ast_expr_vec_t lhs_exprs; - scc_ast_expr_t *lhs_array[] = {&lhs1, &lhs2, &lhs3}; - scc_vec_unsafe_from_static_array(lhs_exprs, lhs_array); - - scc_ast_expr_vec_t rhs_exprs; - scc_ast_expr_t *rhs_array[] = {&rhs1, &rhs2, &rhs3}; - scc_vec_unsafe_from_static_array(rhs_exprs, rhs_array); - - scc_ast_expr_t expr; - scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs); - - // FIXME use real records type - SCC_CHECK_AST(&expr.base, - "(void){.data = ((void *)0), .size = 0, .cap = 0}", - scc_parse_expression); - - scc_ast_stmt_t stmt; - scc_ast_stmt_return_init(&stmt, &expr); - SCC_CHECK_AST(&stmt.base, - "return (void){.data = (void *)0, .size = 0, .cap = 0};", - scc_parse_statement); - - scc_ast_expr_t lhs4; - scc_ast_expr_t lhs5; - scc_ast_expr_member_init(&lhs4, &lvalue, "a"); - scc_ast_expr_member_init(&lhs5, &lhs4, "b"); - scc_ast_expr_t lhs6; - scc_ast_expr_t lhs7; - scc_ast_expr_member_init(&lhs6, &lvalue, "c"); - scc_ast_expr_array_subscript_init(&lhs7, &lhs6, &rl0); - - scc_ast_expr_t *lhs_array_hard[] = {&lhs5, &lhs7}; - scc_vec_unsafe_from_static_array(lhs_exprs, lhs_array_hard); - scc_ast_expr_t *rhs_array_hard[] = {&rhs2, &rhs3}; - scc_vec_unsafe_from_static_array(rhs_exprs, rhs_array_hard); - scc_ast_expr_compound_init(&expr, &lvalue, &lhs_exprs, &rhs_exprs); - SCC_CHECK_AST(&expr.base, "(void){.a.b = 0, .c[0] = 0}", - scc_parse_expression); - } - - { - // 测试 struct S; 仅标记声明 - { - scc_ast_decl_t struct_decl; - scc_ast_decl_vec_t empty_members; - scc_vec_init(empty_members); - scc_ast_decl_struct_init(&struct_decl, "S", &empty_members); - SCC_CHECK_AST(&struct_decl.base, "struct S;", - scc_parse_declaration); - } - - // 测试 union U; 仅标记声明 - { - scc_ast_decl_t union_decl; - scc_ast_decl_vec_t empty_members; - scc_vec_init(empty_members); - scc_ast_decl_union_init(&union_decl, "U", &empty_members); - SCC_CHECK_AST(&union_decl.base, "union U;", scc_parse_declaration); - } - - // 测试 enum E; 仅标记声明 - { - scc_ast_decl_t enum_decl; - scc_ast_expr_vec_t empty_enumerators; - scc_vec_init(empty_enumerators); - scc_ast_decl_enum_init(&enum_decl, "E", &empty_enumerators); - SCC_CHECK_AST(&enum_decl.base, "enum E;", scc_parse_declaration); - } - } - - { - scc_ast_stmt_t continue_stmt; - scc_ast_stmt_continue_init(&continue_stmt); - scc_ast_stmt_t stmt; - scc_ast_stmt_label_init(&stmt, "NEXT", &continue_stmt); - SCC_CHECK_AST(&stmt.base, "NEXT: continue;", scc_parse_statement); - - scc_ast_expr_t str; - scc_ast_expr_literal_string_init(&str, "\"ab\"", false); - SCC_CHECK_AST(&str.base, "\"a\" \"b\"", scc_parse_expression); - } - - { - // 测试 int a = *(int*)b; - { - // 构造类型 int* - scc_ast_type_t ptr_to_int; - scc_ast_type_pointer_init( - &ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int); - - // 标识符 b - scc_ast_expr_t b_expr; - scc_ast_expr_identifier_init(&b_expr, "b"); - - // 类型转换 (int*)b - scc_ast_expr_t cast_expr; - scc_ast_expr_cast_init(&cast_expr, &ptr_to_int, &b_expr); - - // 解引用 *(int*)b - scc_ast_expr_t deref_expr; - scc_ast_expr_unary_init(&deref_expr, SCC_AST_OP_INDIRECTION, - &cast_expr); - - // 声明 int a = *(int*)b; - scc_ast_decl_t decl; - scc_ast_decl_val_init(&decl, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - "a", &deref_expr); - - SCC_CHECK_AST(&decl.base, "int a = *(int*)b;", - scc_parse_declaration); - } - - // 测试 int a, b; - { - scc_ast_decl_t decl_a, decl_b; - scc_ast_decl_val_init(&decl_a, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - "a", null); - scc_ast_decl_val_init(&decl_b, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - "b", null); - - scc_ast_decl_vec_t decl_vec; - scc_vec_init(decl_vec); - scc_vec_push(decl_vec, &decl_a); - scc_vec_push(decl_vec, &decl_b); - - scc_ast_decl_t decl_list; - scc_ast_decl_list_init(&decl_list, &decl_vec); // 假设存在该函数 - - SCC_CHECK_AST(&decl_list.base, "int a, b;", scc_parse_declaration); - } - - // 测试 int a = 1, b = 2; - { - scc_ast_expr_t lit1, lit2; - scc_ast_expr_literal_int_init(&lit1, "1", false); - scc_ast_expr_literal_int_init(&lit2, "2", false); - - scc_ast_decl_t decl_a, decl_b; - scc_ast_decl_val_init(&decl_a, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - "a", &lit1); - scc_ast_decl_val_init(&decl_b, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - "b", &lit2); - - scc_ast_decl_vec_t decl_vec; - scc_vec_init(decl_vec); - scc_vec_push(decl_vec, &decl_a); - scc_vec_push(decl_vec, &decl_b); - - scc_ast_decl_t decl_list; - scc_ast_decl_list_init(&decl_list, &decl_vec); // 假设存在该函数 - - SCC_CHECK_AST(&decl_list.base, "int a = 1, b = 2;", - scc_parse_declaration); - } - // 测试 "struct list_head *next, *prev;" - { - // 构造 struct list_head 类型(不完整) - scc_ast_type_t struct_list_head; - scc_ast_type_struct_init(&struct_list_head, "list_head", null); - - // 构造两个指针类型(分别用于 next 和 prev,指向同一结构体) - scc_ast_type_t ptr_to_struct1, ptr_to_struct2; - scc_ast_type_pointer_init(&ptr_to_struct1, &struct_list_head); - scc_ast_type_pointer_init(&ptr_to_struct2, &struct_list_head); - - // 构造变量声明 next 和 prev - scc_ast_decl_t next_decl, prev_decl; - scc_ast_decl_val_init(&next_decl, &ptr_to_struct1, "next", null); - scc_ast_decl_val_init(&prev_decl, &ptr_to_struct2, "prev", null); - - // 构造声明列表 - scc_ast_decl_vec_t decl_vec; - scc_vec_init(decl_vec); - scc_vec_push(decl_vec, &next_decl); - scc_vec_push(decl_vec, &prev_decl); - scc_ast_decl_t decl_list; - scc_ast_decl_list_init(&decl_list, &decl_vec); - - SCC_CHECK_AST(&decl_list.base, "struct list_head *next, *prev;", - scc_parse_declaration); - } - - // 测试 "typedef struct { int a; } struct_t, *struct_ptr_t;" - { - // 构造字段 int a; - scc_ast_decl_t field_a; - scc_ast_decl_val_init(&field_a, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - "a", null); - - scc_ast_decl_vec_t fields; - scc_vec_init(fields); - scc_vec_push(fields, &field_a); - - // 构造匿名结构体定义声明 - scc_ast_decl_t struct_def; - scc_ast_decl_struct_init(&struct_def, null, - &fields); // fields 被移动 - - // 构造匿名结构体类型 - scc_ast_type_t anon_struct_type; - scc_ast_type_struct_init(&anon_struct_type, null, &struct_def); - - // 构造指针类型指向该匿名结构体 - scc_ast_type_t ptr_to_anon; - scc_ast_type_pointer_init(&ptr_to_anon, &anon_struct_type); - - // 构造 typedef 声明 struct_t - scc_ast_decl_t typedef_struct_t; - scc_ast_decl_typedef_init(&typedef_struct_t, "struct_t", - &anon_struct_type); - - // 构造 typedef 声明 struct_ptr_t - scc_ast_decl_t typedef_struct_ptr_t; - scc_ast_decl_typedef_init(&typedef_struct_ptr_t, "struct_ptr_t", - &ptr_to_anon); - - // 构造声明列表 - scc_ast_decl_vec_t typedef_vec; - scc_vec_init(typedef_vec); - scc_vec_push(typedef_vec, &typedef_struct_t); - scc_vec_push(typedef_vec, &typedef_struct_ptr_t); - scc_ast_decl_t decl_list; - scc_ast_decl_list_init(&decl_list, &typedef_vec); - - SCC_CHECK_AST(&decl_list.base, - "typedef struct { int a; } struct_t, *struct_ptr_t;", - scc_parse_declaration); - } - "__scc_builtin_va_arg(ag, int)"; - "__scc_builtin_va_arg(ag, long long)"; - "typedef struct a;int a;struct a b;"; - } - - { - // int (*(*)(void))[5] (指向函数的指针,该函数返回指向数组的指针) - // 步骤: - // 1) 数组类型:int [5] - scc_ast_expr_t size_5; - scc_ast_expr_literal_int_init(&size_5, "5", false); - scc_ast_type_t array_of_5_int; - scc_ast_type_array_init(&array_of_5_int, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - &size_5); - - // 2) 函数类型:返回指向数组的指针,无参数 - scc_ast_type_t ptr_to_array; - scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int); - scc_ast_type_t func_type; - scc_ast_decl_vec_t func_params; - scc_ast_decl_t void_decl; - scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null); - scc_ast_decl_t *array[] = {&void_decl}; - scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_type, &ptr_to_array, - &func_params); // 无参数 - - // 3) 指向该函数的指针 - scc_ast_type_t ptr_to_func; - scc_ast_type_pointer_init(&ptr_to_func, &func_type); - - scc_ast_decl_t ptr_to_func_decl; - scc_ast_decl_val_init(&ptr_to_func_decl, &ptr_to_func, "foo", null); - SCC_CHECK_AST(&ptr_to_func_decl.base, "int (*(*foo)(void))[5];", - scc_parse_declaration); - - scc_ast_decl_t typedef_func_decl; - scc_ast_decl_typedef_init(&typedef_func_decl, "func_t", &ptr_to_func); - scc_ast_type_t typedef_func_type; - scc_ast_type_typedef_init(&typedef_func_type, "func_t", - &typedef_func_decl); - scc_ast_decl_t func_hard_decl; - scc_ast_type_t func_hard_type; - - scc_ast_decl_t param1; - scc_ast_decl_param_init(¶m1, &ptr_to_func, "bar"); - scc_ast_decl_t param2; - scc_ast_decl_param_init(¶m2, &typedef_func_type, "a"); - scc_ast_decl_t param3; - scc_ast_decl_param_init(¶m1, &scc_ast_builtin_type_va_list, null); - scc_ast_decl_t *func_hard_array[] = {¶m1, ¶m2, ¶m3}; - scc_ast_decl_vec_t func_hard_params; - scc_vec_unsafe_from_static_array(func_hard_params, func_hard_array); - scc_ast_type_function_init(&func_hard_type, &ptr_to_array, - &func_hard_params); - scc_ast_decl_func_init(&func_hard_decl, &func_hard_type, "bar", null); - - scc_ast_decl_vec_t decls; - scc_ast_decl_t *decls_array[] = { - &typedef_func_decl, - &func_hard_decl, - }; - scc_vec_unsafe_from_static_array(decls, decls_array); - scc_ast_translation_unit_t tu; - scc_ast_translation_unit_init(&tu, &decls); - // SCC_CHECK_AST_WITH_SEMA( - // &tu.base, - // "typedef int (*(*func_t)(void))[5];" - // "int (*(*(bar)(int(*(*foo)(void))[5], func_t a, - // ...))(void))[5];", scc_parse_translation_unit); - } -} - -static void test_parser_expression(void) { - // 1. 基本表达式 - { - scc_ast_expr_t ident; - scc_ast_expr_identifier_init(&ident, "x"); - SCC_CHECK_AST(&ident.base, "x", scc_parse_expression); - - scc_ast_expr_t int_lit; - scc_ast_expr_literal_int_init(&int_lit, "42", false); - SCC_CHECK_AST(&int_lit.base, "42", scc_parse_expression); - - scc_ast_expr_t str_lit; - scc_ast_expr_literal_string_init(&str_lit, "\"hello\"", false); - SCC_CHECK_AST(&str_lit.base, "\"hello\"", scc_parse_expression); - - // 括号表达式(解析器应直接返回内部表达式) - scc_ast_expr_t paren_ident; - scc_ast_expr_identifier_init(&paren_ident, "y"); - SCC_CHECK_AST(&paren_ident.base, "(y)", scc_parse_expression); - } - - // 2. 后缀表达式 - { - // 数组下标 a[10] - scc_ast_expr_t a, index, subscript; - scc_ast_expr_identifier_init(&a, "a"); - scc_ast_expr_literal_int_init(&index, "10", false); - scc_ast_expr_array_subscript_init(&subscript, &a, &index); - SCC_CHECK_AST(&subscript.base, "a[10]", scc_parse_expression); - - // 函数调用 f() - scc_ast_expr_t f; - scc_ast_expr_identifier_init(&f, "f"); - scc_ast_expr_vec_t args; - scc_vec_init(args); - scc_ast_expr_t call; - scc_ast_expr_t callee1; - scc_ast_expr_identifier_init(&callee1, "f"); - scc_ast_expr_call_init(&call, &callee1, - &args); // 使用函数名,target 在语义分析时填充 - SCC_CHECK_AST(&call.base, "f()", scc_parse_expression); - - // 函数调用带参数 f(1, x) - scc_ast_expr_t arg1, arg2; - scc_ast_expr_literal_int_init(&arg1, "1", false); - scc_ast_expr_identifier_init(&arg2, "x"); - scc_ast_expr_vec_t args2; - scc_vec_init(args2); - scc_vec_push(args2, &arg1); - scc_vec_push(args2, &arg2); - scc_ast_expr_t callee2; - scc_ast_expr_identifier_init(&callee2, "f"); - scc_ast_expr_t call2; - scc_ast_expr_call_init(&call2, &callee2, &args2); - SCC_CHECK_AST(&call2.base, "f(1, x)", scc_parse_expression); - - // 成员访问 . - scc_ast_expr_t s, dot; - scc_ast_expr_identifier_init(&s, "s"); - scc_ast_expr_member_init(&dot, &s, "field"); - SCC_CHECK_AST(&dot.base, "s.field", scc_parse_expression); - - // 指针成员访问 -> - scc_ast_expr_t p, arrow; - scc_ast_expr_identifier_init(&p, "p"); - scc_ast_expr_ptr_member_init(&arrow, &p, "field"); - SCC_CHECK_AST(&arrow.base, "p->field", scc_parse_expression); - - // 后缀 ++/-- - scc_ast_expr_t x, post_inc, post_dec; - scc_ast_expr_identifier_init(&x, "x"); - scc_ast_expr_unary_init(&post_inc, SCC_AST_OP_POSTFIX_INCREMENT, &x); - scc_ast_expr_unary_init(&post_dec, SCC_AST_OP_POSTFIX_DECREMENT, &x); - SCC_CHECK_AST(&post_inc.base, "x++", scc_parse_expression); - SCC_CHECK_AST(&post_dec.base, "x--", scc_parse_expression); - } - - // 3. 一元表达式 - { - scc_ast_expr_t x; - scc_ast_expr_identifier_init(&x, "x"); - - scc_ast_expr_t pre_inc; - scc_ast_expr_unary_init(&pre_inc, SCC_AST_OP_PREFIX_INCREMENT, &x); - SCC_CHECK_AST(&pre_inc.base, "++x", scc_parse_expression); - - scc_ast_expr_t pre_dec; - scc_ast_expr_unary_init(&pre_dec, SCC_AST_OP_PREFIX_DECREMENT, &x); - SCC_CHECK_AST(&pre_dec.base, "--x", scc_parse_expression); - - scc_ast_expr_t addr; - scc_ast_expr_unary_init(&addr, SCC_AST_OP_ADDRESS_OF, &x); - SCC_CHECK_AST(&addr.base, "&x", scc_parse_expression); - - scc_ast_expr_t deref; - scc_ast_expr_unary_init(&deref, SCC_AST_OP_INDIRECTION, &x); - SCC_CHECK_AST(&deref.base, "*x", scc_parse_expression); - - scc_ast_expr_t plus; - scc_ast_expr_unary_init(&plus, SCC_AST_OP_UNARY_PLUS, &x); - SCC_CHECK_AST(&plus.base, "+x", scc_parse_expression); - - scc_ast_expr_t minus; - scc_ast_expr_unary_init(&minus, SCC_AST_OP_UNARY_MINUS, &x); - SCC_CHECK_AST(&minus.base, "-x", scc_parse_expression); - - scc_ast_expr_t bit_not; - scc_ast_expr_unary_init(&bit_not, SCC_AST_OP_BITWISE_NOT, &x); - SCC_CHECK_AST(&bit_not.base, "~x", scc_parse_expression); - - scc_ast_expr_t log_not; - scc_ast_expr_unary_init(&log_not, SCC_AST_OP_LOGICAL_NOT, &x); - SCC_CHECK_AST(&log_not.base, "!x", scc_parse_expression); - - // sizeof 表达式 - scc_ast_expr_t sizeof_x_expr; - scc_ast_expr_sizeof_init(&sizeof_x_expr, null, &x); - SCC_CHECK_AST(&sizeof_x_expr.base, "sizeof(x)", scc_parse_expression); - - scc_ast_expr_t sizeof_int_expr; - scc_ast_expr_sizeof_init(&sizeof_int_expr, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - null); - SCC_CHECK_AST(&sizeof_int_expr.base, "sizeof(int)", - scc_parse_expression); - } - - // 4. 类型转换(示例: (int)x ) - { - scc_ast_expr_t x; - scc_ast_expr_identifier_init(&x, "x"); - scc_ast_expr_t cast; - scc_ast_expr_cast_init(&cast, - (scc_ast_type_t *)&scc_ast_builtin_type_int, &x); - SCC_CHECK_AST(&cast.base, "(int)x", scc_parse_expression); - } - - // 5. 二元运算符优先级 - { - scc_ast_expr_t a, b, c, d; - scc_ast_expr_identifier_init(&a, "a"); - scc_ast_expr_identifier_init(&b, "b"); - scc_ast_expr_identifier_init(&c, "c"); - scc_ast_expr_identifier_init(&d, "d"); - - // a * b + c - scc_ast_expr_t mul, add; - scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &a, &b); - scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &mul, &c); - SCC_CHECK_AST(&add.base, "a * b + c", scc_parse_expression); - - // a - b - c => (a - b) - c - scc_ast_expr_t sub1, sub2; - scc_ast_expr_binary_init(&sub1, SCC_AST_OP_SUB, &a, &b); - scc_ast_expr_binary_init(&sub2, SCC_AST_OP_SUB, &sub1, &c); - SCC_CHECK_AST(&sub2.base, "a - b - c", scc_parse_expression); - - // a << b - scc_ast_expr_t shift; - scc_ast_expr_binary_init(&shift, SCC_AST_OP_LEFT_SHIFT, &a, &b); - SCC_CHECK_AST(&shift.base, "a << b", scc_parse_expression); - - // a < b - scc_ast_expr_t lt; - scc_ast_expr_binary_init(<, SCC_AST_OP_LESS, &a, &b); - SCC_CHECK_AST(<.base, "a < b", scc_parse_expression); - - // a == b - scc_ast_expr_t eq; - scc_ast_expr_binary_init(&eq, SCC_AST_OP_EQUAL, &a, &b); - SCC_CHECK_AST(&eq.base, "a == b", scc_parse_expression); - - // a & b ^ c | d - scc_ast_expr_t bitand, bitxor, bitor; - scc_ast_expr_binary_init(&bitand, SCC_AST_OP_BITWISE_AND, &a, &b); - scc_ast_expr_binary_init(&bitxor, SCC_AST_OP_BITWISE_XOR, &bitand, &c); - scc_ast_expr_binary_init(&bitor, SCC_AST_OP_BITWISE_OR, &bitxor, &d); - SCC_CHECK_AST(&bitor.base, "a & b ^ c | d", scc_parse_expression); - - // a && b || c - scc_ast_expr_t logand, logor; - scc_ast_expr_binary_init(&logand, SCC_AST_OP_LOGICAL_AND, &a, &b); - scc_ast_expr_binary_init(&logor, SCC_AST_OP_LOGICAL_OR, &logand, &c); - SCC_CHECK_AST(&logor.base, "a && b || c", scc_parse_expression); - } - - // 6. 三元运算符 - { - scc_ast_expr_t a, b, c; - scc_ast_expr_identifier_init(&a, "a"); - scc_ast_expr_identifier_init(&b, "b"); - scc_ast_expr_identifier_init(&c, "c"); - - // a ? b : c - scc_ast_expr_t cond1; - scc_ast_expr_cond_init(&cond1, &a, &b, &c); - SCC_CHECK_AST(&cond1.base, "a ? b : c", scc_parse_expression); - - // a ? b : c ? d : e => a ? b : (c ? d : e) - scc_ast_expr_t d, e; - scc_ast_expr_identifier_init(&d, "d"); - scc_ast_expr_identifier_init(&e, "e"); - scc_ast_expr_t inner, outer; - scc_ast_expr_cond_init(&inner, &c, &d, &e); - scc_ast_expr_cond_init(&outer, &a, &b, &inner); - SCC_CHECK_AST(&outer.base, "a ? b : c ? d : e", scc_parse_expression); - } - - // 7. 赋值运算符 - { - scc_ast_expr_t a, b, c; - scc_ast_expr_identifier_init(&a, "a"); - scc_ast_expr_identifier_init(&b, "b"); - scc_ast_expr_identifier_init(&c, "c"); - scc_ast_expr_t lit42; - scc_ast_expr_literal_int_init(&lit42, "42", false); - - // a = b = c - scc_ast_expr_t assign_inner, assign_outer; - scc_ast_expr_binary_init(&assign_inner, SCC_AST_OP_ASSIGN, &b, &c); - scc_ast_expr_binary_init(&assign_outer, SCC_AST_OP_ASSIGN, &a, - &assign_inner); - SCC_CHECK_AST(&assign_outer.base, "a = b = c", scc_parse_expression); - - // a = 42 - scc_ast_expr_t assign1; - scc_ast_expr_binary_init(&assign1, SCC_AST_OP_ASSIGN, &a, &lit42); - SCC_CHECK_AST(&assign1.base, "a = 42", scc_parse_expression); - - // a = a - b + 42 - scc_ast_expr_t sub, add, assign2; - scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &a, &b); - scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &sub, &lit42); - scc_ast_expr_binary_init(&assign2, SCC_AST_OP_ASSIGN, &a, &add); - SCC_CHECK_AST(&assign2.base, "a = a - b + 42", scc_parse_expression); - - // a += b - scc_ast_expr_t add_assign; - scc_ast_expr_binary_init(&add_assign, SCC_AST_OP_ASSIGN_ADD, &a, &b); - SCC_CHECK_AST(&add_assign.base, "a += b", scc_parse_expression); - } - - // 8. 逗号运算符 - { - scc_ast_expr_t a, b; - scc_ast_expr_identifier_init(&a, "a"); - scc_ast_expr_identifier_init(&b, "b"); - scc_ast_expr_t comma; - scc_ast_expr_binary_init(&comma, SCC_AST_OP_COMMA, &a, &b); - SCC_CHECK_AST(&comma.base, "a, b", scc_parse_expression); - } - - // 9. 混合优先级 - { - scc_ast_expr_t a, b, c, d; - scc_ast_expr_identifier_init(&a, "a"); - scc_ast_expr_identifier_init(&b, "b"); - scc_ast_expr_identifier_init(&c, "c"); - scc_ast_expr_identifier_init(&d, "d"); - - // a + b * c - d - scc_ast_expr_t mul, add, sub; - scc_ast_expr_binary_init(&mul, SCC_AST_OP_MUL, &b, &c); - scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &a, &mul); - scc_ast_expr_binary_init(&sub, SCC_AST_OP_SUB, &add, &d); - SCC_CHECK_AST(&sub.base, "a + b * c - d", scc_parse_expression); - - // *p++ - scc_ast_expr_t p, post_inc, deref; - scc_ast_expr_identifier_init(&p, "p"); - scc_ast_expr_unary_init(&post_inc, SCC_AST_OP_POSTFIX_INCREMENT, &p); - scc_ast_expr_unary_init(&deref, SCC_AST_OP_INDIRECTION, &post_inc); - SCC_CHECK_AST(&deref.base, "*p++", scc_parse_expression); - } -} - -static void test_parser_type(void) { - { - // 1. int - { - SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_int, "int", - scc_parse_type_name); - } - - // 2. int * - { - scc_ast_type_t ptr_to_int; - scc_ast_type_pointer_init( - &ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int); - SCC_CHECK_AST(&ptr_to_int.base, "int *", scc_parse_type_name); - } - - // 3. int *[3] - { - scc_ast_type_t ptr_to_int; - scc_ast_type_pointer_init( - &ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int); - - scc_ast_expr_t size_3; - scc_ast_expr_literal_int_init(&size_3, "3", false); - - scc_ast_type_t array_of_ptr; - scc_ast_type_array_init(&array_of_ptr, &ptr_to_int, &size_3); - SCC_CHECK_AST(&array_of_ptr.base, "int *[3]", scc_parse_type_name); - } - - // 4. int (*)[3] - { - scc_ast_expr_t size_3; - scc_ast_expr_literal_int_init(&size_3, "3", false); - - scc_ast_type_t array_of_int; - scc_ast_type_array_init(&array_of_int, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - &size_3); - - scc_ast_type_t ptr_to_array; - scc_ast_type_pointer_init(&ptr_to_array, &array_of_int); - SCC_CHECK_AST(&ptr_to_array.base, "int (*)[3]", - scc_parse_type_name); - } - - // 5. int (*)[*] - { - scc_ast_type_t array_of_int_var; - scc_ast_type_array_init(&array_of_int_var, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - null); // null 表示不定长数组 - - scc_ast_type_t ptr_to_array_var; - scc_ast_type_pointer_init(&ptr_to_array_var, &array_of_int_var); - SCC_CHECK_AST(&ptr_to_array_var.base, "int (*)[*]", - scc_parse_type_name); - } - - // 6. int *() - { - // 返回类型 int* - scc_ast_type_t ptr_to_int; - scc_ast_type_pointer_init( - &ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int); - - // 函数类型,返回 int*,无参数 - scc_ast_type_t func_type; - scc_ast_type_function_init(&func_type, &ptr_to_int, null); - SCC_CHECK_AST(&func_type.base, "int *()", scc_parse_type_name); - } - - // 7. int (*)(void) - { - // 函数类型,返回 int,无参数 - scc_ast_type_t func_void; - scc_ast_decl_vec_t func_params; - scc_ast_decl_t void_decl; - scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, - null); - scc_ast_decl_t *array[] = {&void_decl}; - scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init( - &func_void, (scc_ast_type_t *)&scc_ast_builtin_type_int, - &func_params); - - scc_ast_type_t ptr_to_func; - scc_ast_type_pointer_init(&ptr_to_func, &func_void); - SCC_CHECK_AST(&ptr_to_func.base, "int (*)(void)", - scc_parse_type_name); - } - - // 8. int (*const [])(unsigned int, ...) - { - // --- 构造参数列表 --- - // 第一个参数:unsigned int - scc_ast_decl_t param_uint; - scc_ast_decl_param_init( - ¶m_uint, - (scc_ast_type_t *)&scc_ast_builtin_type_unsigned_int, "u"); - - // 第二个参数:... 用内置 va_list 类型近似表示 - scc_ast_type_t va_list_type; - _scc_ast_type_builtin_init(&va_list_type, - SCC_AST_BUILTIN_TYPE_VA_LIST); - scc_ast_decl_t param_var; - scc_ast_decl_param_init(¶m_var, &va_list_type, "..."); - - scc_ast_decl_vec_t params; - scc_vec_init(params); - scc_vec_push(params, ¶m_uint); - scc_vec_push(params, ¶m_var); - - // --- 函数类型,返回 int --- - scc_ast_type_t func_type; - scc_ast_type_function_init( - &func_type, (scc_ast_type_t *)&scc_ast_builtin_type_int, - ¶ms); // params 被移动 - - // --- 指向函数的指针,带 const 限定 --- - scc_ast_type_t ptr_to_func; - scc_ast_type_pointer_init(&ptr_to_func, &func_type); - ptr_to_func.quals.is_const = true; // 设置 const - - // --- 数组,元素为上述 const 指针,大小未指定 --- - scc_ast_type_t array_of_ptr; - scc_ast_type_array_init(&array_of_ptr, &ptr_to_func, null); - - SCC_CHECK_AST(&array_of_ptr.base, - "int (*const [])(unsigned int, ...)", - scc_parse_type_name); - } - } - - // 1. 基本内置类型及组合 - { - // int - SCC_CHECK_AST(&scc_ast_builtin_type_int.base, "int", - scc_parse_type_name); - - // char - SCC_CHECK_AST(&scc_ast_builtin_type_char.base, "char", - scc_parse_type_name); - - // long long - SCC_CHECK_AST(&scc_ast_builtin_type_long_long.base, "long long", - scc_parse_type_name); - - // long long - SCC_CHECK_AST(&scc_ast_builtin_type_long_long.base, "long long int", - scc_parse_type_name); - - // short - SCC_CHECK_AST(&scc_ast_builtin_type_short.base, "short int", - scc_parse_type_name); - - // unsigned int - SCC_CHECK_AST(&scc_ast_builtin_type_unsigned_int.base, "unsigned int", - scc_parse_type_name); - - // float - SCC_CHECK_AST(&scc_ast_builtin_type_float.base, "float", - scc_parse_type_name); - - // double - SCC_CHECK_AST(&scc_ast_builtin_type_double.base, "double", - scc_parse_type_name); - - // void - SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_void, "void", - scc_parse_type_name); - - // bool - SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_bool, "bool", - scc_parse_type_name); - - // long double - SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_long_double, - "long double", scc_parse_type_name); - - // _Complex double - SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_complex_double, - "double complex", scc_parse_type_name); - } - - // 2. 带类型限定符的基本类型 (const, volatile) - { - // const int - scc_ast_type_t const_int = scc_ast_builtin_type_int; - const_int.quals.is_const = true; - SCC_CHECK_AST(&const_int.base, "const int", scc_parse_type_name); - - // volatile unsigned long - scc_ast_type_t volatile_ulong = scc_ast_builtin_type_unsigned_long; - volatile_ulong.quals.is_volatile = true; - SCC_CHECK_AST(&volatile_ulong.base, "volatile unsigned long", - scc_parse_type_name); - - // const volatile char - scc_ast_type_t const_volatile_char = scc_ast_builtin_type_char; - const_volatile_char.quals.is_const = true; - const_volatile_char.quals.is_volatile = true; - SCC_CHECK_AST(&const_volatile_char.base, "const volatile char", - scc_parse_type_name); - } - - // 3. 指针类型 - { - // int * - scc_ast_type_t ptr_to_int; - scc_ast_type_pointer_init(&ptr_to_int, - (scc_ast_type_t *)&scc_ast_builtin_type_int); - SCC_CHECK_AST(&ptr_to_int.base, "int *", scc_parse_type_name); - - // int ** - scc_ast_type_t ptr_to_ptr_to_int; - scc_ast_type_pointer_init(&ptr_to_ptr_to_int, &ptr_to_int); - SCC_CHECK_AST(&ptr_to_ptr_to_int.base, "int **", scc_parse_type_name); - - // int * const (const pointer to int) - scc_ast_type_t const_ptr_to_int; - scc_ast_type_pointer_init(&const_ptr_to_int, - (scc_ast_type_t *)&scc_ast_builtin_type_int); - const_ptr_to_int.quals.is_const = true; - SCC_CHECK_AST(&const_ptr_to_int.base, "int * const", - scc_parse_type_name); - - // const int * (pointer to const int) - scc_ast_type_t const_int_type = scc_ast_builtin_type_int; - const_int_type.quals.is_const = true; - scc_ast_type_t ptr_to_const_int; - scc_ast_type_pointer_init(&ptr_to_const_int, &const_int_type); - SCC_CHECK_AST(&ptr_to_const_int.base, "const int *", - scc_parse_type_name); - - // const int * const (const pointer to const int) - scc_ast_type_t const_ptr_to_const_int; - scc_ast_type_pointer_init(&const_ptr_to_const_int, &const_int_type); - const_ptr_to_const_int.quals.is_const = true; - SCC_CHECK_AST(&const_ptr_to_const_int.base, "const int * const", - scc_parse_type_name); - - // volatile int * restrict - scc_ast_type_t volatile_int = scc_ast_builtin_type_int; - volatile_int.quals.is_volatile = true; - scc_ast_type_t restrict_ptr_to_volatile_int; - scc_ast_type_pointer_init(&restrict_ptr_to_volatile_int, &volatile_int); - restrict_ptr_to_volatile_int.quals.is_restrict = true; - SCC_CHECK_AST(&restrict_ptr_to_volatile_int.base, - "volatile int * restrict", scc_parse_type_name); - } - - // 4. 数组类型 - { - // int [5] - scc_ast_expr_t size_5; - scc_ast_expr_literal_int_init(&size_5, "5", false); - scc_ast_type_t array_of_5_int; - scc_ast_type_array_init(&array_of_5_int, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - &size_5); - SCC_CHECK_AST(&array_of_5_int.base, "int [5]", scc_parse_type_name); - - // int [] (不完整类型) - scc_ast_type_t array_of_int_unknown; - scc_ast_type_array_init(&array_of_int_unknown, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - null); - SCC_CHECK_AST(&array_of_int_unknown.base, "int []", - scc_parse_type_name); - - // // int [*] (变长数组原型中的不定长数组) - // FIXME - // scc_ast_type_t array_of_int_var; - // scc_ast_type_array_init(&array_of_int_var, - // (scc_ast_type_t *)&scc_ast_builtin_type_int, - // null); - // // 注意:[*] 与 [] 在AST中目前无法区分,都使用 size=null - // // 表示。如果解析器需要区分,可能需要特殊处理。 这里暂时假设解析器对 - // [*] - // // 也生成 size=null 的数组节点。 - // SCC_CHECK_AST(&array_of_int_var.base, "int [*]", scc_parse_type); - - // int [5][3] (二维数组) - scc_ast_expr_t size_3; - scc_ast_expr_literal_int_init(&size_3, "3", false); - scc_ast_type_t inner_array; - scc_ast_type_array_init( - &inner_array, (scc_ast_type_t *)&scc_ast_builtin_type_int, &size_3); - scc_ast_type_t outer_array; - scc_ast_type_array_init(&outer_array, &inner_array, &size_5); - SCC_CHECK_AST(&outer_array.base, "int [5][3]", scc_parse_type_name); - - // int (*)[5] (指向数组的指针) 已在前面测试,这里重复以保持完整性 - scc_ast_type_t array_of_5_int2; - scc_ast_type_array_init(&array_of_5_int2, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - &size_5); - scc_ast_type_t ptr_to_array; - scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int2); - SCC_CHECK_AST(&ptr_to_array.base, "int (*)[5]", scc_parse_type_name); - - // int *[5] (指针数组) - scc_ast_type_t ptr_to_int2; - scc_ast_type_pointer_init(&ptr_to_int2, - (scc_ast_type_t *)&scc_ast_builtin_type_int); - scc_ast_type_t array_of_5_ptr; - scc_ast_type_array_init(&array_of_5_ptr, &ptr_to_int2, &size_5); - SCC_CHECK_AST(&array_of_5_ptr.base, "int *[5]", scc_parse_type_name); - - // const int [5] (数组元素为const int) - scc_ast_type_t const_int2 = scc_ast_builtin_type_int; - const_int2.quals.is_const = true; - scc_ast_type_t const_array; - scc_ast_type_array_init(&const_array, &const_int2, &size_5); - SCC_CHECK_AST(&const_array.base, "const int [5]", scc_parse_type_name); - } - - // 5. 函数类型 - { - // int (void) - scc_ast_type_t func_void; - scc_ast_decl_vec_t func_params; - scc_ast_decl_t void_decl; - scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null); - scc_ast_decl_t *array[] = {&void_decl}; - scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_void, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - &func_params); - SCC_CHECK_AST(&func_void.base, "int (void)", scc_parse_type_name); - - // // int () (无参数声明,非原型) - // // - // 在C中,空括号表示未指定参数,但AST中可能仍然用空参数列表表示。这里假设与 - // // (void) 相同。 - // SCC_CHECK_AST(&func_void.base, "int ()", scc_parse_type); - - // int (int, float) - scc_ast_decl_t param1, param2; - scc_ast_decl_param_init( - ¶m1, (scc_ast_type_t *)&scc_ast_builtin_type_int, null); - scc_ast_decl_param_init( - ¶m2, (scc_ast_type_t *)&scc_ast_builtin_type_float, null); - scc_ast_decl_vec_t params; - scc_vec_init(params); - scc_vec_push(params, ¶m1); - scc_vec_push(params, ¶m2); - - scc_ast_type_t func_with_params; - scc_ast_type_function_init(&func_with_params, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - ¶ms); - SCC_CHECK_AST(&func_with_params.base, "int (int, float)", - scc_parse_type_name); - - // int (int, ...) (可变参数) - scc_ast_decl_t param_int, param_var; - scc_ast_decl_param_init( - ¶m_int, (scc_ast_type_t *)&scc_ast_builtin_type_int, null); - scc_ast_type_t va_list_type; - _scc_ast_type_builtin_init(&va_list_type, SCC_AST_BUILTIN_TYPE_VA_LIST); - scc_ast_decl_param_init(¶m_var, &va_list_type, null); - scc_ast_decl_vec_t params_var; - scc_vec_init(params_var); - scc_vec_push(params_var, ¶m_int); - scc_vec_push(params_var, ¶m_var); - - scc_ast_type_t func_varargs; - scc_ast_type_function_init(&func_varargs, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - ¶ms_var); - SCC_CHECK_AST(&func_varargs.base, "int (int, ...)", - scc_parse_type_name); - - // int (*)(int) (函数指针) - scc_ast_decl_t param; - scc_ast_decl_param_init( - ¶m, (scc_ast_type_t *)&scc_ast_builtin_type_int, null); - scc_ast_decl_vec_t params2; - scc_vec_init(params2); - scc_vec_push(params2, ¶m); - - scc_ast_type_t func_type; - scc_ast_type_function_init( - &func_type, (scc_ast_type_t *)&scc_ast_builtin_type_int, ¶ms2); - scc_ast_type_t ptr_to_func; - scc_ast_type_pointer_init(&ptr_to_func, &func_type); - SCC_CHECK_AST(&ptr_to_func.base, "int (*)(int)", scc_parse_type_name); - } - - // 6. 函数指针和复杂声明符 - { - // int (*foo)(void) - // 这里应解析为类型名,但包含标识符?我们的解析函数是scc_parse_type,它应该解析类型名,不应包含标识符。 - // 所以跳过带标识符的,只测试抽象声明符。 - - // int (*(*)(void))[5] (指向函数的指针,该函数返回指向数组的指针) - // 步骤: - // 1) 数组类型:int [5] - scc_ast_expr_t size_5; - scc_ast_expr_literal_int_init(&size_5, "5", false); - scc_ast_type_t array_of_5_int; - scc_ast_type_array_init(&array_of_5_int, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - &size_5); - - // 2) 函数类型:返回指向数组的指针,无参数 - scc_ast_type_t ptr_to_array; - scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int); - scc_ast_type_t func_type; - scc_ast_decl_vec_t func_params; - scc_ast_decl_t void_decl; - scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null); - scc_ast_decl_t *array[] = {&void_decl}; - scc_vec_unsafe_from_static_array(func_params, array); - scc_ast_type_function_init(&func_type, &ptr_to_array, - &func_params); // 无参数 - - // 3) 指向该函数的指针 - scc_ast_type_t ptr_to_func; - scc_ast_type_pointer_init(&ptr_to_func, &func_type); - - SCC_CHECK_AST(&ptr_to_func.base, "int (*(*)(void))[5]", - scc_parse_type_name); - - // int (*(*)[5])(void) (指向数组的指针,数组元素为函数指针) - // 1) 函数类型:返回 int,无参数 - scc_ast_type_t func_type2; - scc_ast_decl_vec_t func_params2; - scc_vec_unsafe_from_static_array(func_params2, array); - scc_ast_type_function_init(&func_type2, - (scc_ast_type_t *)&scc_ast_builtin_type_int, - &func_params2); - - // 2) 指针指向该函数 - scc_ast_type_t ptr_to_func2; - scc_ast_type_pointer_init(&ptr_to_func2, &func_type2); - - // 3) 数组,元素为上述指针 - scc_ast_type_t array_of_ptr_to_func; - scc_ast_type_array_init(&array_of_ptr_to_func, &ptr_to_func2, &size_5); - - // 4) 指针指向该数组 - scc_ast_type_t ptr_to_array_of_ptr; - scc_ast_type_pointer_init(&ptr_to_array_of_ptr, &array_of_ptr_to_func); - SCC_CHECK_AST(&ptr_to_array_of_ptr.base, "int (*(*)[5])(void)", - scc_parse_type_name); - } - - // 7. 结构体/联合/枚举类型(标记和定义) - { - // struct S (不完整类型) - scc_ast_type_t struct_tag; - scc_ast_type_struct_init(&struct_tag, "S", - null); // name="S", members=null - SCC_CHECK_AST(&struct_tag.base, "struct S", scc_parse_type_name); - - // struct { int x; } (匿名结构体定义) - scc_ast_decl_t field; - scc_ast_decl_val_init( - &field, (scc_ast_type_t *)&scc_ast_builtin_type_int, "x", null); - scc_ast_decl_vec_t fields; - scc_vec_init(fields); - scc_vec_push(fields, &field); - - scc_ast_decl_t struct_def; - scc_ast_decl_struct_init(&struct_def, null, &fields); - scc_ast_type_t struct_type; - scc_ast_type_struct_init(&struct_type, null, &struct_def); - SCC_CHECK_AST(&struct_type.base, "struct { int x; }", - scc_parse_type_name); - scc_vec_init(fields); - scc_vec_push(fields, &field); - scc_ast_decl_struct_init(&struct_def, "A", &fields); - scc_ast_type_struct_init(&struct_type, "A", &struct_def); - SCC_CHECK_AST(&struct_type.base, "struct A { int x; }", - scc_parse_type_name); - - // union U (不完整类型) - scc_ast_type_t union_tag; - scc_ast_type_union_init(&union_tag, "U", null); - SCC_CHECK_AST(&union_tag.base, "union U", scc_parse_type_name); - - // union { int a; float b; } (匿名联合定义) - scc_ast_decl_t field_a, field_b; - scc_ast_decl_val_init( - &field_a, (scc_ast_type_t *)&scc_ast_builtin_type_int, "a", null); - scc_ast_decl_val_init( - &field_b, (scc_ast_type_t *)&scc_ast_builtin_type_float, "b", null); - scc_ast_decl_vec_t fields_union; - scc_vec_init(fields_union); - scc_vec_push(fields_union, &field_a); - scc_vec_push(fields_union, &field_b); - - scc_ast_decl_t union_def; - scc_ast_decl_union_init(&union_def, null, &fields_union); - scc_ast_type_t union_type; - scc_ast_type_union_init(&union_type, null, &union_def); - SCC_CHECK_AST(&union_type.base, "union { int a; float b; }", - scc_parse_type_name); - scc_ast_decl_union_init(&union_def, "Union", &fields_union); - scc_ast_type_union_init(&union_type, "Union", &union_def); - SCC_CHECK_AST(&union_type.base, "union Union { int a; float b; }", - scc_parse_type_name); - - // enum E (不完整类型) - scc_ast_type_t enum_tag; - scc_ast_type_enum_init(&enum_tag, "E", null); - SCC_CHECK_AST(&enum_tag.base, "enum E", scc_parse_type_name); - - // enum { RED, GREEN, BLUE } (匿名枚举定义) - scc_ast_expr_t red, green, blue; - scc_ast_expr_identifier_init(&red, "RED"); - scc_ast_expr_identifier_init(&green, "GREEN"); - scc_ast_expr_identifier_init(&blue, "BLUE"); - scc_ast_expr_vec_t enumerators; - scc_ast_expr_t *array[] = {&red, &green, &blue}; - scc_vec_unsafe_from_static_array(enumerators, array); - - scc_ast_decl_t enum_def; - scc_ast_decl_enum_init(&enum_def, null, &enumerators); - scc_ast_type_t enum_type; - scc_ast_type_enum_init(&enum_type, null, &enum_def); - SCC_CHECK_AST(&enum_type.base, "enum { RED, GREEN, BLUE }", - scc_parse_type_name); - - scc_vec_unsafe_from_static_array(enumerators, array); - scc_ast_decl_enum_init(&enum_def, "E", &enumerators); - scc_ast_type_enum_init(&enum_type, "E", &enum_def); - SCC_CHECK_AST(&enum_type.base, "enum E { RED, GREEN, BLUE, }", - scc_parse_type_name); - } - - // 8. typedef 类型 - { - // 假设存在 typedef int myint; 但类型解析时,遇到 myint - // 应得到对应的类型节点。 为了测试,我们直接构造一个 typedef 类型节点。 - // scc_ast_type_t myint_type; - // scc_ast_type_typedef_init(&myint_type, "myint", - // (scc_ast_type_t - // *)&scc_ast_builtin_type_int); - // SCC_CHECK_AST(&myint_type.base, "myint", scc_parse_type); - - // // myint * (指针指向 typedef 类型) - // scc_ast_type_t ptr_to_myint; - // scc_ast_type_pointer_init(&ptr_to_myint, &myint_type); - // SCC_CHECK_AST(&ptr_to_myint.base, "myint *", scc_parse_type); - } - - // 9. 混合复杂类型 - { - // const int * volatile (*)[10] - // 步骤: - // 1) const int - scc_ast_type_t const_int = scc_ast_builtin_type_int; - const_int.quals.is_const = true; - - // 2) 指针指向 const int (普通指针) - scc_ast_type_t ptr_to_const_int; - scc_ast_type_pointer_init(&ptr_to_const_int, &const_int); - // 该指针本身是 volatile 限定?语法上 "const int * volatile" 表示指针是 - // volatile 的,指向 const int。 - ptr_to_const_int.quals.is_volatile = true; - - // 3) 数组,元素为上述指针,大小为10 - scc_ast_expr_t size_10; - scc_ast_expr_literal_int_init(&size_10, "10", false); - scc_ast_type_t array_of_ptr; - scc_ast_type_array_init(&array_of_ptr, &ptr_to_const_int, &size_10); - - // 4) 指针指向该数组 - scc_ast_type_t ptr_to_array; - scc_ast_type_pointer_init(&ptr_to_array, &array_of_ptr); - SCC_CHECK_AST(&ptr_to_array.base, "const int * volatile (*)[10]", - scc_parse_type_name); - - // float (*(*)(int, ...))() - // 1) float 类型作为内部函数返回类型 - // 2) 构建返回 float 的函数类型,无参数(或者参数为空) - scc_ast_type_t func_ret_float; - scc_ast_type_function_init( - &func_ret_float, (scc_ast_type_t *)&scc_ast_builtin_type_float, - null); - - // 3) 指针指向该函数 - scc_ast_type_t ptr_to_func_ret_float; - scc_ast_type_pointer_init(&ptr_to_func_ret_float, &func_ret_float); - - // 4) 外层函数类型,返回上述指针,参数为 (int, ...) - scc_ast_decl_t param_int, param_var; - scc_ast_decl_param_init( - ¶m_int, (scc_ast_type_t *)&scc_ast_builtin_type_int, null); - scc_ast_type_t va_list_type; - _scc_ast_type_builtin_init(&va_list_type, SCC_AST_BUILTIN_TYPE_VA_LIST); - scc_ast_decl_param_init(¶m_var, &va_list_type, null); - scc_ast_decl_vec_t params_outer; - scc_vec_init(params_outer); - scc_vec_push(params_outer, ¶m_int); - scc_vec_push(params_outer, ¶m_var); - - scc_ast_type_t outer_func; - scc_ast_type_function_init(&outer_func, &ptr_to_func_ret_float, - ¶ms_outer); - - // 5) 指针指向外层函数 - scc_ast_type_t ptr_to_outer_func; - scc_ast_type_pointer_init(&ptr_to_outer_func, &outer_func); - SCC_CHECK_AST(&ptr_to_outer_func.base, "float (*(*)(int, ...))()", - scc_parse_type_name); - } -} - -TEST_LIST = { - {"parser_unit", test_parser_unit}, - {"parser_expression", test_parser_expression}, - {"parser_type", test_parser_type}, - // {"parser_statement", test_parser_statement}, - // {"parser_declaration", test_parser_declaration}, - // {"parser_translation_unit", test_parser_translation_unit}, - {null, null}, -}; diff --git a/libs/pproc/include/pproc_macro.h b/libs/pproc/include/pproc_macro.h index f88ea01..1966019 100644 --- a/libs/pproc/include/pproc_macro.h +++ b/libs/pproc/include/pproc_macro.h @@ -10,6 +10,10 @@ typedef enum { SCC_PP_MACRO_NONE, // 不是宏 SCC_PP_MACRO_OBJECT, // 对象宏 SCC_PP_MACRO_FUNCTION, // 函数宏 + SCC_PP_MACRO_BUILTIN__FILE__, + SCC_PP_MACRO_BUILTIN__LINE__, + SCC_PP_MACRO_BUILTIN__DATE__, // TODO + SCC_PP_MACRO_BUILTIN__TIME__, // TODO } scc_pproc_macro_type_t; typedef SCC_VEC(scc_lexer_tok_vec_t) scc_pproc_macro_extened_params_t; diff --git a/libs/pproc/src/pproc_expand.c b/libs/pproc/src/pproc_expand.c index f040634..6a02c1b 100644 --- a/libs/pproc/src/pproc_expand.c +++ b/libs/pproc/src/pproc_expand.c @@ -658,10 +658,14 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) { expand_ctx->need_rescan = true; expand_ctx->call_pos = tok.loc; - if (macro->type == SCC_PP_MACRO_OBJECT) { + + switch (macro->type) { + case SCC_PP_MACRO_OBJECT: { scc_lexer_tok_drop(&tok); expand_object_macro(expand_ctx, macro); - } else if (macro->type == SCC_PP_MACRO_FUNCTION) { + break; + } + case SCC_PP_MACRO_FUNCTION: { scc_lexer_tok_t expect_tok; scc_ring_peek(*expand_ctx->input, expect_tok, ok); if (ok == false || expect_tok.type != SCC_TOK_L_PAREN) { @@ -671,8 +675,30 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) { scc_lexer_tok_drop(&tok); expand_function_macro(expand_ctx, macro); - } else { + break; + } + // FIXME 这可能不符合c语义 + case SCC_PP_MACRO_BUILTIN__FILE__: + scc_cstring_free(&tok.lexeme); + scc_cstring_append_ch(&tok.lexeme, '"'); + scc_cstring_append_cstr(&tok.lexeme, tok.loc.name, + scc_strlen(tok.loc.name)); + scc_cstring_append_ch(&tok.lexeme, '"'); + tok.type = SCC_TOK_STRING_LITERAL; + scc_vec_push(expand_ctx->output, tok); + break; + case SCC_PP_MACRO_BUILTIN__LINE__: + scc_cstring_free(&tok.lexeme); + char *buff = scc_malloc(32); + scc_snprintf(buff, 32, "%zu", tok.loc.line); + tok.lexeme = scc_cstring_from_cstr(buff); + scc_free(buff); + tok.type = SCC_TOK_INT_LITERAL; + scc_vec_push(expand_ctx->output, tok); + break; + default: UNREACHABLE(); + break; } } } diff --git a/libs/pproc/src/scc_pproc.c b/libs/pproc/src/scc_pproc.c index 66966e0..a77d4c0 100644 --- a/libs/pproc/src/scc_pproc.c +++ b/libs/pproc/src/scc_pproc.c @@ -101,6 +101,23 @@ CONTINUE: goto CONTINUE; } +void scc_pproc_add_builtin_macros(scc_pproc_macro_table_t *macro_table) { + struct { + const char *name; + scc_pproc_macro_type_t type; + } builin_table[] = { + {"__FILE__", SCC_PP_MACRO_BUILTIN__FILE__}, + {"__LINE__", SCC_PP_MACRO_BUILTIN__LINE__}, + }; + for (usize i = 0; i < SCC_ARRLEN(builin_table); i += 1) { + scc_cstring_t builtin_name = + scc_cstring_from_cstr(builin_table[i].name); + scc_pproc_macro_t *builtin = + scc_pproc_macro_new(&builtin_name, builin_table[i].type); + scc_pproc_macro_table_set(macro_table, builtin); + } +} + void scc_pproc_init(scc_pproc_t *pp, scc_lexer_tok_ring_t *input) { Assert(pp != null && input != null); pp->org_ring = input; @@ -115,10 +132,7 @@ void scc_pproc_init(scc_pproc_t *pp, scc_lexer_tok_ring_t *input) { pp->config.max_include_depth = 32; pp->config.keep_original_pos = true; -} - -void scc_pproc_add_builtin_macros() { - // TODO + scc_pproc_add_builtin_macros(&pp->macro_table); } static cbool fill_token(scc_lexer_tok_t *tok, void *userdata) { diff --git a/libs/sccf/include/sccf_utils.h b/libs/sccf/include/sccf_utils.h index d0524ec..aae4b46 100644 --- a/libs/sccf/include/sccf_utils.h +++ b/libs/sccf/include/sccf_utils.h @@ -275,7 +275,6 @@ static inline void sccf_write(const sccf_t *sccf, sccf_buffer_t *buffer) { scc_vec_size(*buffer) = size; } u8 *data = scc_vec_unsafe_get_data(*buffer); - usize offset = 0; scc_memcpy(data, &sccf->header, sizeof(sccf_header_t)); data += sizeof(sccf_header_t); scc_memcpy(data, scc_vec_unsafe_get_data(sccf->sect_headers), @@ -287,7 +286,7 @@ static inline void sccf_write(const sccf_t *sccf, sccf_buffer_t *buffer) { scc_memcpy(data, scc_vec_unsafe_get_data(*sect_data), sect_data->size); data += sect_data->size; } - if (data - scc_vec_unsafe_get_data(*buffer) != size) { + if ((usize)(data - scc_vec_unsafe_get_data(*buffer)) != size) { Panic(); } } diff --git a/libs/sstream/src/scc_sstream.c b/libs/sstream/src/scc_sstream.c index 500132a..1026acd 100644 --- a/libs/sstream/src/scc_sstream.c +++ b/libs/sstream/src/scc_sstream.c @@ -92,8 +92,8 @@ int scc_sstream_init(scc_sstream_t *stream, const char *fname, int ring_size) { stream->fill_pos = scc_pos_create(); stream->fill_pos.name = fname; SCC_WARN(stream->fill_pos, "file size is 0"); - scc_fclose(file); - return 2; + scc_sstream_init_by_buffer(stream, "", 0, false, ring_size); + return 0; } char *buffer = (char *)scc_malloc(fsize); scc_memset(buffer, 0, fsize); @@ -101,7 +101,7 @@ int scc_sstream_init(scc_sstream_t *stream, const char *fname, int ring_size) { Assert(read_ret == fsize); /* read bytes assert it */ scc_fclose(file); - scc_sstream_init_by_buffer(stream, buffer, read_ret, 1, ring_size); + scc_sstream_init_by_buffer(stream, buffer, read_ret, true, ring_size); stream->fname = fname; stream->fill_pos.name = stream->fname; return 0; diff --git a/libs/target/pe/include/scc_pe_def.h b/libs/target/pe/include/scc_pe_def.h index 56cd72e..6ed5362 100644 --- a/libs/target/pe/include/scc_pe_def.h +++ b/libs/target/pe/include/scc_pe_def.h @@ -538,19 +538,20 @@ typedef struct _IMAGE_RESOURCE_DIRECTORY { typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { union { - struct { - DWORD NameOffset : 31; - DWORD NameIsString : 1; - }; + // FIXME scc not supported bit field + // struct { + // DWORD NameOffset : 31; + // DWORD NameIsString : 1; + // }; DWORD Name; WORD Id; }; union { DWORD OffsetToData; - struct { - DWORD OffsetToDirectory : 31; - DWORD DataIsDirectory : 1; - }; + // struct { + // DWORD OffsetToDirectory : 31; + // DWORD DataIsDirectory : 1; + // }; }; } IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY; diff --git a/src/config.h b/src/config.h index 3ed8960..db81a15 100644 --- a/src/config.h +++ b/src/config.h @@ -6,6 +6,7 @@ typedef struct { const char *input_file; const char *output_file; + const char *target_description; int verbose; scc_argparse_list_t include_paths; scc_argparse_list_t define_macros; @@ -24,6 +25,7 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, SCC_HINT_INPUT_FILE, SCC_HINT_INCLUDE_PATH, SCC_HINT_DEFINED_MACRO, + SCC_HINT_TARGET_DESC, SCC_HINT_VERBOSE, SCC_HINT_EMIT_LEX, @@ -39,6 +41,8 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, [SCC_HINT_INPUT_FILE] = "Input source file", [SCC_HINT_INCLUDE_PATH] = "Add directory to the include search paths", [SCC_HINT_DEFINED_MACRO] = "Define a macro", + [SCC_HINT_TARGET_DESC] = + "Target description(eg. x86_64-pc-windows-msvc)", [SCC_HINT_VERBOSE] = "Increase verbosity (can be used multiple times)", [SCC_HINT_EMIT_LEX] = "Generate lexer sources tokens and exit", [SCC_HINT_EMIT_PP] = "Generate preprocessed tokens and exit", @@ -52,6 +56,7 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, [SCC_HINT_INPUT_FILE] = "输入源文件", [SCC_HINT_INCLUDE_PATH] = "添加系统头文件到搜索路径", [SCC_HINT_DEFINED_MACRO] = "定义宏", + [SCC_HINT_TARGET_DESC] = "目标机器描述(eg. x86_64-pc-windows-msvc)", [SCC_HINT_VERBOSE] = "增加详细输出(可多次使用)", [SCC_HINT_EMIT_LEX] = "生成`源代码的词法单元`并退出", [SCC_HINT_EMIT_PP] = "生成`预处理后的词法单元`并退出", @@ -105,6 +110,14 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, scc_argparse_spec_setup_list(&opt_define.spec, &(config->define_macros)); scc_argparse_cmd_add_opt(root, &opt_define); + // --target + scc_argparse_opt_t opt_target; + scc_argparse_opt_init(&opt_target, 0, "target", + scc_hints[SCC_HINT_TARGET_DESC]); + scc_argparse_spec_setup_string(&opt_target.spec, + &(config->target_description)); + scc_argparse_cmd_add_opt(root, &opt_target); + // -v, --verbose (计数) scc_argparse_opt_t opt_verbose; scc_argparse_opt_init(&opt_verbose, 'V', "verbose", diff --git a/src/main.c b/src/main.c index 2e6e1bd..8090a1c 100644 --- a/src/main.c +++ b/src/main.c @@ -78,6 +78,7 @@ int main(int argc, const char **argv, const char **envp) { .output_file = null, .emit_ast = false, .emit_ir = false, + .target_description = "x86_64-pc-windows-msvc", }; scc_vec_init(config.include_paths);