refactor(ast): 调整AST结构体和枚举类型的声明表示方式
将结构体、联合和枚举类型的字段表示从向量改为声明指针, 允许name和decl字段为null,更新相关初始化函数的断言检查, 使结构更加灵活并支持不完整类型定义。 BREAKING CHANGE: 修改了scc_ast_type结构体中record和enumeration 子类型的字段表示方法,从fields向量改为decl指针。
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 名称:查符号表获取类型节点
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user