From c46578736a1b0887a1fbfa7132bce006d82af2d2 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Thu, 12 Mar 2026 21:14:08 +0800 Subject: [PATCH] =?UTF-8?q?feat(ast):=20=E6=B7=BB=E5=8A=A0=E5=A4=8D?= =?UTF-8?q?=E5=90=88=E8=A1=A8=E8=BE=BE=E5=BC=8F=E5=92=8C=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E5=99=A8=E8=A7=A3=E6=9E=90=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构AST表达式枚举,将COMPOUND_LITERAL重命名为COMPOUND, 更新相关结构体定义以支持复合字面量的左右表达式向量表示。 添加lvalue表达式类型用于左值处理,实现完整的初始化器解析功能, 包括大括号初始化列表、成员访问和数组下标的处理逻辑。 更新表达式解析器为基于优先级的递归下降解析,修复变量声明中 初始化表达式的内存泄漏问题。 完善类型限定符和存储类说明符的重复检查机制,增强语法分析的准确性。 --- libs/ast/include/ast_def.h | 34 ++-- libs/ast/include/scc_ast.h | 39 +++- libs/ast/src/ast_dump.c | 20 +- libs/parser/include/scc_parser.h | 2 + libs/parser/src/parse_decl.c | 94 ++++++++- libs/parser/src/parse_expr.c | 259 ++++++++++-------------- libs/parser/src/parse_type.c | 83 +++++++- libs/parser/tests/test_parser_unit.c | 86 +++++++- libs/pproc/include/pproc_expand.h | 7 +- libs/pproc/include/scc_pproc.h | 1 + libs/pproc/src/pproc_directive.c | 2 +- libs/pproc/src/pproc_expand.c | 44 ++-- libs/pproc/src/scc_pproc.c | 4 +- libs/pproc/tests/test_pproc_pos.c | 41 ++++ runtime/scc_core/include/scc_core_mem.h | 4 +- 15 files changed, 495 insertions(+), 225 deletions(-) create mode 100644 libs/pproc/tests/test_pproc_pos.c diff --git a/libs/ast/include/ast_def.h b/libs/ast/include/ast_def.h index e89d7f0..5b5517c 100644 --- a/libs/ast/include/ast_def.h +++ b/libs/ast/include/ast_def.h @@ -39,18 +39,18 @@ typedef enum { scc_ast_stmt_t_END, // 结束语句 // 表达式 - scc_ast_expr_t_BEGIN, // 表达式开始 - SCC_AST_EXPR_BINARY, // 二元运算 - SCC_AST_EXPR_UNARY, // 一元运算 - SCC_AST_EXPR_COND, // 条件表达式 ?: - SCC_AST_EXPR_CALL, // 函数调用 - SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标 - SCC_AST_EXPR_MEMBER, // 成员访问 . - SCC_AST_EXPR_PTR_MEMBER, // 指针成员访问 -> - SCC_AST_EXPR_CAST, // 类型转换 - SCC_AST_EXPR_SIZE_OF, // sizeof - SCC_AST_EXPR_ALIGN_OF, // _Alignof - SCC_AST_EXPR_COMPOUND_LITERAL, // 复合字面量 + scc_ast_expr_t_BEGIN, // 表达式开始 + SCC_AST_EXPR_BINARY, // 二元运算 + SCC_AST_EXPR_UNARY, // 一元运算 + SCC_AST_EXPR_COND, // 条件表达式 ?: + SCC_AST_EXPR_CALL, // 函数调用 + SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标 + SCC_AST_EXPR_MEMBER, // 成员访问 . + SCC_AST_EXPR_PTR_MEMBER, // 指针成员访问 -> + SCC_AST_EXPR_CAST, // 类型转换 + SCC_AST_EXPR_SIZE_OF, // sizeof + SCC_AST_EXPR_ALIGN_OF, // _Alignof + SCC_AST_EXPR_COMPOUND, // 复合字面量 // 字面量 SCC_AST_EXPR_INT_LITERAL, // 整数字面量 SCC_AST_EXPR_FLOAT_LITERAL, // 浮点字面量 @@ -310,9 +310,10 @@ struct scc_ast_expr { } attr_of; // 复合字面量 struct { - scc_ast_type_t *type; - scc_ast_expr_vec_t init_list; - } compound_literal; + scc_ast_expr_t *base; + scc_ast_expr_vec_t lhs_exprs; + scc_ast_expr_vec_t rhs_exprs; + } compound; // 字面量 struct { const char *lexme; @@ -323,6 +324,9 @@ struct scc_ast_expr { const char *name; scc_ast_decl_t *_target; } identifier; + struct { + scc_ast_type_t *type; + } lvalue; }; }; diff --git a/libs/ast/include/scc_ast.h b/libs/ast/include/scc_ast.h index 6320bd3..4a8a459 100644 --- a/libs/ast/include/scc_ast.h +++ b/libs/ast/include/scc_ast.h @@ -369,19 +369,28 @@ static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr, expr->attr_of.expr = null; } -// init can be null -static inline void -scc_ast_expr_compound_literal_init(scc_ast_expr_t *expr, scc_ast_type_t *type, - scc_ast_expr_vec_t *init) { - Assert(expr != null && type != null); +// lhs_exprs and rhs_exprs can be null +static inline void scc_ast_expr_compound_init(scc_ast_expr_t *expr, + scc_ast_expr_t *base, + scc_ast_expr_vec_t *lhs_exprs, + scc_ast_expr_vec_t *rhs_exprs) { + Assert(expr != null && base != null); expr->base.loc = scc_pos_create(); - expr->base.type = SCC_AST_EXPR_COMPOUND_LITERAL; - expr->compound_literal.type = type; - if (init == null) { - scc_vec_init(expr->compound_literal.init_list); + expr->base.type = SCC_AST_EXPR_COMPOUND; + expr->compound.base = base; + + if (lhs_exprs == null) { + scc_vec_init(expr->compound.lhs_exprs); } else { - expr->compound_literal.init_list = *init; - scc_vec_init(*init); + expr->compound.lhs_exprs = *lhs_exprs; + scc_vec_init(*lhs_exprs); + } + + if (rhs_exprs == null) { + scc_vec_init(expr->compound.rhs_exprs); + } else { + expr->compound.rhs_exprs = *rhs_exprs; + scc_vec_init(*rhs_exprs); } } @@ -426,6 +435,14 @@ static inline void scc_ast_expr_identifier_init(scc_ast_expr_t *expr, expr->identifier._target = null; } +static inline void scc_ast_expr_lvalue_init(scc_ast_expr_t *expr, + scc_ast_type_t *type) { + Assert(expr != null && type != null); + expr->base.loc = scc_pos_create(); + expr->base.type = SCC_AST_EXPR_IDENTIFIER; + expr->lvalue.type = type; +} + // have defined builtin type static inline void _scc_ast_type_builtin_init(scc_ast_type_t *type, scc_ast_builtin_type_t builtin) { diff --git a/libs/ast/src/ast_dump.c b/libs/ast/src/ast_dump.c index 3840f1d..030ee8b 100644 --- a/libs/ast/src/ast_dump.c +++ b/libs/ast/src/ast_dump.c @@ -52,7 +52,7 @@ static const char *node_type_names[] = { [SCC_AST_EXPR_CAST] = "CastExpr", [SCC_AST_EXPR_SIZE_OF] = "SizeofExpr", [SCC_AST_EXPR_ALIGN_OF] = "AlignofExpr", - [SCC_AST_EXPR_COMPOUND_LITERAL] = "CompoundLiteralExpr", + [SCC_AST_EXPR_COMPOUND] = "CompoundExpr", [SCC_AST_EXPR_INT_LITERAL] = "IntLiteralExpr", [SCC_AST_EXPR_FLOAT_LITERAL] = "FloatLiteralExpr", [SCC_AST_EXPR_CHAR_LITERAL] = "CharLiteralExpr", @@ -461,15 +461,15 @@ static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_ctx_t *ctx) { } break; - case SCC_AST_EXPR_COMPOUND_LITERAL: - dump_child_node((scc_ast_node_t *)expr->compound_literal.type, ctx, - false); - // 初始化列表 - for (size_t i = 0; i < expr->compound_literal.init_list.size; i++) { - dump_child_node( - (scc_ast_node_t *)expr->compound_literal.init_list.data[i], ctx, - i == expr->compound_literal.init_list.size - 1); - } + case SCC_AST_EXPR_COMPOUND: + // dump_child_node((scc_ast_node_t *)expr->compound_literal.type, ctx, + // false); + // // 初始化列表 + // for (size_t i = 0; i < expr->compound_literal.init_list.size; i++) { + // dump_child_node( + // (scc_ast_node_t *)expr->compound_literal.init_list.data[i], + // ctx, i == expr->compound_literal.init_list.size - 1); + // } break; default: diff --git a/libs/parser/include/scc_parser.h b/libs/parser/include/scc_parser.h index aa84554..39e358d 100644 --- a/libs/parser/include/scc_parser.h +++ b/libs/parser/include/scc_parser.h @@ -51,6 +51,8 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser); * @return 声明 AST 节点 */ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser); +scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, + scc_ast_expr_t *base); /** * @brief 解析语句 diff --git a/libs/parser/src/parse_decl.c b/libs/parser/src/parse_decl.c index 0944b84..c226886 100644 --- a/libs/parser/src/parse_decl.c +++ b/libs/parser/src/parse_decl.c @@ -154,6 +154,94 @@ A.2.4 External definitions #include #include +scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, + scc_ast_expr_t *base) { + /* + initializer: + assignment-expression + { initializer-list } + { initializer-list , } + initializer-list: + designation(opt) initializer + initializer-list , designation(opt) initializer + designation: + designator-list = + designator-list: + designator + designator-list designator + designator: + [ constant-expression ] + . identifier + */ + const scc_lexer_tok_t *tok_ptr = null; + tok_ptr = scc_parser_peek(parser); + scc_ast_expr_t *init = null; + if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE)) { + // TODO int a = 1, b = 1; + init = scc_parse_assignment_expression(parser); + return init; + } + scc_parser_next_consume(parser, null); + + init = scc_malloc(sizeof(scc_ast_expr_t)); + Assert(init != null); + scc_ast_expr_vec_t lhs_exprs; + scc_vec_init(lhs_exprs); + scc_ast_expr_vec_t rhs_exprs; + scc_vec_init(rhs_exprs); + scc_ast_expr_t *lhs = null; + scc_ast_expr_t *rhs = null; + + while (1) { + tok_ptr = scc_parser_peek(parser); + if (tok_ptr->type == SCC_TOK_DOT) { + scc_parser_next_consume(parser, null); + tok_ptr = scc_parser_peek(parser); + if (tok_ptr && tok_ptr->type == SCC_TOK_IDENT) { + lhs = scc_malloc(sizeof(scc_ast_expr_t)); + Assert(lhs != null); + scc_ast_expr_member_init(lhs, base, + scc_cstring_as_cstr(&tok_ptr->lexeme)); + + rhs = scc_parse_initializer(parser, lhs); + Assert(rhs != null); + scc_vec_push(lhs_exprs, lhs); + scc_vec_push(rhs_exprs, rhs); + } else { + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected 'identifier' after '.'"); + } + } else if (tok_ptr->type == SCC_TOK_L_BRACKET) { + scc_parser_next_consume(parser, null); + scc_ast_expr_t *idx = scc_parser_constant_expression(parser); + Assert(idx != null); + if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) { + SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ']'"); + } + lhs = scc_malloc(sizeof(scc_ast_expr_t)); + Assert(lhs != null); + scc_ast_expr_array_subscript_init(lhs, base, idx); + + rhs = scc_parse_initializer(parser, lhs); + Assert(rhs != null); + scc_vec_push(lhs_exprs, lhs); + scc_vec_push(rhs_exprs, rhs); + } else if (tok_ptr->type == SCC_TOK_R_BRACE) { + scc_parser_next_consume(parser, null); + break; + } else if (tok_ptr->type == SCC_TOK_COMMA) { + continue; + } else { + // FIXME + scc_ast_expr_t *expr = scc_parse_initializer(parser, base); + scc_vec_push(lhs_exprs, null); + scc_vec_push(rhs_exprs, expr); + } + } + scc_ast_expr_compound_init(init, base, &lhs_exprs, &rhs_exprs); + return init; +} + scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) { scc_ast_node_t *type_or_decl = _scc_parse_type(parser); scc_ast_decl_t *decl = null; @@ -189,8 +277,10 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) { goto RETURN; } else if (tok_ptr->type == SCC_TOK_ASSIGN) { scc_parser_next_consume(parser, null); - scc_ast_expr_t *init = scc_parse_expression(parser); - decl->var.init = init; + // TODO maybe memory leak + scc_ast_expr_t *lvalue = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_lvalue_init(lvalue, decl->var.type); + decl->var.init = scc_parse_initializer(parser, lvalue); if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { SCC_ERROR(scc_parser_got_current_pos(parser), "expect semicolon"); } diff --git a/libs/parser/src/parse_expr.c b/libs/parser/src/parse_expr.c index 14573e3..1f03712 100644 --- a/libs/parser/src/parse_expr.c +++ b/libs/parser/src/parse_expr.c @@ -355,9 +355,9 @@ static scc_ast_expr_op_t map_token_to_assign_op(scc_tok_type_t type) { /* ---------------------------- 错误恢复辅助 ---------------------------- */ // 跳过直到遇到同步 token(分号、右括号、逗号、EOF) static void parser_sync(scc_parser_t *parser) { - const scc_lexer_tok_t *tok; - while ((tok = scc_parser_peek(parser)) != null) { - scc_tok_type_t type = tok->type; + const scc_lexer_tok_t *tok_ptr; + while ((tok_ptr = scc_parser_peek(parser)) != null) { + scc_tok_type_t type = tok_ptr->type; if (type == SCC_TOK_SEMICOLON || type == SCC_TOK_R_PAREN || type == SCC_TOK_R_BRACE || type == SCC_TOK_COMMA || type == SCC_TOK_EOF) { @@ -411,112 +411,41 @@ static scc_ast_expr_t *create_conditional_expr(scc_parser_t *parser, // 其他创建函数根据需要添加(如 call、subscript、member 等) /* ---------------------------- 通用二元解析器 ---------------------------- */ -/** - * 解析左结合的二元表达式 - * @param parser 解析器 - * @param parse_sub 解析下一级(优先级更低)的函数 - * @param this_prec 当前层的优先级 - * @return 表达式节点 - */ -static scc_ast_expr_t *parse_binary_expression(scc_parser_t *parser, - parse_sub_expr_func parse_sub, - int this_prec) { - scc_ast_expr_t *left = parse_sub(parser); - if (!left) { - // 左侧解析失败,尝试同步后返回 null - parser_sync(parser); +static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser, + int min_prec) { + // 从最底层(cast-expression)开始 + scc_ast_expr_t *left = parse_cast_expression(parser); + if (!left) return null; - } while (1) { - const scc_lexer_tok_t *tok = scc_parser_peek(parser); - if (!tok) + const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); + if (!tok_ptr) break; - int prec = get_token_precedence(tok->type); - if (prec < this_prec) - break; - // 必须是二元运算符(但赋值和条件除外,它们已在高层处理,这里不会出现) - if (!is_binary_operator(tok->type)) + int prec = get_token_precedence(tok_ptr->type); + // 只处理优先级 >= min_prec 的普通二元运算符 + if (prec < min_prec || !is_binary_operator(tok_ptr->type)) break; // 消费运算符 scc_lexer_tok_t op_tok; - if (!scc_parser_next_consume(parser, &op_tok)) { - // 消费失败,可能是流结束,退出循环 + if (!scc_parser_next_consume(parser, &op_tok)) break; - } scc_ast_expr_op_t op = map_token_to_binary_op(op_tok.type); scc_lexer_tok_drop(&op_tok); - // 解析右侧(注意左结合:传入 - // this_prec+1,确保优先级相同的不再结合,避免右结合) + // 解析右操作数(优先级 +1,确保左结合) scc_ast_expr_t *right = - parse_binary_expression(parser, parse_sub, this_prec + 1); + parse_expression_with_precedence(parser, prec + 1); if (!right) { - // 右侧解析失败,尝试恢复 parser_sync(parser); - // 释放已构建的 left?这里 left 可能已被使用,简单的做法是向上返回 - // null return null; } left = create_binary_expr(parser, left, right, op); - if (!left) - return null; } return left; } - -static scc_ast_expr_t *parse_multiplicative_expression(scc_parser_t *parser) { - return parse_binary_expression(parser, parse_cast_expression, - PREC_MULTIPLICATIVE); -} - -static scc_ast_expr_t *parse_additive_expression(scc_parser_t *parser) { - return parse_binary_expression(parser, parse_multiplicative_expression, - PREC_ADDITIVE); -} - -static scc_ast_expr_t *parse_shift_expression(scc_parser_t *parser) { - return parse_binary_expression(parser, parse_additive_expression, - PREC_SHIFT); -} - -static scc_ast_expr_t *parse_relational_expression(scc_parser_t *parser) { - return parse_binary_expression(parser, parse_shift_expression, - PREC_RELATIONAL); -} - -static scc_ast_expr_t *parse_equality_expression(scc_parser_t *parser) { - return parse_binary_expression(parser, parse_relational_expression, - PREC_EQUALITY); -} - -static scc_ast_expr_t *parse_bitwise_and_expression(scc_parser_t *parser) { - return parse_binary_expression(parser, parse_equality_expression, - PREC_BITWISE_AND); -} - -static scc_ast_expr_t *parse_bitwise_xor_expression(scc_parser_t *parser) { - return parse_binary_expression(parser, parse_bitwise_and_expression, - PREC_BITWISE_XOR); -} - -static scc_ast_expr_t *parse_bitwise_or_expression(scc_parser_t *parser) { - return parse_binary_expression(parser, parse_bitwise_xor_expression, - PREC_BITWISE_OR); -} - -static scc_ast_expr_t *parse_logical_and_expression(scc_parser_t *parser) { - return parse_binary_expression(parser, parse_bitwise_or_expression, - PREC_LOGICAL_AND); -} - -static scc_ast_expr_t *parse_logical_or_expression(scc_parser_t *parser) { - return parse_binary_expression(parser, parse_logical_and_expression, - PREC_LOGICAL_OR); -} - // 赋值表达式(右结合) scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) { // 先解析左侧的 unary-expression(C 标准规定赋值左边必须是 @@ -526,12 +455,12 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) { if (!left) return null; - const scc_lexer_tok_t *tok = scc_parser_peek(parser); - if (!tok) + const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); + if (!tok_ptr) return left; - int prec = get_token_precedence(tok->type); - if (prec == PREC_ASSIGNMENT && is_binary_operator(tok->type)) { + int prec = get_token_precedence(tok_ptr->type); + if (prec == PREC_ASSIGNMENT && is_binary_operator(tok_ptr->type)) { // 消费赋值运算符 scc_lexer_tok_t op_tok; if (!scc_parser_next_consume(parser, &op_tok)) @@ -554,12 +483,13 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) { // 条件表达式(右结合) static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) { - scc_ast_expr_t *cond = parse_logical_or_expression(parser); + scc_ast_expr_t *cond = + parse_expression_with_precedence(parser, PREC_LOGICAL_OR); if (!cond) return null; - const scc_lexer_tok_t *tok = scc_parser_peek(parser); - if (tok && tok->type == SCC_TOK_COND) { + const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); + if (tok_ptr && tok_ptr->type == SCC_TOK_COND) { // 消耗 '?' scc_lexer_tok_t q_tok; if (!scc_parser_next_consume(parser, &q_tok)) @@ -595,12 +525,13 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) { // 类型转换表达式 (type-name) cast-expression static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) { - const scc_lexer_tok_t *tok = scc_parser_peek(parser); - if (tok && tok->type == SCC_TOK_L_PAREN) { + const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); + scc_ast_type_t *type = null; + if (tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN) { // 尝试解析类型名 scc_parser_store(parser); scc_parser_next(parser); - scc_ast_type_t *type = scc_parse_type_name(parser); // 需要外部实现 + type = scc_parse_type_name(parser); // 需要外部实现 if (type) { // 消耗了类型名后,下一个应该是 ')' if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { @@ -620,6 +551,7 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) { // 不是类型转换,回退 // 释放 type(假设 scc_parse_type_name 分配了) // TODO: scc_ast_type_drop(type); + scc_parser_restore(parser); } } else { scc_parser_restore(parser); @@ -632,12 +564,12 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) { // 一元表达式 static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) { - const scc_lexer_tok_t *tok = scc_parser_peek(parser); - if (!tok) + const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); + if (!tok_ptr) return null; // 处理一元运算符 - switch (tok->type) { + switch (tok_ptr->type) { case SCC_TOK_ADD_ADD: // ++x case SCC_TOK_SUB_SUB: // --x case SCC_TOK_AND: // &x @@ -670,11 +602,12 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) { // sizeof 表达式(特殊处理两种形式) static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) { - scc_lexer_tok_t tok; - if (!scc_parser_next_consume(parser, &tok) || tok.type != SCC_TOK_SIZEOF) { + scc_lexer_tok_t tok_ptr; + if (!scc_parser_next_consume(parser, &tok_ptr) || + tok_ptr.type != SCC_TOK_SIZEOF) { return null; } - scc_lexer_tok_drop(&tok); + scc_lexer_tok_drop(&tok_ptr); const scc_lexer_tok_t *next = scc_parser_peek(parser); if (!next) { @@ -719,21 +652,41 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) { // 后缀表达式 static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { scc_ast_expr_t *left = parse_primary_expression(parser); - if (!left) - return null; + const scc_lexer_tok_t *tok_ptr = null; + if (!left) { + tok_ptr = scc_parser_peek(parser); + if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN)) { + return null; + } + scc_parser_store(parser); + scc_parser_next(parser); + scc_ast_type_t *type = scc_parse_type_name(parser); + if (!type) { + scc_parser_restore(parser); + return null; + } + scc_parser_commit(parser); + if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { + SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ')'"); + } + if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACKET)) { + SCC_ERROR(scc_parser_got_current_pos(parser), "Expected '{"); + } + scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_lvalue_init(expr, type); + return scc_parse_initializer(parser, expr); + } while (1) { - const scc_lexer_tok_t *tok = scc_parser_peek(parser); - if (!tok) + tok_ptr = scc_parser_peek(parser); + if (!tok_ptr) break; - switch (tok->type) { + switch (tok_ptr->type) { case SCC_TOK_L_BRACKET: // left[expr] { - scc_lexer_tok_t lb; - if (!scc_parser_next_consume(parser, &lb)) + if (!scc_parser_next_consume(parser, null)) return left; - scc_lexer_tok_drop(&lb); scc_ast_expr_t *index = scc_parse_expression(parser); if (!index) { @@ -746,52 +699,45 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { parser_sync(parser); return null; } - scc_ast_expr_t *subscript = - expr_create(parser, SCC_AST_EXPR_ARRAY_SUBSCRIPT); - subscript->subscript.array = left; - subscript->subscript.index = index; + scc_ast_expr_t *subscript = scc_malloc(sizeof(scc_ast_expr_t)); + Assert(subscript != null); + scc_ast_expr_array_subscript_init(subscript, left, index); left = subscript; break; } case SCC_TOK_L_PAREN: // left(args) { - scc_lexer_tok_t lp; - if (!scc_parser_next_consume(parser, &lp)) + if (!scc_parser_next_consume(parser, null)) return left; - scc_lexer_tok_drop(&lp); + scc_ast_expr_vec_t args; + scc_vec_init(args); - scc_ast_expr_t *call = expr_create(parser, SCC_AST_EXPR_CALL); - call->call.callee = left; - scc_vec_init(call->call.args); + while (1) { + if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) + break; + scc_ast_expr_t *arg = scc_parse_assignment_expression(parser); + if (!arg) { + parser_sync(parser); + break; + } + scc_vec_push(args, arg); - // 解析参数列表 - if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { - while (1) { - scc_ast_expr_t *arg = - scc_parse_assignment_expression(parser); - if (!arg) { - parser_sync(parser); - // 释放已解析的参数 - // TODO: 释放 call->call.args 中的表达式 - scc_free(call); - return null; - } - scc_vec_push(call->call.args, arg); - - if (scc_parser_consume_if(parser, SCC_TOK_COMMA)) { - continue; - } else if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { - break; - } else { - SCC_ERROR(scc_parser_got_current_pos(parser), - "Expected ',' or ')' in function call"); - parser_sync(parser); - // 释放资源 - scc_free(call); - return null; - } + if (scc_parser_consume_if(parser, SCC_TOK_COMMA)) { + continue; + } else if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) + break; + else { + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected ',' or ')' in function call"); + // 释放已解析的参数 + // TODO: 释放 args 中的表达式 + parser_sync(parser); + return null; } } + scc_ast_expr_t *call = scc_malloc(sizeof(scc_ast_expr_t)); + Assert(call != null); + scc_ast_expr_call_init(call, left, &args); left = call; break; } @@ -811,11 +757,13 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { } const char *name = scc_cstring_as_cstr(&ident_tok.lexeme); - scc_ast_expr_t *member = expr_create( - parser, op_tok.type == SCC_TOK_DOT ? SCC_AST_EXPR_MEMBER - : SCC_AST_EXPR_PTR_MEMBER); - member->member.base = left; - member->member.name = name; + scc_ast_expr_t *member = scc_malloc(sizeof(scc_ast_expr_t)); + Assert(member != null); + if (op_tok.type == SCC_TOK_DOT) { + scc_ast_expr_member_init(member, left, name); + } else { + scc_ast_expr_ptr_member_init(member, left, name); + } scc_lexer_tok_drop(&op_tok); left = member; @@ -842,11 +790,11 @@ done: // 基本表达式 static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { - const scc_lexer_tok_t *tok = scc_parser_peek(parser); - if (!tok) + const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); + if (!tok_ptr) return null; - switch (tok->type) { + switch (tok_ptr->type) { case SCC_TOK_IDENT: { scc_lexer_tok_t ident; if (!scc_parser_next_consume(parser, &ident)) @@ -900,7 +848,6 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { case SCC_TOK_L_PAREN: return parse_paren_expression(parser); default: - parser_sync(parser); return null; } } diff --git a/libs/parser/src/parse_type.c b/libs/parser/src/parse_type.c index 098f8ab..4e0046e 100644 --- a/libs/parser/src/parse_type.c +++ b/libs/parser/src/parse_type.c @@ -285,8 +285,15 @@ cbool scc_parse_is_storage_class_start(scc_parser_t *parser) { } } +#define DUP_CHECK(expr) \ + do { \ + if (expr) \ + goto duplicate_error; \ + expr = true; \ + } while (0) static scc_ast_decl_specifier_t -parse_type_qualifier_list(scc_parser_t *parser) { +parse_type_qualifier_list(scc_parser_t *parser, + scc_ast_decl_specifier_t quals) { /* (6.7.3) type-qualifier: @@ -298,7 +305,6 @@ parse_type_qualifier_list(scc_parser_t *parser) { type-qualifier type-qualifier-list type-qualifier */ - scc_ast_decl_specifier_t quals = {0}; const scc_lexer_tok_t *tok_ptr = null; CONTINUE: tok_ptr = scc_parser_peek(parser); @@ -307,21 +313,68 @@ CONTINUE: } switch (tok_ptr->type) { case SCC_TOK_CONST: - scc_parser_next_consume(parser, null); - quals.is_const = true; + DUP_CHECK(quals.is_const); break; case SCC_TOK_RESTRICT: - scc_parser_next_consume(parser, null); + DUP_CHECK(quals.is_restrict); quals.is_restrict = true; break; case SCC_TOK_VOLATILE: - scc_parser_next_consume(parser, null); - quals.is_volatile = true; + DUP_CHECK(quals.is_volatile); break; default: return quals; } + scc_parser_next_consume(parser, null); goto CONTINUE; +duplicate_error: + SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier"); + return quals; +} + +static scc_ast_decl_specifier_t +parse_declaration_specifiers_list(scc_parser_t *parser, + scc_ast_decl_specifier_t quals) { + const scc_lexer_tok_t *tok_ptr = null; +CONTINUE: + tok_ptr = scc_parser_peek(parser); + if (tok_ptr == null) { + return quals; + } + switch (tok_ptr->type) { + case SCC_TOK_CONST: + DUP_CHECK(quals.is_const); + break; + case SCC_TOK_RESTRICT: + DUP_CHECK(quals.is_restrict); + quals.is_restrict = true; + break; + case SCC_TOK_VOLATILE: + DUP_CHECK(quals.is_volatile); + break; + case SCC_TOK_EXTERN: + DUP_CHECK(quals.is_extern); + break; + case SCC_TOK_STATIC: + DUP_CHECK(quals.is_static); + break; + case SCC_TOK_AUTO: + DUP_CHECK(quals.is_auto); + break; + case SCC_TOK_REGISTER: + DUP_CHECK(quals.is_register); + break; + case SCC_TOK_INLINE: + DUP_CHECK(quals.is_inline); + break; + default: + return quals; + } + scc_parser_next_consume(parser, null); + goto CONTINUE; +duplicate_error: + SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier"); + return quals; } typedef struct { @@ -801,7 +854,7 @@ static scc_ast_type_t *parse_pointer(scc_parser_t *parser, pointee = pointer; } scc_ast_type_pointer_init(pointer, pointee); - pointer->quals = parse_type_qualifier_list(parser); + pointer->quals = parse_type_qualifier_list(parser, pointer->quals); return parse_pointer(parser, pointer, delay_pointee_ptr); } @@ -890,6 +943,7 @@ static scc_ast_expr_t *parse_array_size_type(scc_parser_t *parser) { } scc_ast_expr_t *size = null; + scc_ast_decl_specifier_t quals = {0}; if (scc_parse_is_type_qualifier_start(parser)) { // static assignment-expression // assignment-expression(opt) @@ -904,7 +958,7 @@ static scc_ast_expr_t *parse_array_size_type(scc_parser_t *parser) { // [ * ] } else if (scc_parser_consume_if(parser, SCC_TOK_STATIC)) { // type-qualifier-list(opt) assignment-expression - parse_type_qualifier_list(parser); + parse_type_qualifier_list(parser, quals); size = scc_parse_expression(parser); } else { // assignment-expression(opt) @@ -1086,10 +1140,12 @@ scc_ast_node_t *_scc_parse_type(scc_parser_t *parser) { } scc_ast_type_t *ret = null; - scc_ast_decl_specifier_t spec = parse_type_qualifier_list(parser); + scc_ast_decl_specifier_t spec = {0}; + spec = parse_declaration_specifiers_list(parser, spec); ret = parse_type_specifier(parser); if (ret != null) { ret->quals = spec; + ret->quals.is_inline = false; } scc_lexer_tok_t tok_ident = {0}; @@ -1112,6 +1168,10 @@ scc_ast_node_t *_scc_parse_type(scc_parser_t *parser) { } else if (decl) { if (type->base.type == SCC_AST_TYPE_FUNCTION) { scc_ast_decl_func_init(decl, type, name, null); + // TODO using sema to change it + if (spec.is_inline) { + type->quals.is_inline = true; + } } else { scc_ast_decl_val_init(decl, type, name, null); } @@ -1127,7 +1187,8 @@ scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser) { } scc_ast_type_t *ret = null; - scc_ast_decl_specifier_t spec = parse_type_qualifier_list(parser); + scc_ast_decl_specifier_t spec = {0}; + spec = parse_type_qualifier_list(parser, spec); ret = parse_type_specifier(parser); if (ret != null) { ret->quals = spec; diff --git a/libs/parser/tests/test_parser_unit.c b/libs/parser/tests/test_parser_unit.c index 10c2471..979adc3 100644 --- a/libs/parser/tests/test_parser_unit.c +++ b/libs/parser/tests/test_parser_unit.c @@ -507,6 +507,90 @@ static void test_parser_unit(void) { 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_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_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); + } + { // int (*(*)(void))[5] (指向函数的指针,该函数返回指向数组的指针) // 步骤: @@ -1018,7 +1102,7 @@ static void test_parser_type(void) { // _Complex double SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_complex_double, - "complex double", _scc_parse_type); + "double complex", _scc_parse_type); } // 2. 带类型限定符的基本类型 (const, volatile) diff --git a/libs/pproc/include/pproc_expand.h b/libs/pproc/include/pproc_expand.h index 79b05c6..3ad6cc7 100644 --- a/libs/pproc/include/pproc_expand.h +++ b/libs/pproc/include/pproc_expand.h @@ -11,8 +11,10 @@ typedef struct { scc_pproc_macro_table_t *expanded_set; scc_lexer_tok_ring_t *input; scc_lexer_tok_vec_t output; + scc_pos_t call_pos; cbool need_rescan; cbool need_parse_defined; + cbool need_keep_org_pos; } scc_pproc_expand_t; static inline scc_lexer_tok_ring_t @@ -27,10 +29,11 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx); void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table, scc_lexer_tok_ring_t *input, scc_lexer_tok_ring_t *output, - const scc_pproc_macro_t *macro); + const scc_pproc_macro_t *macro, + cbool need_keep_org_pos); void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table, scc_lexer_tok_vec_t *input, scc_lexer_tok_vec_t *output, - cbool need_parse_defined); + cbool need_parse_defined, cbool need_keep_org_pos); #endif /* __SCC_PPROC_EXPAND_H__ */ diff --git a/libs/pproc/include/scc_pproc.h b/libs/pproc/include/scc_pproc.h index c8681d5..7caaacc 100644 --- a/libs/pproc/include/scc_pproc.h +++ b/libs/pproc/include/scc_pproc.h @@ -51,6 +51,7 @@ typedef struct scc_pproc { struct { int max_include_depth; + cbool keep_original_pos; } config; } scc_pproc_t; diff --git a/libs/pproc/src/pproc_directive.c b/libs/pproc/src/pproc_directive.c index 068f14b..f7a15d8 100644 --- a/libs/pproc/src/pproc_directive.c +++ b/libs/pproc/src/pproc_directive.c @@ -176,7 +176,7 @@ static void scc_pproc_parse_line_and_expand(scc_pproc_t *pp, } scc_lexer_tok_vec_t out_vec; scc_pproc_expand_by_vec(&pp->macro_table, &org_toks, &out_vec, - need_parse_defined); + need_parse_defined, pp->config.keep_original_pos); *out_ring = scc_lexer_array_to_ring(&out_vec); } diff --git a/libs/pproc/src/pproc_expand.c b/libs/pproc/src/pproc_expand.c index c81afb9..8350f57 100644 --- a/libs/pproc/src/pproc_expand.c +++ b/libs/pproc/src/pproc_expand.c @@ -6,7 +6,8 @@ static void rescan(scc_pproc_expand_t *expand_ctx, const scc_pproc_macro_t *macro, scc_lexer_tok_vec_t *tok_buffer); -static scc_lexer_tok_t stringify_argument(scc_lexer_tok_vec_t *arg_tokens) { +static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx, + scc_lexer_tok_vec_t *arg_tokens) { // WRITE BY AI scc_cstring_t str = scc_cstring_create(); scc_cstring_append_ch(&str, '\"'); // 左引号 @@ -38,10 +39,13 @@ static scc_lexer_tok_t stringify_argument(scc_lexer_tok_vec_t *arg_tokens) { scc_lexer_tok_t result; result.type = SCC_TOK_STRING_LITERAL; result.lexeme = str; + if (ctx->need_keep_org_pos) + result.loc = ctx->call_pos; return result; } -static scc_lexer_tok_t concatenate_tokens(const scc_lexer_tok_t *left, +static scc_lexer_tok_t concatenate_tokens(scc_pproc_expand_t *ctx, + const scc_lexer_tok_t *left, const scc_lexer_tok_t *right) { scc_cstring_t new_lex = scc_cstring_from_cstr(""); if (left != null) { @@ -84,6 +88,8 @@ RETURN: scc_lexer_drop_ring(ring); scc_lexer_drop(&lexer); scc_sstream_drop(&sstream); + if (ctx->need_keep_org_pos) + result.loc = ctx->call_pos; return result; } @@ -102,7 +108,8 @@ static inline void scc_copy_expand(scc_pproc_expand_t *expand_ctx, void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table, scc_lexer_tok_ring_t *input, scc_lexer_tok_ring_t *output, - const scc_pproc_macro_t *macro) { + const scc_pproc_macro_t *macro, + cbool need_keep_org_pos) { scc_lexer_tok_vec_t expaned_buffer; scc_vec_init(expaned_buffer); @@ -130,7 +137,8 @@ void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table, } scc_lexer_tok_vec_t output_vec; - scc_pproc_expand_by_vec(macro_table, &expaned_buffer, &output_vec, false); + scc_pproc_expand_by_vec(macro_table, &expaned_buffer, &output_vec, false, + need_keep_org_pos); Assert(output->cap == 0 && output->data == null); // FIXME hack it *output = scc_lexer_array_to_ring(&output_vec); } @@ -138,13 +146,16 @@ void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table, void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table, scc_lexer_tok_vec_t *input, scc_lexer_tok_vec_t *output, - cbool need_parse_defined) { + cbool need_parse_defined, + cbool need_keep_org_pos) { scc_pproc_expand_t ctx; scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(input); ctx.input = ˚ ctx.macro_table = macro_table; ctx.need_rescan = false; ctx.need_parse_defined = need_parse_defined; + ctx.need_keep_org_pos = need_keep_org_pos; + ctx.call_pos = scc_pos_create(); scc_vec_init(ctx.output); scc_pproc_macro_table_t expanded_set; ctx.expanded_set = &expanded_set; @@ -311,7 +322,8 @@ static void rescan(scc_pproc_expand_t *expand_ctx, true); scc_lexer_tok_vec_t output = {0}; scc_pproc_expand_by_vec(expand_ctx->macro_table, &expaned_buffer, - &output, expand_ctx->need_parse_defined); + &output, expand_ctx->need_parse_defined, + expand_ctx->need_keep_org_pos); scc_vec_foreach(output, i) { scc_vec_push(expand_ctx->output, scc_vec_at(output, i)); } @@ -352,8 +364,8 @@ static inline int got_right_non_blank(int i, return right_idx; } -static void concact(scc_lexer_tok_vec_t *tok_buffer, scc_lexer_tok_t *right, - cbool gnu_va_arg_extend) { +static void concact(scc_pproc_expand_t *ctx, scc_lexer_tok_vec_t *tok_buffer, + scc_lexer_tok_t *right, cbool gnu_va_arg_extend) { // ## contact int tok_buf_size = (int)scc_vec_size(*tok_buffer); int left_idx = got_left_non_blank(tok_buf_size, tok_buffer); @@ -369,7 +381,7 @@ static void concact(scc_lexer_tok_vec_t *tok_buffer, scc_lexer_tok_t *right, } } - scc_lexer_tok_t concate_tok = concatenate_tokens(left, right); + scc_lexer_tok_t concate_tok = concatenate_tokens(ctx, left, right); while (left_idx++ < tok_buf_size) { scc_lexer_tok_drop(&scc_vec_pop(*tok_buffer)); @@ -409,6 +421,8 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, scc_vec_foreach(macro->replaces, i) { scc_lexer_tok_t tok = scc_lexer_tok_copy(&scc_vec_at(macro->replaces, i)); + if (expand_ctx->need_keep_org_pos) + tok.loc = expand_ctx->call_pos; if (tok.type == SCC_TOK_BLANK) { scc_cstring_free(&tok.lexeme); tok.lexeme = scc_cstring_from_cstr(" "); @@ -430,7 +444,8 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, int j = find_params(&scc_vec_at(macro->replaces, right_idx), macro); Assert(j != -1 && j < (int)scc_vec_size(splited_params)); - tok = stringify_argument(&scc_vec_at(splited_params, j)); + tok = + stringify_argument(expand_ctx, &scc_vec_at(splited_params, j)); scc_vec_push(tok_buffer, tok); i = right_idx; continue; @@ -467,12 +482,12 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, if (scc_strcmp(scc_cstring_as_cstr(&(right_tok->lexeme)), "__VA_ARGS__") == 0) { if (scc_vec_size(right_vec) == 0) { - concact(&tok_buffer, right, true); + concact(expand_ctx, &tok_buffer, right, true); } else { continue; } } else { - concact(&tok_buffer, right, false); + concact(expand_ctx, &tok_buffer, right, false); } scc_vec_foreach(right_vec, j) { @@ -520,6 +535,8 @@ static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx, scc_vec_foreach(macro->replaces, i) { scc_lexer_tok_t tok = scc_lexer_tok_copy(&scc_vec_at(macro->replaces, i)); + if (expand_ctx->need_keep_org_pos) + tok.loc = expand_ctx->call_pos; if (tok.type == SCC_TOK_BLANK) { // FIXME using function to warpper it scc_cstring_free(&tok.lexeme); @@ -536,7 +553,7 @@ static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx, right = &scc_vec_at(macro->replaces, right_idx); } - concact(&tok_buffer, right, false); + concact(expand_ctx, &tok_buffer, right, false); i = right_idx; continue; } @@ -630,6 +647,7 @@ 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) { scc_lexer_tok_drop(&tok); expand_object_macro(expand_ctx, macro); diff --git a/libs/pproc/src/scc_pproc.c b/libs/pproc/src/scc_pproc.c index af5dd31..8641721 100644 --- a/libs/pproc/src/scc_pproc.c +++ b/libs/pproc/src/scc_pproc.c @@ -62,7 +62,8 @@ CONTINUE: return ok; } scc_pproc_expand_by_src(&pp->macro_table, pp->cur_ring, - &pp->expanded_ring, macro); + &pp->expanded_ring, macro, + pp->config.keep_original_pos); goto CONTINUE; } else { // continue @@ -113,6 +114,7 @@ void scc_pproc_init(scc_pproc_t *pp, scc_lexer_tok_ring_t *input) { pp->enable = true; pp->config.max_include_depth = 32; + pp->config.keep_original_pos = true; } void scc_pproc_add_builtin_macros() { diff --git a/libs/pproc/tests/test_pproc_pos.c b/libs/pproc/tests/test_pproc_pos.c new file mode 100644 index 0000000..8acb6ab --- /dev/null +++ b/libs/pproc/tests/test_pproc_pos.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include + +static void test_define_pos(void) { + int ret = 0; + scc_sstream_t mem_stream; + const char *input = "#define OBJ 1\nOBJ"; + ret = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false, + 16); + Assert(ret == 0); + + scc_lexer_t lexer; + scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream)); + + scc_pproc_t pp; + scc_pproc_init(&pp, scc_lexer_to_ring(&lexer, 8, true)); + + scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pp, 8, true, true); + scc_lexer_tok_t tok = {0}; + + scc_ring_next_consume(*tok_ring, tok, ret); + Assert(ret == true); + TEST_CHECK(tok.loc.line == 2 && tok.loc.col == 1 && + scc_strcmp(tok.lexeme.data, "1") == 0); + TEST_MSG("Expected: %d:%d:%s", 2, 1, "1"); + TEST_MSG("Produced: %zu:%zu:%s", tok.loc.line, tok.loc.col, + tok.lexeme.data); + + scc_ring_free(*tok_ring); + scc_pproc_drop(&pp); + scc_lexer_drop(&lexer); + scc_sstream_drop(&mem_stream); +} + +#define TEST_LIST_CASE(func_name) {#func_name, func_name} +TEST_LIST = { + TEST_LIST_CASE(test_define_pos), + {NULL, NULL}, +}; diff --git a/runtime/scc_core/include/scc_core_mem.h b/runtime/scc_core/include/scc_core_mem.h index cfd788a..57c7823 100644 --- a/runtime/scc_core/include/scc_core_mem.h +++ b/runtime/scc_core/include/scc_core_mem.h @@ -15,10 +15,10 @@ int scc_memcmp(const void *s1, const void *s2, usize n); * @return u32 */ static inline u32 scc_strhash32(const char *s) { - u32 hash = 2166136261u; // FNV-1a偏移基础值 + u32 hash = 2166136261; // FNV-1a偏移基础值 while (*s) { hash ^= *s++; - hash *= 16777619u; + hash *= 16777619; } return hash; }