refactor(ast): 调整AST结构体和枚举类型的声明表示方式

将结构体、联合和枚举类型的字段表示从向量改为声明指针,
允许name和decl字段为null,更新相关初始化函数的断言检查,
使结构更加灵活并支持不完整类型定义。

BREAKING CHANGE: 修改了scc_ast_type结构体中record和enumeration
子类型的字段表示方法,从fields向量改为decl指针。
This commit is contained in:
zzy
2026-03-11 21:53:19 +08:00
parent ce5414f2eb
commit e6511c508c
12 changed files with 338 additions and 116 deletions

View File

@@ -155,25 +155,6 @@ A.2.4 External definitions
#include <scc_parser.h>
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
/**
* ISO/IEC 9899:TC3
* 6.7 Declarations
* Syntax
*
* declaration:
* declaration-specifiers init-declarator-list(opt) ;
* declaration-specifiers:
* storage-class-specifier declaration-specifiers(opt)
* type-specifier declaration-specifiers(opt)
* type-qualifier declaration-specifiers(opt)
* function-specifier declaration-specifiers(opt)
* init-declarator-list:
* init-declarator
* init-declarator-list , init-declarator
* init-declarator:
* declarator
* declarator = initializer
*/
cbool ok;
scc_lexer_tok_t tok;
@@ -184,8 +165,20 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
}
if (SCC_AST_IS_A(scc_ast_type_t, type_or_decl)) {
LOG_WARN("declaration dose not declare anything");
return null;
scc_ast_type_t *type = SCC_AST_CAST_TO(scc_ast_type_t, type_or_decl);
if (type->base.type == SCC_AST_TYPE_STRUCT ||
type->base.type == SCC_AST_TYPE_UNION) {
Assert(type->record.decl != null);
decl = type->record.decl;
scc_free(type_or_decl); // FIXME
} else if (type->base.type == SCC_AST_TYPE_ENUM) {
Assert(type->enumeration.decl != null);
decl = type->enumeration.decl;
scc_free(type_or_decl); // FIXME
} else {
LOG_WARN("declaration dose not declare anything");
return null;
}
} else if (SCC_AST_IS_A(scc_ast_decl_t, type_or_decl)) {
decl = SCC_AST_CAST_TO(scc_ast_decl_t, type_or_decl);
} else {

View File

@@ -806,8 +806,6 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
return null;
}
const char *name = scc_cstring_as_cstr(&ident_tok.lexeme);
scc_lexer_tok_drop(&ident_tok);
scc_ast_expr_t *member = expr_create(
parser, op_tok.type == SCC_TOK_DOT ? SCC_AST_EXPR_MEMBER
: SCC_AST_EXPR_PTR_MEMBER);

View File

