#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) { 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, 8, false); scc_parser_t parser; 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); Assert(!not_eof == true); 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); scc_vsnprintf(buffer + strlen(buffer), BUFFER_SIZE - strlen(buffer) - 1, fmt, args); va_end(args); } #define SCC_CHECK_AST(expect_node_ptr, str, parse_func) \ do { \ scc_ast_node_t *output_node_ptr = \ process_input(str, (scc_parse_node_func)parse_func); \ 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); \ 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) { scc_ast_decl_t int_decl = { .base.type = SCC_AST_DECL_VAR, .var.name = "a", .var.init = null, .var.type = &(scc_ast_type_t){.base.type = SCC_AST_TYPE_BUILTIN, .builtin.type = SCC_AST_BUILTIN_TYPE_INT}, }; SCC_CHECK_AST(&int_decl.base, "int a;", scc_parse_declaration); scc_ast_decl_t func_decl = { .base.type = SCC_AST_DECL_FUNC, .func.name = "main", .func.body = &(scc_ast_stmt_t){ .base.type = SCC_AST_STMT_COMPOUND, .compound.block_items = {0}, }, .func.type = &(scc_ast_type_t){ .base.type = SCC_AST_TYPE_FUNCTION, .function.is_variadic = false, .function.param_types = {0}, .function.return_type = &(scc_ast_type_t){.base.type = SCC_AST_TYPE_BUILTIN, .builtin.type = SCC_AST_BUILTIN_TYPE_INT}, }, }; SCC_CHECK_AST(&func_decl.base, "int main(void) {}", scc_parse_declaration); scc_ast_decl_t *decls[] = {&func_decl}; scc_ast_translation_unit_t tu = { .base.type = SCC_AST_TRANSLATION_UNIT, .declarations.data = decls, .declarations.cap = 1, .declarations.size = 1, }; SCC_CHECK_AST(&tu.base, "int main(void) {}", scc_parse_translation_unit); // SCC_CHECK_AST(&func_decl.base, "int main(void);", scc_parse_declaration); { scc_ast_node_t *items[] = { (scc_ast_node_t *)&(scc_ast_stmt_t){ .base.type = SCC_AST_STMT_RETURN, .return_stmt.expr = &(scc_ast_expr_t){ .base.type = SCC_AST_EXPR_INT_LITERAL, .literal.lexme = "0", }, }, }; scc_ast_decl_t func_decl = { .base.type = SCC_AST_DECL_FUNC, .func.name = "main", .func.body = &(scc_ast_stmt_t){ .base.type = SCC_AST_STMT_COMPOUND, .compound.block_items.cap = 1, .compound.block_items.size = 1, .compound.block_items.data = items, }, .func.type = &(scc_ast_type_t){ .base.type = SCC_AST_TYPE_FUNCTION, .function.is_variadic = false, .function.param_types = {0}, .function.return_type = &(scc_ast_type_t){.base.type = SCC_AST_TYPE_BUILTIN, .builtin.type = SCC_AST_BUILTIN_TYPE_INT}, }, }; scc_ast_decl_t *decls[] = {&func_decl}; scc_ast_translation_unit_t tu = { .base.type = SCC_AST_TRANSLATION_UNIT, .declarations.cap = 1, .declarations.size = 1, .declarations.data = decls, }; SCC_CHECK_AST(&tu.base, "int main(void) { return 0; }", scc_parse_translation_unit); } } static scc_ast_expr_t make_binary(scc_ast_expr_op_t op, scc_ast_expr_t *lhs, scc_ast_expr_t *rhs) { scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_BINARY}; expr.binary.op = op; expr.binary.lhs = lhs; expr.binary.rhs = rhs; return expr; } static scc_ast_expr_t make_unary(scc_ast_expr_op_t op, scc_ast_expr_t *operand) { scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_UNARY}; expr.unary.op = op; expr.unary.operand = operand; return expr; } static scc_ast_expr_t make_identifier(char *name) { scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_IDENTIFIER}; expr.identifier.name = name; return expr; } static scc_ast_expr_t make_int_literal(char *val) { scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_INT_LITERAL}; expr.literal.lexme = val; return expr; } static scc_ast_expr_t make_float_literal(char *val) { scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_FLOAT_LITERAL}; expr.literal.lexme = val; return expr; } static scc_ast_expr_t make_string_literal(char *val) { scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_STRING_LITERAL}; expr.literal.lexme = val; return expr; } static scc_ast_expr_t make_char_literal(char *val) { scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_CHAR_LITERAL}; expr.literal.lexme = val; return expr; } static scc_ast_expr_t make_conditional(scc_ast_expr_t *cond, scc_ast_expr_t *then_expr, scc_ast_expr_t *else_expr) { scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_COND}; expr.cond.cond = cond; expr.cond.then_expr = then_expr; expr.cond.else_expr = else_expr; return expr; } static scc_ast_expr_t make_call(scc_ast_expr_t *callee, scc_ast_expr_vec_t *args) { scc_ast_expr_t expr = {.base.type = SCC_AST_EXPR_CALL}; expr.call.callee = callee; // 注意:args 需要提前初始化,此处简化处理,实际测试中可能需要动态分配 // 我们将在具体测试中手动初始化 args 数组 return expr; } static void test_parser_expression(void) { // 1. 基本表达式:标识符、整数常量、字符串字面量、括号 { scc_ast_expr_t ident = make_identifier("x"); SCC_CHECK_AST(&ident.base, "x", scc_parse_expression); scc_ast_expr_t int_lit = make_int_literal("42"); SCC_CHECK_AST(&int_lit.base, "42", scc_parse_expression); scc_ast_expr_t str_lit = make_string_literal("\"hello\""); SCC_CHECK_AST(&str_lit.base, "\"hello\"", scc_parse_expression); // 括号表达式 scc_ast_expr_t paren_ident = make_identifier("y"); SCC_CHECK_AST(&paren_ident.base, "(y)", scc_parse_expression); } // 2. 后缀表达式 { // 数组下标:a[10] scc_ast_expr_t a = make_identifier("a"); scc_ast_expr_t index = make_int_literal("10"); scc_ast_expr_t subscript = {.base.type = SCC_AST_EXPR_ARRAY_SUBSCRIPT}; subscript.subscript.array = &a; subscript.subscript.index = &index; SCC_CHECK_AST(&subscript.base, "a[10]", scc_parse_expression); // 函数调用:f() scc_ast_expr_t f = make_identifier("f"); scc_ast_expr_t call = {.base.type = SCC_AST_EXPR_CALL}; call.call.callee = &f; scc_ast_expr_vec_t args; scc_vec_init(args); call.call.args = args; // 空参数列表 SCC_CHECK_AST(&call.base, "f()", scc_parse_expression); // 函数调用带参数:f(1, x) scc_ast_expr_t f2 = make_identifier("f"); scc_ast_expr_t arg1 = make_int_literal("1"); scc_ast_expr_t arg2 = make_identifier("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 call2 = {.base.type = SCC_AST_EXPR_CALL}; call2.call.callee = &f2; call2.call.args = args2; SCC_CHECK_AST(&call2.base, "f(1, x)", scc_parse_expression); // 成员访问 . 和 -> scc_ast_expr_t s = make_identifier("s"); scc_ast_expr_t dot = {.base.type = SCC_AST_EXPR_MEMBER}; dot.member.base = &s; dot.member.member_name = "field"; SCC_CHECK_AST(&dot.base, "s.field", scc_parse_expression); scc_ast_expr_t p = make_identifier("p"); scc_ast_expr_t arrow = {.base.type = SCC_AST_EXPR_PTR_MEMBER}; arrow.ptr_member.base = &p; arrow.ptr_member.member_name = "field"; SCC_CHECK_AST(&arrow.base, "p->field", scc_parse_expression); // 后缀 ++/-- scc_ast_expr_t x = make_identifier("x"); scc_ast_expr_t post_inc = make_unary(SCC_AST_OP_POSTFIX_INCREMENT, &x); SCC_CHECK_AST(&post_inc.base, "x++", scc_parse_expression); scc_ast_expr_t post_dec = make_unary(SCC_AST_OP_POSTFIX_DECREMENT, &x); SCC_CHECK_AST(&post_dec.base, "x--", scc_parse_expression); // 复合字面量 TODO: (int){1,2} 需要更复杂的构造,暂略 // SCC_CHECK_AST(..., "(int){1,2}", scc_parse_expression); } // 3. 一元表达式 { scc_ast_expr_t x = make_identifier("x"); scc_ast_expr_t pre_inc = make_unary(SCC_AST_OP_PREFIX_INCREMENT, &x); SCC_CHECK_AST(&pre_inc.base, "++x", scc_parse_expression); scc_ast_expr_t pre_dec = make_unary(SCC_AST_OP_PREFIX_DECREMENT, &x); SCC_CHECK_AST(&pre_dec.base, "--x", scc_parse_expression); scc_ast_expr_t addr = make_unary(SCC_AST_OP_ADDRESS_OF, &x); SCC_CHECK_AST(&addr.base, "&x", scc_parse_expression); scc_ast_expr_t deref = make_unary(SCC_AST_OP_INDIRECTION, &x); SCC_CHECK_AST(&deref.base, "*x", scc_parse_expression); scc_ast_expr_t plus = make_unary(SCC_AST_OP_UNARY_PLUS, &x); SCC_CHECK_AST(&plus.base, "+x", scc_parse_expression); scc_ast_expr_t minus = make_unary(SCC_AST_OP_UNARY_MINUS, &x); SCC_CHECK_AST(&minus.base, "-x", scc_parse_expression); scc_ast_expr_t bit_not = make_unary(SCC_AST_OP_BITWISE_NOT, &x); SCC_CHECK_AST(&bit_not.base, "~x", scc_parse_expression); scc_ast_expr_t log_not = make_unary(SCC_AST_OP_LOGICAL_NOT, &x); SCC_CHECK_AST(&log_not.base, "!x", scc_parse_expression); // sizeof 两种形式 // sizeof 表达式 scc_ast_expr_t sizeof_expr = {.base.type = SCC_AST_EXPR_SIZE_OF}; sizeof_expr.attr_of.expr = &x; SCC_CHECK_AST(&sizeof_expr.base, "sizeof x", scc_parse_expression); // sizeof(类型名) 需要构造类型节点,暂时略,用TODO // SCC_CHECK_AST(..., "sizeof(int)", scc_parse_expression); } // 4. 类型转换 { // (int)x // 需要构造类型节点,这里简化,用TODO // scc_ast_type_t int_type = { .base.type = SCC_AST_TYPE_BUILTIN, // .builtin.type = SCC_AST_BUILTIN_TYPE_INT }; scc_ast_expr_t x = // make_identifier("x"); scc_ast_expr_t cast = { .base.type = // SCC_AST_EXPR_CAST }; cast.cast.type = &int_type; cast.cast.expr = &x; // SCC_CHECK_AST(&cast.base, "(int)x", scc_parse_expression); } // 5. 二元运算符(按优先级测试) { scc_ast_expr_t a = make_identifier("a"); scc_ast_expr_t b = make_identifier("b"); scc_ast_expr_t c = make_identifier("c"); scc_ast_expr_t d = make_identifier("d"); // 乘除模优先级高于加减 scc_ast_expr_t mul = make_binary(SCC_AST_OP_MUL, &a, &b); scc_ast_expr_t add = make_binary(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 = make_binary(SCC_AST_OP_SUB, &a, &b); scc_ast_expr_t sub2 = make_binary(SCC_AST_OP_SUB, &sub1, &c); SCC_CHECK_AST(&sub2.base, "a - b - c", scc_parse_expression); // 移位 scc_ast_expr_t shift = make_binary(SCC_AST_OP_LEFT_SHIFT, &a, &b); SCC_CHECK_AST(&shift.base, "a << b", scc_parse_expression); // 关系 scc_ast_expr_t lt = make_binary(SCC_AST_OP_LESS, &a, &b); SCC_CHECK_AST(<.base, "a < b", scc_parse_expression); // 相等 scc_ast_expr_t eq = make_binary(SCC_AST_OP_EQUAL, &a, &b); SCC_CHECK_AST(&eq.base, "a == b", scc_parse_expression); // 按位与、异或、或的优先级:& 高于 ^ 高于 | scc_ast_expr_t bitand = make_binary(SCC_AST_OP_BITWISE_AND, &a, &b); scc_ast_expr_t bitxor = make_binary(SCC_AST_OP_BITWISE_XOR, &bitand, &c); scc_ast_expr_t bitor = make_binary(SCC_AST_OP_BITWISE_OR, &bitxor, &d); SCC_CHECK_AST(&bitor.base, "a & b ^ c | d", scc_parse_expression); // 逻辑与、或:&& 高于 || scc_ast_expr_t logand = make_binary(SCC_AST_OP_LOGICAL_AND, &a, &b); scc_ast_expr_t logor = make_binary(SCC_AST_OP_LOGICAL_OR, &logand, &c); SCC_CHECK_AST(&logor.base, "a && b || c", scc_parse_expression); } // 6. 三元运算符 { scc_ast_expr_t cond = make_identifier("a"); scc_ast_expr_t then_expr = make_identifier("b"); scc_ast_expr_t else_expr = make_identifier("c"); scc_ast_expr_t cond_expr = make_conditional(&cond, &then_expr, &else_expr); SCC_CHECK_AST(&cond_expr.base, "a ? b : c", scc_parse_expression); // 右结合性 a ? b : c ? d : e => a ? b : (c ? d : e) scc_ast_expr_t cond2 = make_identifier("c"); scc_ast_expr_t then2 = make_identifier("d"); scc_ast_expr_t else2 = make_identifier("e"); scc_ast_expr_t inner_cond = make_conditional(&cond2, &then2, &else2); scc_ast_expr_t outer_cond = make_conditional(&cond, &then_expr, &inner_cond); SCC_CHECK_AST(&outer_cond.base, "a ? b : c ? d : e", scc_parse_expression); } // 7. 赋值运算符(右结合) { // scc_ast_expr_t a = make_identifier("a"); // scc_ast_expr_t b = make_identifier("b"); // scc_ast_expr_t c = make_identifier("c"); // scc_ast_expr_t assign1 = make_binary(SCC_AST_OP_ASSIGN, &a, &b); // scc_ast_expr_t assign2 = // make_binary(SCC_AST_OP_ASSIGN, &assign1, &c); // a = (b = c) // SCC_CHECK_AST(&assign2.base, "a = b = c", scc_parse_expression); // scc_ast_expr_t add_assign = make_binary(SCC_AST_OP_ASSIGN_ADD, &a, // &b); SCC_CHECK_AST(&add_assign.base, "a += b", scc_parse_expression); } // 8. 逗号运算符 { scc_ast_expr_t a = make_identifier("a"); scc_ast_expr_t b = make_identifier("b"); scc_ast_expr_t comma1 = make_binary(SCC_AST_OP_COMMA, &a, &b); SCC_CHECK_AST(&comma1.base, "a, b", scc_parse_expression); } // 9. 混合优先级测试 { scc_ast_expr_t a = make_identifier("a"); scc_ast_expr_t b = make_identifier("b"); scc_ast_expr_t c = make_identifier("c"); scc_ast_expr_t d = make_identifier("d"); // a + b * c - d => (a + (b * c)) - d scc_ast_expr_t mul = make_binary(SCC_AST_OP_MUL, &b, &c); scc_ast_expr_t add = make_binary(SCC_AST_OP_ADD, &a, &mul); scc_ast_expr_t sub = make_binary(SCC_AST_OP_SUB, &add, &d); SCC_CHECK_AST(&sub.base, "a + b * c - d", scc_parse_expression); // *p++ => *(p++) scc_ast_expr_t p = make_identifier("p"); scc_ast_expr_t post_inc = make_unary(SCC_AST_OP_POSTFIX_INCREMENT, &p); scc_ast_expr_t deref = make_unary(SCC_AST_OP_INDIRECTION, &post_inc); SCC_CHECK_AST(&deref.base, "*p++", scc_parse_expression); } } TEST_LIST = { {"parser_unit", test_parser_unit}, {"parser_expression", test_parser_expression}, {NULL, NULL}, };