From 742bede02f58eb5a2322140573468e542d1827a3 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Tue, 10 Mar 2026 14:33:32 +0800 Subject: [PATCH] =?UTF-8?q?feat(ast):=20=E4=BF=AE=E6=94=B9=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E8=B0=83=E7=94=A8=E8=A1=A8=E8=BE=BE=E5=BC=8F=E7=9A=84?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在AST定义中将函数调用表达式的name字段替换为callee字段, 以支持更复杂的函数调用场景。同时更新了相关的初始化函数、 转储函数和解析逻辑,使函数调用表达式能够正确处理callee节点。 BREAKING CHANGE: 函数调用表达式的结构发生了改变,从使用name字符串 改为使用callee表达式节点。 --- libs/ast/include/ast_def.h | 1 + libs/ast/include/scc_ast.h | 6 +-- libs/ast/src/ast_dump.c | 3 +- libs/parser/src/parse_decl.c | 11 ++-- libs/parser/src/parse_expr.c | 2 +- libs/parser/src/parse_stmt.c | 24 ++++----- libs/parser/tests/test_parser_unit.c | 78 +++++++++++++++++++++++++++- 7 files changed, 102 insertions(+), 23 deletions(-) diff --git a/libs/ast/include/ast_def.h b/libs/ast/include/ast_def.h index da2b2d7..e673f3a 100644 --- a/libs/ast/include/ast_def.h +++ b/libs/ast/include/ast_def.h @@ -269,6 +269,7 @@ struct scc_ast_expr { // 函数调用 struct { const char *name; + scc_ast_expr_t *callee; scc_ast_expr_t *_target; scc_ast_expr_vec_t args; } call; diff --git a/libs/ast/include/scc_ast.h b/libs/ast/include/scc_ast.h index c484961..4dda9a0 100644 --- a/libs/ast/include/scc_ast.h +++ b/libs/ast/include/scc_ast.h @@ -293,12 +293,12 @@ static inline void scc_ast_expr_cond_init(scc_ast_expr_t *expr, // args can be null static inline void scc_ast_expr_call_init(scc_ast_expr_t *expr, - const char *name, + scc_ast_expr_t *callee, scc_ast_expr_vec_t *args) { - Assert(expr != null && name != null); + Assert(expr != null && callee != null); expr->base.loc = scc_pos_create(); expr->base.type = SCC_AST_EXPR_CALL; - expr->call.name = name; + expr->call.callee = callee; expr->call._target = null; if (args == null) { scc_vec_init(expr->call.args); diff --git a/libs/ast/src/ast_dump.c b/libs/ast/src/ast_dump.c index c8bd9df..a5a22f4 100644 --- a/libs/ast/src/ast_dump.c +++ b/libs/ast/src/ast_dump.c @@ -440,8 +440,7 @@ static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_ctx_t *ctx) { break; case SCC_AST_EXPR_CALL: - // dump_child_node((scc_ast_node_t *)expr->call._target, ctx, false); - PRINT_NODE(ctx, "%s", expr->call.name); + dump_child_node((scc_ast_node_t *)expr->call.callee, ctx, false); // 转储参数 for (size_t i = 0; i < expr->call.args.size; i++) { dump_child_node((scc_ast_node_t *)expr->call.args.data[i], ctx, diff --git a/libs/parser/src/parse_decl.c b/libs/parser/src/parse_decl.c index 8ef339e..e28b54c 100644 --- a/libs/parser/src/parse_decl.c +++ b/libs/parser/src/parse_decl.c @@ -145,7 +145,7 @@ A.2.4 External definitions function-definition declaration (6.9.1) function-definition: - declaration-specifiers declarator declaration-listopt compound-statement + declaration-specifiers declarator declaration-list(opt) compound-statement (6.9.1) declaration-list: declaration declaration-list declaration @@ -210,6 +210,9 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) { scc_ast_expr_t *init = scc_parse_expression(parser); scc_ast_decl_val_init(decl, type, scc_cstring_as_cstr(&tok.lexeme), init); + if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { + LOG_ERROR("expect semicolon"); + } goto RETURN; } // TODO @@ -250,7 +253,9 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) { Assert(decl->func.body->base.type == SCC_AST_STMT_COMPOUND); RETURN: - parser->sema_callbacks.on_decl(parser->sema_callbacks.context, - decl->base.type, decl); + if (decl) { + parser->sema_callbacks.on_decl(parser->sema_callbacks.context, + decl->base.type, decl); + } return decl; } diff --git a/libs/parser/src/parse_expr.c b/libs/parser/src/parse_expr.c index 5b8f196..9e6f814 100644 --- a/libs/parser/src/parse_expr.c +++ b/libs/parser/src/parse_expr.c @@ -760,7 +760,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { scc_lexer_tok_drop(&lp); scc_ast_expr_t *call = expr_create(parser, SCC_AST_EXPR_CALL); - call->call._target = left; + call->call.callee = left; scc_vec_init(call->call.args); // 解析参数列表 diff --git a/libs/parser/src/parse_stmt.c b/libs/parser/src/parse_stmt.c index 62ba1fb..52976ec 100644 --- a/libs/parser/src/parse_stmt.c +++ b/libs/parser/src/parse_stmt.c @@ -249,16 +249,12 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) { scc_ast_stmt_t *body = null; // TODO use decl or expr - init = (scc_ast_type_t *)scc_parse_expression(parser); + init = (scc_ast_type_t *)scc_parse_declaration(parser); if (init == null) { - init = (scc_ast_type_t *)scc_parse_declaration(parser); - } - if (init == null) { - LOG_ERROR("Expected expression or declaration in for statement."); - } - - if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { - LOG_ERROR("Expected semicolon in for statement."); + init = (scc_ast_type_t *)scc_parse_expression(parser); + if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { + LOG_ERROR("Expected semicolon in for statement."); + } } cond = scc_parse_expression(parser); @@ -309,7 +305,9 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) { static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser) { if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { - return null; + scc_ast_stmt_t *stmt = ast_stmt_alloc(); + scc_ast_stmt_expr_init(stmt, null); + return stmt; } scc_ast_expr_t *expr = scc_parse_expression(parser); @@ -430,7 +428,9 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) { stmt = parse_expression_statement(parser); RETURN: scc_parser_reset(parser); - parser->sema_callbacks.on_stmt(parser->sema_callbacks.context, - stmt->base.type, stmt); + if (stmt) { + parser->sema_callbacks.on_stmt(parser->sema_callbacks.context, + stmt->base.type, stmt); + } return stmt; } diff --git a/libs/parser/tests/test_parser_unit.c b/libs/parser/tests/test_parser_unit.c index 79b304d..75ac743 100644 --- a/libs/parser/tests/test_parser_unit.c +++ b/libs/parser/tests/test_parser_unit.c @@ -248,6 +248,76 @@ static void test_parser_unit(void) { 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); + + // 变量声明 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); + + // 表达式 x + 1 + scc_ast_expr_t x_ref1, lit1, add; + scc_ast_expr_identifier_init(&x_ref1, "x"); + scc_ast_expr_literal_int_init(&lit1, "1", false); + scc_ast_expr_binary_init(&add, SCC_AST_OP_ADD, &x_ref1, &lit1); + + // 赋值 x = x + 1 + scc_ast_expr_t x_ref2, assign; + scc_ast_expr_identifier_init(&x_ref2, "x"); + scc_ast_expr_binary_init(&assign, SCC_AST_OP_ASSIGN, &x_ref2, &add); + + // 表达式语句 + scc_ast_stmt_t assign_stmt; + scc_ast_stmt_expr_init(&assign_stmt, &assign); + + // return x + scc_ast_expr_t x_ref3; + scc_ast_expr_identifier_init(&x_ref3, "x"); + scc_ast_stmt_t ret_stmt; + scc_ast_stmt_return_init(&ret_stmt, &x_ref3); + + // 复合语句块 + 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); + } } static void test_parser_expression(void) { @@ -286,7 +356,9 @@ static void test_parser_expression(void) { scc_ast_expr_vec_t args; scc_vec_init(args); scc_ast_expr_t call; - scc_ast_expr_call_init(&call, "f", + 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); @@ -298,8 +370,10 @@ static void test_parser_expression(void) { 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, "f", &args2); + scc_ast_expr_call_init(&call2, &callee2, &args2); SCC_CHECK_AST(&call2.base, "f(1, x)", scc_parse_expression); // 成员访问 .