feat(ast): 添加复合表达式和初始化器解析支持
重构AST表达式枚举,将COMPOUND_LITERAL重命名为COMPOUND, 更新相关结构体定义以支持复合字面量的左右表达式向量表示。 添加lvalue表达式类型用于左值处理,实现完整的初始化器解析功能, 包括大括号初始化列表、成员访问和数组下标的处理逻辑。 更新表达式解析器为基于优先级的递归下降解析,修复变量声明中 初始化表达式的内存泄漏问题。 完善类型限定符和存储类说明符的重复检查机制,增强语法分析的准确性。
This commit is contained in:
@@ -154,6 +154,94 @@ A.2.4 External definitions
|
||||
#include <parser_utils.h>
|
||||
#include <scc_parser.h>
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user