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

@@ -181,11 +181,11 @@ struct scc_ast_type {
} function;
struct {
const char *name;
scc_ast_decl_vec_t fields; // 结构体/联合字段
scc_ast_decl_t *decl; // can be null
} record;
struct {
const char *name;
scc_ast_expr_vec_t enumerators; // 枚举项
scc_ast_decl_t *decl; // can be null
} enumeration;
struct {
const char *name;

View File

@@ -57,11 +57,11 @@ static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl,
decl->param.type = type;
}
// fields can be null
// name and fields can be null
static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_decl_vec_t *fields_move) {
Assert(decl != null && name != null);
Assert(decl != null);
decl->base.loc = scc_pos_create();
decl->base.type = SCC_AST_DECL_STRUCT;
decl->name = name;
@@ -73,11 +73,11 @@ static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl,
}
}
// fields can be null
// name and fields can be null
static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_decl_vec_t *fields_move) {
Assert(decl != null && name != null);
Assert(decl != null);
decl->base.loc = scc_pos_create();
decl->base.type = SCC_AST_DECL_UNION;
decl->name = name;
@@ -89,11 +89,11 @@ static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl,
}
}
// fields can be null
// name and fields can be null
static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_expr_vec_t *fields_move) {
Assert(decl != null && name != null);
Assert(decl != null);
decl->base.loc = scc_pos_create();
decl->base.type = SCC_AST_DECL_ENUM;
decl->name = name;
@@ -454,48 +454,39 @@ static inline void scc_ast_type_function_init(scc_ast_type_t *type,
static inline void _scc_ast_type_record_init(scc_ast_type_t *type,
scc_ast_node_type_t type_kind,
const char *name,
scc_ast_decl_vec_t *members) {
Assert(type != null && name != null);
scc_ast_decl_t *decl) {
Assert(type != null);
type->base.loc = scc_pos_create();
type->base.type = type_kind;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
if (members == null) {
scc_vec_init(type->record.fields);
} else {
type->record.fields = *members;
scc_vec_init(*members);
}
type->record.name = name;
type->record.decl = decl;
}
// name and members can be null
// name and decl can be null
static inline void scc_ast_type_struct_init(scc_ast_type_t *type,
const char *name,
scc_ast_decl_vec_t *members) {
_scc_ast_type_record_init(type, SCC_AST_TYPE_STRUCT, name, members);
scc_ast_decl_t *decl) {
_scc_ast_type_record_init(type, SCC_AST_TYPE_STRUCT, name, decl);
}
// name and members can be null
// name and decl can be null
static inline void scc_ast_type_union_init(scc_ast_type_t *type,
const char *name,
scc_ast_decl_vec_t *members) {
_scc_ast_type_record_init(type, SCC_AST_TYPE_UNION, name, members);
scc_ast_decl_t *decl) {
_scc_ast_type_record_init(type, SCC_AST_TYPE_UNION, name, decl);
}
// name and members can be null
// name and decl can be null
static inline void scc_ast_type_enum_init(scc_ast_type_t *type,
const char *name,
scc_ast_expr_vec_t *members) {
scc_ast_decl_t *decl) {
Assert(type != null);
type->base.loc = scc_pos_create();
type->base.type = SCC_AST_TYPE_ENUM;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->enumeration.name = name;
if (members == null) {
scc_vec_init(type->enumeration.enumerators);
} else {
type->enumeration.enumerators = *members;
scc_vec_init(*members);
}
type->enumeration.decl = null;
}
static inline void scc_ast_type_typedef_init(scc_ast_type_t *type,

View File

@@ -282,33 +282,19 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) {
break;
case SCC_AST_TYPE_FUNCTION:
PRINT_QUOTED_VALUE(ctx, "function");
scc_tree_dump_printf(ctx, "\n");
if (type->function.return_type) {
dump_type_impl(type->function.return_type, ctx);
}
if (scc_vec_size(type->function.param_types) != 0) {
scc_vec_foreach(type->function.param_types, i) {
scc_ast_decl_t *param =
scc_vec_at(type->function.param_types, i);
if (param->name) {
// FIXME param name
}
dump_type_impl(param->param.type, ctx);
}
}
break;
case SCC_AST_TYPE_STRUCT:
if (type->record.name) {
BUILD_TYPE_NAME(ctx, "struct ", type->record.name);
} else {
PRINT_QUOTED_VALUE(ctx, "anonymous struct");
PRINT_QUOTED_VALUE(ctx, "<anonymous struct>");
}
break;
case SCC_AST_TYPE_UNION:
if (type->record.name) {
BUILD_TYPE_NAME(ctx, "union ", type->record.name);
} else {
PRINT_QUOTED_VALUE(ctx, "anonymous union");
PRINT_QUOTED_VALUE(ctx, "<anonymous union>");
}
break;
case SCC_AST_TYPE_ENUM:
@@ -339,6 +325,40 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) {
dump_child_node((scc_ast_node_t *)type->array.size, ctx, true);
}
break;
case SCC_AST_TYPE_STRUCT:
if (type->enumeration.decl) {
dump_child_node((scc_ast_node_t *)type->enumeration.decl, ctx,
true);
}
break;
case SCC_AST_TYPE_ENUM:
if (type->record.decl) {
dump_child_node((scc_ast_node_t *)type->record.decl, ctx, true);
}
break;
case SCC_AST_TYPE_FUNCTION:
scc_vec_push(ctx->stack, false);
scc_tree_print_indent(ctx);
SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->node_color, "%s\n", "ReturnType");
dump_child_node((scc_ast_node_t *)type->function.return_type, ctx,
true);
scc_vec_pop(ctx->stack);
scc_vec_push(ctx->stack, true);
if (scc_vec_size(type->function.param_types) != 0) {
scc_vec_foreach(type->function.param_types, i) {
scc_ast_decl_t *param =
scc_vec_at(type->function.param_types, i);
if (param->name) {
// FIXME param name
}
dump_type_impl(param->param.type, ctx);
}
} else {
PRINT_QUOTED_VALUE(ctx, "()");
}
scc_vec_pop(ctx->stack);
break;
default:
break;
}
@@ -416,10 +436,13 @@ static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_ctx_t *ctx) {
case SCC_AST_EXPR_MEMBER:
case SCC_AST_EXPR_PTR_MEMBER:
dump_child_node((scc_ast_node_t *)expr->member.base, ctx, false);
// 打印成员访问信息
scc_vec_push(ctx->stack, true);
scc_tree_print_indent(ctx);
PRINT_NODE(ctx, "Member [\"%s\"]", expr->member.name);
scc_tree_dump_printf(ctx, "\n");
SCC_TREE_DUMP_PRINT_PURE(
ctx, ctx->node_color, "%s %s\n",
expr->base.type == SCC_AST_EXPR_MEMBER ? "Member" : "PtrMember",
expr->member.name);
scc_vec_pop(ctx->stack);
break;
case SCC_AST_EXPR_CAST:

View File

@@ -188,6 +188,7 @@ scc_tok_subtype_t scc_get_tok_subtype(scc_tok_type_t type);
const char *scc_get_tok_name(scc_tok_type_t type);
static inline void scc_lexer_tok_drop(scc_lexer_tok_t *tok) {
Assert(tok != null);
tok->type = SCC_TOK_UNKNOWN;
tok->loc.col = 0;
tok->loc.line = 0;

View File

@@ -4,6 +4,7 @@
#include "scc_sema.h"
#include <scc_ast.h>
#include <scc_core_ring.h>
#include <scc_hashtable.h>
#include <scc_lexer_token.h>
/**
@@ -13,11 +14,15 @@ typedef struct scc_parser {
scc_lexer_tok_ring_t *ring;
usize checkpoint;
scc_hashtable_t type_ht;
scc_sema_callbacks_t sema_callbacks;
scc_ast_translation_unit_t *translation_unit;
int errcode;
} scc_parser_t;
// static inline scc_ast_type_t *scc_parser_
/**
* @brief 初始化解析器
* @param parser 解析器实例

View File

@@ -9,6 +9,8 @@
typedef void (*scc_sema_callback_t)(void *context,
scc_ast_node_type_t node_type, void *node);
typedef scc_ast_type_t *(*scc_sema_got_type_t)(void *context, const char *name);
/**
* @brief 语义分析回调集合
*/
@@ -17,6 +19,7 @@ typedef struct scc_sema_callbacks {
scc_sema_callback_t on_stmt;
scc_sema_callback_t on_expr;
scc_sema_callback_t on_type;
scc_sema_got_type_t got_type;
void *context;
} scc_sema_callbacks_t;

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)) {
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;
}