@@ -460,6 +460,167 @@ static scc_ast_type_t *build_type_from_info(type_spec_info_t *info) {
// 注意限定符const, volatile不应在此处处理应由上层函数负责
return type;
}
static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
scc_ast_node_type_t type_kind) {
/*
(6.7.2.1)
struct-or-union-specifier:
struct-or-union identifier(opt) { struct-declaration-list }
struct-or-union identifier
(6.7.2.1)
struct-or-union:
struct
union
(6.7.2.1)
struct-declaration-list:
struct-declaration
struct-declaration-list struct-declaration
(6.7.2.1)
struct-declaration:
specifier-qualifier-list struct-declarator-list ;
(6.7.2.1)
specifier-qualifier-list:
type-specifier specifier-qualifier-list(opt)
type-qualifier specifier-qualifier-list(opt)
(6.7.2.1)
struct-declarator-list:
struct-declarator
struct-declarator-list , struct-declarator
(6.7.2.1)
struct-declarator:
declarator
declarator(opt) : constant-expression
*/
// FIXME check struct/union
scc_parser_next_consume(parser, null);
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
scc_lexer_tok_t tok;
const char *name = null;
scc_ast_decl_t *decl = null;
scc_ast_decl_vec_t member;
scc_vec_init(member);
if (tok_ptr->type == SCC_TOK_IDENT) {
scc_parser_next_consume(parser, &tok);
name = scc_cstring_as_cstr(&tok.lexeme);
tok_ptr = scc_parser_peek(parser);
}
if (tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE) {
scc_parser_next_consume(parser, null);
while (1) {
tok_ptr = scc_parser_peek(parser);
if (tok_ptr == null) {
LOG_ERROR("Unexpected EOF in enum specifier");
break;
}
scc_ast_node_t *node = _scc_parse_type(parser);
scc_ast_decl_t *decl = null;
if (node != null) {
decl = SCC_AST_CAST_TO(scc_ast_decl_t, node);
}
if (decl != null) {
scc_vec_push(member, decl);
continue;
}
if (tok_ptr->type == SCC_TOK_SEMICOLON) {
// FIXME check semicolon
scc_parser_next_consume(parser, null);
} else if (tok_ptr->type == SCC_TOK_R_BRACE) {
scc_parser_next_consume(parser, null);
break;
} else {
LOG_ERROR("Unexpected token in enum specifier");
scc_parser_next_consume(parser, null);
break;
}
}
decl = scc_malloc(sizeof(scc_ast_decl_t));
Assert(decl != null);
if (type_kind == SCC_AST_TYPE_STRUCT) {
scc_ast_decl_struct_init(decl, name, &member);
} else {
scc_ast_decl_union_init(decl, name, &member);
}
}
scc_ast_type_t *type = ast_type_alloc();
_scc_ast_type_record_init(type, type_kind, name, decl);
return type;
}
static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
/*
(6.7.2.2)
enum-specifier:
enum identifier(opt) { enumerator-list }
enum identifier(opt) { enumerator-list , }
enum identifier
(6.7.2.2)
enumerator-list:
enumerator
enumerator-list , enumerator
(6.7.2.2)
enumerator:
enumeration-constant
enumeration-constant = constant-expression
*/
if (!scc_parser_consume_if(parser, SCC_TOK_ENUM)) {
LOG_ERROR("Expected 'enum'");
return null;
}
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
scc_lexer_tok_t tok;
const char *name = null;
scc_ast_decl_t *decl = null;
scc_ast_expr_vec_t member;
scc_vec_init(member);
if (tok_ptr->type == SCC_TOK_IDENT) {
scc_parser_next_consume(parser, &tok);
tok_ptr = scc_parser_peek(parser);
name = scc_cstring_as_cstr(&tok.lexeme);
}
if (tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE) {
scc_parser_next_consume(parser, null);
while (1) {
tok_ptr = scc_parser_peek(parser);
if (tok_ptr == null) {
LOG_ERROR("Unexpected EOF in enum specifier");
break;
}
scc_ast_expr_t *expr = scc_parse_expression(parser);
if (expr != null) {
scc_vec_push(member, expr);
continue;
}
if (tok_ptr->type == SCC_TOK_COMMA) {
// FIXME check comma
scc_parser_next_consume(parser, null);
} else if (tok_ptr->type == SCC_TOK_R_BRACE) {
scc_parser_next_consume(parser, null);
break;
} else {
LOG_ERROR("Unexpected token in enum specifier");
scc_parser_next_consume(parser, null);
break;
}
}
decl = scc_malloc(sizeof(scc_ast_decl_t));
Assert(decl != null);
scc_ast_decl_enum_init(decl, name, &member);
}
scc_ast_type_t *type = ast_type_alloc();
scc_ast_type_enum_init(type, name, decl);
return type;
}
static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
type_spec_info_t info = {0};
if (!scc_parse_is_type_specifier_start(parser))
@@ -550,13 +711,12 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
break;
case SCC_TOK_STRUCT:
case SCC_TOK_UNION:
info.user_type = parse_record_type(
parser, tok_ptr->type == SCC_TOK_STRUCT ? SCC_AST_TYPE_STRUCT
: SCC_AST_TYPE_UNION);
goto done;
case SCC_TOK_ENUM:
// // 解析 struct/union/enum 说明符(需单独实现)
// info.user_type = parse_struct_union_enum(parser, tok->type);
// if (!info.user_type)
// return null;
// // 这些类型说明符后不能再跟其他类型说明符,因此直接跳出循环
TODO();
info.user_type = parse_enum_type(parser);
goto done;
case SCC_TOK_IDENT:
// // 处理 typedef 名称:查符号表获取类型节点

View File

@@ -8,6 +8,13 @@ static void dummy_sema_callback(void *context, scc_ast_node_type_t node_type,
return;
}
static scc_ast_type_t *dummy_got_type_callback(void *context,
const char *name) {
(void)context;
(void)name;
return null;
}
#define ASSIGN_PTR_OR_DEFAULT(assigned_val, value, default) \
assigned_val = value ? value : default
@@ -26,12 +33,15 @@ void scc_parser_init(scc_parser_t *parser, scc_lexer_tok_ring_t *tok_ring,
callbacks->on_expr, dummy_sema_callback);
ASSIGN_PTR_OR_DEFAULT(parser->sema_callbacks.on_type,
callbacks->on_type, dummy_sema_callback);
ASSIGN_PTR_OR_DEFAULT(parser->sema_callbacks.got_type,
callbacks->got_type, dummy_got_type_callback);
parser->sema_callbacks.context = callbacks->context;
} else {
parser->sema_callbacks.on_decl = dummy_sema_callback;
parser->sema_callbacks.on_stmt = dummy_sema_callback;
parser->sema_callbacks.on_expr = dummy_sema_callback;
parser->sema_callbacks.on_type = dummy_sema_callback;
parser->sema_callbacks.got_type = dummy_got_type_callback;
parser->sema_callbacks.context = null;
}
}

View File

@@ -12,4 +12,5 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) {
callbacks->on_expr = null;
callbacks->on_stmt = null;
callbacks->on_type = null;
callbacks->got_type = null;
}