feat(ast): 添加复合表达式和初始化器解析支持

重构AST表达式枚举,将COMPOUND_LITERAL重命名为COMPOUND,
更新相关结构体定义以支持复合字面量的左右表达式向量表示。

添加lvalue表达式类型用于左值处理,实现完整的初始化器解析功能,
包括大括号初始化列表、成员访问和数组下标的处理逻辑。

更新表达式解析器为基于优先级的递归下降解析,修复变量声明中
初始化表达式的内存泄漏问题。

完善类型限定符和存储类说明符的重复检查机制,增强语法分析的准确性。
This commit is contained in:
zzy
2026-03-12 21:14:08 +08:00
parent b00a42a539
commit c46578736a
15 changed files with 495 additions and 225 deletions

View File

@@ -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-expressionC 标准规定赋值左边必须是
@@ -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;
}
}