View File

@@ -28,6 +28,7 @@ static scc_ast_node_t *process_input(const char *input,
scc_ring_not_eof(*parser.ring, not_eof);
if (not_eof == true) {
// FIXME MAYBE free
LOG_ERROR("Didn't consume all tokens");
return null;
}
@@ -53,19 +54,23 @@ static void dump2buffer(void *_buffer, const char *fmt, ...) {
va_end(args);
}
static void _scc_check_ast(scc_ast_node_t *expect_node_ptr, const char *str,
scc_parse_node_func parse_func) {
scc_ast_node_t *output_node_ptr = process_input(str, parse_func);
scc_tree_dump_ctx_t ctx;
expect_buffer[0] = '\n', expect_buffer[1] = '\0';
scc_tree_dump_ctx_init(&ctx, true, dump2buffer, expect_buffer);
scc_ast_dump_node(&ctx, expect_node_ptr);
scc_tree_dump_ctx_drop(&ctx);
output_buffer[0] = '\n', output_buffer[1] = '\0';
scc_tree_dump_ctx_init(&ctx, true, dump2buffer, output_buffer);
scc_ast_dump_node(&ctx, output_node_ptr);
scc_tree_dump_ctx_drop(&ctx);
}
#define SCC_CHECK_AST(expect_node_ptr, str, parse_func) \
do { \
scc_ast_node_t *output_node_ptr = \
process_input(str, (scc_parse_node_func)parse_func); \
scc_tree_dump_ctx_t ctx; \
expect_buffer[0] = '\n', expect_buffer[1] = '\0'; \
scc_tree_dump_ctx_init(&ctx, true, dump2buffer, expect_buffer); \
scc_ast_dump_node(&ctx, expect_node_ptr); \
scc_tree_dump_ctx_drop(&ctx); \
output_buffer[0] = '\n', output_buffer[1] = '\0'; \
scc_tree_dump_ctx_init(&ctx, true, dump2buffer, output_buffer); \
scc_ast_dump_node(&ctx, output_node_ptr); \
scc_tree_dump_ctx_drop(&ctx); \
_scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func); \
TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \
TEST_MSG("Expected: %s", expect_buffer); \
TEST_MSG("Produced: %s", output_buffer); \
@@ -368,6 +373,21 @@ static void test_parser_unit(void) {
SCC_CHECK_AST(&typedef_decl.base, "typedef int int32_t;",
scc_parse_declaration);
}
{
// struct { int x; } (匿名结构体定义)
scc_ast_decl_t field;
scc_ast_decl_val_init(
&field, (scc_ast_type_t *)&scc_ast_builtin_type_int, "x", null);
scc_ast_decl_vec_t fields;
scc_vec_init(fields);
scc_vec_push(fields, &field);
scc_ast_decl_t struct_def;
scc_ast_decl_struct_init(&struct_def, null, &fields);
SCC_CHECK_AST(&struct_def.base, "struct { int x; };",
scc_parse_declaration);
}
}
static void test_parser_expression(void) {
@@ -696,7 +716,7 @@ static void test_parser_type(void) {
scc_ast_type_t array_of_int_var;
scc_ast_type_array_init(&array_of_int_var,
(scc_ast_type_t *)&scc_ast_builtin_type_int,
NULL); // NULL 表示不定长数组
null); // null 表示不定长数组
scc_ast_type_t ptr_to_array_var;
scc_ast_type_pointer_init(&ptr_to_array_var, &array_of_int_var);
@@ -713,7 +733,7 @@ static void test_parser_type(void) {
// 函数类型,返回 int*,无参数
scc_ast_type_t func_type;
scc_ast_type_function_init(&func_type, &ptr_to_int, NULL);
scc_ast_type_function_init(&func_type, &ptr_to_int, null);
SCC_CHECK_AST(&func_type.base, "int *()", _scc_parse_type);
}
@@ -770,7 +790,7 @@ static void test_parser_type(void) {
// --- 数组,元素为上述 const 指针,大小未指定 ---
scc_ast_type_t array_of_ptr;
scc_ast_type_array_init(&array_of_ptr, &ptr_to_func, NULL);
scc_ast_type_array_init(&array_of_ptr, &ptr_to_func, null);
SCC_CHECK_AST(&array_of_ptr.base,
"int (*const [])(unsigned int, ...)",
@@ -901,7 +921,7 @@ static void test_parser_type(void) {
scc_ast_type_t array_of_int_unknown;
scc_ast_type_array_init(&array_of_int_unknown,
(scc_ast_type_t *)&scc_ast_builtin_type_int,
NULL);
null);
SCC_CHECK_AST(&array_of_int_unknown.base, "int []", _scc_parse_type);
// // int [*] (变长数组原型中的不定长数组)
@@ -909,11 +929,11 @@ static void test_parser_type(void) {
// scc_ast_type_t array_of_int_var;
// scc_ast_type_array_init(&array_of_int_var,
// (scc_ast_type_t *)&scc_ast_builtin_type_int,
// NULL);
// // 注意:[*] 与 [] 在AST中目前无法区分都使用 size=NULL
// null);
// // 注意:[*] 与 [] 在AST中目前无法区分都使用 size=null
// // 表示。如果解析器需要区分,可能需要特殊处理。 这里暂时假设解析器对
// [*]
// // 也生成 size=NULL 的数组节点。
// // 也生成 size=null 的数组节点。
// SCC_CHECK_AST(&array_of_int_var.base, "int [*]", scc_parse_type);
// int [5][3] (二维数组)
@@ -1087,46 +1107,57 @@ static void test_parser_type(void) {
// struct S (不完整类型)
scc_ast_type_t struct_tag;
scc_ast_type_struct_init(&struct_tag, "S",
NULL); // name="S", members=NULL
null); // name="S", members=null
SCC_CHECK_AST(&struct_tag.base, "struct S", _scc_parse_type);
// struct { int x; } (匿名结构体定义)
scc_ast_decl_t field;
scc_ast_decl_val_init(
&field, (scc_ast_type_t *)&scc_ast_builtin_type_int, "x", NULL);
&field, (scc_ast_type_t *)&scc_ast_builtin_type_int, "x", null);
scc_ast_decl_vec_t fields;
scc_vec_init(fields);
scc_vec_push(fields, &field);
scc_ast_type_t struct_def;
scc_ast_type_struct_init(&struct_def, NULL,
&fields); // name=NULL, members=fields
SCC_CHECK_AST(&struct_def.base, "struct { int x; }", _scc_parse_type);
scc_ast_decl_t struct_def;
scc_ast_decl_struct_init(&struct_def, null, &fields);
scc_ast_type_t struct_type;
scc_ast_type_struct_init(&struct_type, null, &struct_def);
SCC_CHECK_AST(&struct_type.base, "struct { int x; }", _scc_parse_type);
scc_ast_decl_struct_init(&struct_def, "A", &fields);
scc_ast_type_struct_init(&struct_type, "A", &struct_def);
SCC_CHECK_AST(&struct_type.base, "struct A { int x; }",
_scc_parse_type);
// union U (不完整类型)
scc_ast_type_t union_tag;
scc_ast_type_union_init(&union_tag, "U", NULL);
scc_ast_type_union_init(&union_tag, "U", null);
SCC_CHECK_AST(&union_tag.base, "union U", _scc_parse_type);
// union { int a; float b; } (匿名联合定义)
scc_ast_decl_t field_a, field_b;
scc_ast_decl_val_init(
&field_a, (scc_ast_type_t *)&scc_ast_builtin_type_int, "a", NULL);
&field_a, (scc_ast_type_t *)&scc_ast_builtin_type_int, "a", null);
scc_ast_decl_val_init(
&field_b, (scc_ast_type_t *)&scc_ast_builtin_type_float, "b", NULL);
&field_b, (scc_ast_type_t *)&scc_ast_builtin_type_float, "b", null);
scc_ast_decl_vec_t fields_union;
scc_vec_init(fields_union);
scc_vec_push(fields_union, &field_a);
scc_vec_push(fields_union, &field_b);
scc_ast_type_t union_def;
scc_ast_type_union_init(&union_def, NULL, &fields_union);
SCC_CHECK_AST(&union_def.base, "union { int a; float b; }",
scc_ast_decl_t union_def;
scc_ast_decl_union_init(&union_def, null, &fields_union);
scc_ast_type_t union_type;
scc_ast_type_union_init(&union_type, null, &union_def);
SCC_CHECK_AST(&union_type.base, "union { int a; float b; }",
_scc_parse_type);
scc_ast_decl_union_init(&union_def, "Union", &fields_union);
scc_ast_type_union_init(&union_type, "Union", &union_def);
SCC_CHECK_AST(&union_type.base, "union Union { int a; float b; }",
_scc_parse_type);
// enum E (不完整类型)
scc_ast_type_t enum_tag;
scc_ast_type_enum_init(&enum_tag, "E", NULL);
scc_ast_type_enum_init(&enum_tag, "E", null);
SCC_CHECK_AST(&enum_tag.base, "enum E", _scc_parse_type);
// enum { RED, GREEN, BLUE } (匿名枚举定义)
@@ -1140,9 +1171,15 @@ static void test_parser_type(void) {
scc_vec_push(enumerators, &green);
scc_vec_push(enumerators, &blue);
scc_ast_type_t enum_def;
scc_ast_type_enum_init(&enum_def, NULL, &enumerators);
SCC_CHECK_AST(&enum_def.base, "enum { RED, GREEN, BLUE }",
scc_ast_decl_t enum_def;
scc_ast_decl_enum_init(&enum_def, null, &enumerators);
scc_ast_type_t enum_type;
scc_ast_type_enum_init(&enum_type, null, &enum_def);
SCC_CHECK_AST(&enum_type.base, "enum { RED, GREEN, BLUE }",
_scc_parse_type);
scc_ast_decl_enum_init(&enum_def, "E", &enumerators);
scc_ast_type_enum_init(&enum_type, "E", &enum_def);
SCC_CHECK_AST(&enum_type.base, "enum E { RED, GREEN, BLUE }",
_scc_parse_type);
}
@@ -1189,13 +1226,13 @@ static void test_parser_type(void) {
SCC_CHECK_AST(&ptr_to_array.base, "const int * volatile (*)[10]",
_scc_parse_type);
// int (*(*)(int, ...))(float)
// float (*(*)(int, ...))()
// 1) float 类型作为内部函数返回类型
// 2) 构建返回 float 的函数类型,无参数(或者参数为空)
scc_ast_type_t func_ret_float;
scc_ast_type_function_init(
&func_ret_float, (scc_ast_type_t *)&scc_ast_builtin_type_float,
NULL);
null);
// 3) 指针指向该函数
scc_ast_type_t ptr_to_func_ret_float;
@@ -1220,7 +1257,7 @@ static void test_parser_type(void) {
// 5) 指针指向外层函数
scc_ast_type_t ptr_to_outer_func;
scc_ast_type_pointer_init(&ptr_to_outer_func, &outer_func);
SCC_CHECK_AST(&ptr_to_outer_func.base, "int (*(*)(int, ...))(float)",
SCC_CHECK_AST(&ptr_to_outer_func.base, "float (*(*)(int, ...))()",
_scc_parse_type);
}
}