refactor(ast): 调整AST结构体和枚举类型的声明表示方式
将结构体、联合和枚举类型的字段表示从向量改为声明指针, 允许name和decl字段为null,更新相关初始化函数的断言检查, 使结构更加灵活并支持不完整类型定义。 BREAKING CHANGE: 修改了scc_ast_type结构体中record和enumeration 子类型的字段表示方法,从fields向量改为decl指针。
This commit is contained in:
@@ -181,11 +181,11 @@ struct scc_ast_type {
|
|||||||
} function;
|
} function;
|
||||||
struct {
|
struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
scc_ast_decl_vec_t fields; // 结构体/联合字段
|
scc_ast_decl_t *decl; // can be null
|
||||||
} record;
|
} record;
|
||||||
struct {
|
struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
scc_ast_expr_vec_t enumerators; // 枚举项
|
scc_ast_decl_t *decl; // can be null
|
||||||
} enumeration;
|
} enumeration;
|
||||||
struct {
|
struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|||||||
@@ -57,11 +57,11 @@ static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl,
|
|||||||
decl->param.type = type;
|
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,
|
static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl,
|
||||||
const char *name,
|
const char *name,
|
||||||
scc_ast_decl_vec_t *fields_move) {
|
scc_ast_decl_vec_t *fields_move) {
|
||||||
Assert(decl != null && name != null);
|
Assert(decl != null);
|
||||||
decl->base.loc = scc_pos_create();
|
decl->base.loc = scc_pos_create();
|
||||||
decl->base.type = SCC_AST_DECL_STRUCT;
|
decl->base.type = SCC_AST_DECL_STRUCT;
|
||||||
decl->name = name;
|
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,
|
static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl,
|
||||||
const char *name,
|
const char *name,
|
||||||
scc_ast_decl_vec_t *fields_move) {
|
scc_ast_decl_vec_t *fields_move) {
|
||||||
Assert(decl != null && name != null);
|
Assert(decl != null);
|
||||||
decl->base.loc = scc_pos_create();
|
decl->base.loc = scc_pos_create();
|
||||||
decl->base.type = SCC_AST_DECL_UNION;
|
decl->base.type = SCC_AST_DECL_UNION;
|
||||||
decl->name = name;
|
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,
|
static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl,
|
||||||
const char *name,
|
const char *name,
|
||||||
scc_ast_expr_vec_t *fields_move) {
|
scc_ast_expr_vec_t *fields_move) {
|
||||||
Assert(decl != null && name != null);
|
Assert(decl != null);
|
||||||
decl->base.loc = scc_pos_create();
|
decl->base.loc = scc_pos_create();
|
||||||
decl->base.type = SCC_AST_DECL_ENUM;
|
decl->base.type = SCC_AST_DECL_ENUM;
|
||||||
decl->name = name;
|
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,
|
static inline void _scc_ast_type_record_init(scc_ast_type_t *type,
|
||||||
scc_ast_node_type_t type_kind,
|
scc_ast_node_type_t type_kind,
|
||||||
const char *name,
|
const char *name,
|
||||||
scc_ast_decl_vec_t *members) {
|
scc_ast_decl_t *decl) {
|
||||||
Assert(type != null && name != null);
|
Assert(type != null);
|
||||||
type->base.loc = scc_pos_create();
|
type->base.loc = scc_pos_create();
|
||||||
type->base.type = type_kind;
|
type->base.type = type_kind;
|
||||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||||
if (members == null) {
|
type->record.name = name;
|
||||||
scc_vec_init(type->record.fields);
|
type->record.decl = decl;
|
||||||
} else {
|
|
||||||
type->record.fields = *members;
|
|
||||||
scc_vec_init(*members);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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,
|
static inline void scc_ast_type_struct_init(scc_ast_type_t *type,
|
||||||
const char *name,
|
const char *name,
|
||||||
scc_ast_decl_vec_t *members) {
|
scc_ast_decl_t *decl) {
|
||||||
_scc_ast_type_record_init(type, SCC_AST_TYPE_STRUCT, name, members);
|
_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,
|
static inline void scc_ast_type_union_init(scc_ast_type_t *type,
|
||||||
const char *name,
|
const char *name,
|
||||||
scc_ast_decl_vec_t *members) {
|
scc_ast_decl_t *decl) {
|
||||||
_scc_ast_type_record_init(type, SCC_AST_TYPE_UNION, name, members);
|
_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,
|
static inline void scc_ast_type_enum_init(scc_ast_type_t *type,
|
||||||
const char *name,
|
const char *name,
|
||||||
scc_ast_expr_vec_t *members) {
|
scc_ast_decl_t *decl) {
|
||||||
Assert(type != null);
|
Assert(type != null);
|
||||||
type->base.loc = scc_pos_create();
|
type->base.loc = scc_pos_create();
|
||||||
type->base.type = SCC_AST_TYPE_ENUM;
|
type->base.type = SCC_AST_TYPE_ENUM;
|
||||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||||
type->enumeration.name = name;
|
type->enumeration.name = name;
|
||||||
if (members == null) {
|
type->enumeration.decl = null;
|
||||||
scc_vec_init(type->enumeration.enumerators);
|
|
||||||
} else {
|
|
||||||
type->enumeration.enumerators = *members;
|
|
||||||
scc_vec_init(*members);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void scc_ast_type_typedef_init(scc_ast_type_t *type,
|
static inline void scc_ast_type_typedef_init(scc_ast_type_t *type,
|
||||||
|
|||||||
@@ -282,33 +282,19 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) {
|
|||||||
break;
|
break;
|
||||||
case SCC_AST_TYPE_FUNCTION:
|
case SCC_AST_TYPE_FUNCTION:
|
||||||
PRINT_QUOTED_VALUE(ctx, "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;
|
break;
|
||||||
case SCC_AST_TYPE_STRUCT:
|
case SCC_AST_TYPE_STRUCT:
|
||||||
if (type->record.name) {
|
if (type->record.name) {
|
||||||
BUILD_TYPE_NAME(ctx, "struct ", type->record.name);
|
BUILD_TYPE_NAME(ctx, "struct ", type->record.name);
|
||||||
} else {
|
} else {
|
||||||
PRINT_QUOTED_VALUE(ctx, "anonymous struct");
|
PRINT_QUOTED_VALUE(ctx, "<anonymous struct>");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SCC_AST_TYPE_UNION:
|
case SCC_AST_TYPE_UNION:
|
||||||
if (type->record.name) {
|
if (type->record.name) {
|
||||||
BUILD_TYPE_NAME(ctx, "union ", type->record.name);
|
BUILD_TYPE_NAME(ctx, "union ", type->record.name);
|
||||||
} else {
|
} else {
|
||||||
PRINT_QUOTED_VALUE(ctx, "anonymous union");
|
PRINT_QUOTED_VALUE(ctx, "<anonymous union>");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SCC_AST_TYPE_ENUM:
|
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);
|
dump_child_node((scc_ast_node_t *)type->array.size, ctx, true);
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
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_MEMBER:
|
||||||
case SCC_AST_EXPR_PTR_MEMBER:
|
case SCC_AST_EXPR_PTR_MEMBER:
|
||||||
dump_child_node((scc_ast_node_t *)expr->member.base, ctx, false);
|
dump_child_node((scc_ast_node_t *)expr->member.base, ctx, false);
|
||||||
// 打印成员访问信息
|
scc_vec_push(ctx->stack, true);
|
||||||
scc_tree_print_indent(ctx);
|
scc_tree_print_indent(ctx);
|
||||||
PRINT_NODE(ctx, "Member [\"%s\"]", expr->member.name);
|
SCC_TREE_DUMP_PRINT_PURE(
|
||||||
scc_tree_dump_printf(ctx, "\n");
|
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;
|
break;
|
||||||
|
|
||||||
case SCC_AST_EXPR_CAST:
|
case SCC_AST_EXPR_CAST:
|
||||||
|
|||||||
@@ -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);
|
const char *scc_get_tok_name(scc_tok_type_t type);
|
||||||
|
|
||||||
static inline void scc_lexer_tok_drop(scc_lexer_tok_t *tok) {
|
static inline void scc_lexer_tok_drop(scc_lexer_tok_t *tok) {
|
||||||
|
Assert(tok != null);
|
||||||
tok->type = SCC_TOK_UNKNOWN;
|
tok->type = SCC_TOK_UNKNOWN;
|
||||||
tok->loc.col = 0;
|
tok->loc.col = 0;
|
||||||
tok->loc.line = 0;
|
tok->loc.line = 0;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "scc_sema.h"
|
#include "scc_sema.h"
|
||||||
#include <scc_ast.h>
|
#include <scc_ast.h>
|
||||||
#include <scc_core_ring.h>
|
#include <scc_core_ring.h>
|
||||||
|
#include <scc_hashtable.h>
|
||||||
#include <scc_lexer_token.h>
|
#include <scc_lexer_token.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -13,11 +14,15 @@ typedef struct scc_parser {
|
|||||||
scc_lexer_tok_ring_t *ring;
|
scc_lexer_tok_ring_t *ring;
|
||||||
usize checkpoint;
|
usize checkpoint;
|
||||||
|
|
||||||
|
scc_hashtable_t type_ht;
|
||||||
|
|
||||||
scc_sema_callbacks_t sema_callbacks;
|
scc_sema_callbacks_t sema_callbacks;
|
||||||
scc_ast_translation_unit_t *translation_unit;
|
scc_ast_translation_unit_t *translation_unit;
|
||||||
int errcode;
|
int errcode;
|
||||||
} scc_parser_t;
|
} scc_parser_t;
|
||||||
|
|
||||||
|
// static inline scc_ast_type_t *scc_parser_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化解析器
|
* @brief 初始化解析器
|
||||||
* @param parser 解析器实例
|
* @param parser 解析器实例
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
typedef void (*scc_sema_callback_t)(void *context,
|
typedef void (*scc_sema_callback_t)(void *context,
|
||||||
scc_ast_node_type_t node_type, void *node);
|
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 语义分析回调集合
|
* @brief 语义分析回调集合
|
||||||
*/
|
*/
|
||||||
@@ -17,6 +19,7 @@ typedef struct scc_sema_callbacks {
|
|||||||
scc_sema_callback_t on_stmt;
|
scc_sema_callback_t on_stmt;
|
||||||
scc_sema_callback_t on_expr;
|
scc_sema_callback_t on_expr;
|
||||||
scc_sema_callback_t on_type;
|
scc_sema_callback_t on_type;
|
||||||
|
scc_sema_got_type_t got_type;
|
||||||
void *context;
|
void *context;
|
||||||
} scc_sema_callbacks_t;
|
} scc_sema_callbacks_t;
|
||||||
|
|
||||||
|
|||||||
@@ -155,25 +155,6 @@ A.2.4 External definitions
|
|||||||
#include <scc_parser.h>
|
#include <scc_parser.h>
|
||||||
|
|
||||||
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
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;
|
cbool ok;
|
||||||
scc_lexer_tok_t tok;
|
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)) {
|
if (SCC_AST_IS_A(scc_ast_type_t, type_or_decl)) {
|
||||||
LOG_WARN("declaration dose not declare anything");
|
scc_ast_type_t *type = SCC_AST_CAST_TO(scc_ast_type_t, type_or_decl);
|
||||||
return null;
|
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)) {
|
} 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);
|
decl = SCC_AST_CAST_TO(scc_ast_decl_t, type_or_decl);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -806,8 +806,6 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const char *name = scc_cstring_as_cstr(&ident_tok.lexeme);
|
const char *name = scc_cstring_as_cstr(&ident_tok.lexeme);
|
||||||
scc_lexer_tok_drop(&ident_tok);
|
|
||||||
|
|
||||||
scc_ast_expr_t *member = expr_create(
|
scc_ast_expr_t *member = expr_create(
|
||||||
parser, op_tok.type == SCC_TOK_DOT ? SCC_AST_EXPR_MEMBER
|
parser, op_tok.type == SCC_TOK_DOT ? SCC_AST_EXPR_MEMBER
|
||||||
: SCC_AST_EXPR_PTR_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)不应在此处处理,应由上层函数负责
|
// 注意:限定符(const, volatile)不应在此处处理,应由上层函数负责
|
||||||
return type;
|
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) {
|
static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||||
type_spec_info_t info = {0};
|
type_spec_info_t info = {0};
|
||||||
if (!scc_parse_is_type_specifier_start(parser))
|
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;
|
break;
|
||||||
case SCC_TOK_STRUCT:
|
case SCC_TOK_STRUCT:
|
||||||
case SCC_TOK_UNION:
|
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:
|
case SCC_TOK_ENUM:
|
||||||
// // 解析 struct/union/enum 说明符(需单独实现)
|
info.user_type = parse_enum_type(parser);
|
||||||
// info.user_type = parse_struct_union_enum(parser, tok->type);
|
|
||||||
// if (!info.user_type)
|
|
||||||
// return null;
|
|
||||||
// // 这些类型说明符后不能再跟其他类型说明符,因此直接跳出循环
|
|
||||||
TODO();
|
|
||||||
goto done;
|
goto done;
|
||||||
case SCC_TOK_IDENT:
|
case SCC_TOK_IDENT:
|
||||||
// // 处理 typedef 名称:查符号表获取类型节点
|
// // 处理 typedef 名称:查符号表获取类型节点
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ static void dummy_sema_callback(void *context, scc_ast_node_type_t node_type,
|
|||||||
return;
|
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) \
|
#define ASSIGN_PTR_OR_DEFAULT(assigned_val, value, default) \
|
||||||
assigned_val = value ? 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);
|
callbacks->on_expr, dummy_sema_callback);
|
||||||
ASSIGN_PTR_OR_DEFAULT(parser->sema_callbacks.on_type,
|
ASSIGN_PTR_OR_DEFAULT(parser->sema_callbacks.on_type,
|
||||||
callbacks->on_type, dummy_sema_callback);
|
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;
|
parser->sema_callbacks.context = callbacks->context;
|
||||||
} else {
|
} else {
|
||||||
parser->sema_callbacks.on_decl = dummy_sema_callback;
|
parser->sema_callbacks.on_decl = dummy_sema_callback;
|
||||||
parser->sema_callbacks.on_stmt = dummy_sema_callback;
|
parser->sema_callbacks.on_stmt = dummy_sema_callback;
|
||||||
parser->sema_callbacks.on_expr = dummy_sema_callback;
|
parser->sema_callbacks.on_expr = dummy_sema_callback;
|
||||||
parser->sema_callbacks.on_type = 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;
|
parser->sema_callbacks.context = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,4 +12,5 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) {
|
|||||||
callbacks->on_expr = null;
|
callbacks->on_expr = null;
|
||||||
callbacks->on_stmt = null;
|
callbacks->on_stmt = null;
|
||||||
callbacks->on_type = null;
|
callbacks->on_type = null;
|
||||||
|
callbacks->got_type = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ static scc_ast_node_t *process_input(const char *input,
|
|||||||
scc_ring_not_eof(*parser.ring, not_eof);
|
scc_ring_not_eof(*parser.ring, not_eof);
|
||||||
if (not_eof == true) {
|
if (not_eof == true) {
|
||||||
// FIXME MAYBE free
|
// FIXME MAYBE free
|
||||||
|
LOG_ERROR("Didn't consume all tokens");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,19 +54,23 @@ static void dump2buffer(void *_buffer, const char *fmt, ...) {
|
|||||||
va_end(args);
|
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) \
|
#define SCC_CHECK_AST(expect_node_ptr, str, parse_func) \
|
||||||
do { \
|
do { \
|
||||||
scc_ast_node_t *output_node_ptr = \
|
_scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func); \
|
||||||
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); \
|
|
||||||
TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \
|
TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \
|
||||||
TEST_MSG("Expected: %s", expect_buffer); \
|
TEST_MSG("Expected: %s", expect_buffer); \
|
||||||
TEST_MSG("Produced: %s", output_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_CHECK_AST(&typedef_decl.base, "typedef int int32_t;",
|
||||||
scc_parse_declaration);
|
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) {
|
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_t array_of_int_var;
|
||||||
scc_ast_type_array_init(&array_of_int_var,
|
scc_ast_type_array_init(&array_of_int_var,
|
||||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||||
NULL); // NULL 表示不定长数组
|
null); // null 表示不定长数组
|
||||||
|
|
||||||
scc_ast_type_t ptr_to_array_var;
|
scc_ast_type_t ptr_to_array_var;
|
||||||
scc_ast_type_pointer_init(&ptr_to_array_var, &array_of_int_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*,无参数
|
// 函数类型,返回 int*,无参数
|
||||||
scc_ast_type_t func_type;
|
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);
|
SCC_CHECK_AST(&func_type.base, "int *()", _scc_parse_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -770,7 +790,7 @@ static void test_parser_type(void) {
|
|||||||
|
|
||||||
// --- 数组,元素为上述 const 指针,大小未指定 ---
|
// --- 数组,元素为上述 const 指针,大小未指定 ---
|
||||||
scc_ast_type_t array_of_ptr;
|
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,
|
SCC_CHECK_AST(&array_of_ptr.base,
|
||||||
"int (*const [])(unsigned int, ...)",
|
"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_t array_of_int_unknown;
|
||||||
scc_ast_type_array_init(&array_of_int_unknown,
|
scc_ast_type_array_init(&array_of_int_unknown,
|
||||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||||
NULL);
|
null);
|
||||||
SCC_CHECK_AST(&array_of_int_unknown.base, "int []", _scc_parse_type);
|
SCC_CHECK_AST(&array_of_int_unknown.base, "int []", _scc_parse_type);
|
||||||
|
|
||||||
// // int [*] (变长数组原型中的不定长数组)
|
// // int [*] (变长数组原型中的不定长数组)
|
||||||
@@ -909,11 +929,11 @@ static void test_parser_type(void) {
|
|||||||
// scc_ast_type_t array_of_int_var;
|
// scc_ast_type_t array_of_int_var;
|
||||||
// scc_ast_type_array_init(&array_of_int_var,
|
// scc_ast_type_array_init(&array_of_int_var,
|
||||||
// (scc_ast_type_t *)&scc_ast_builtin_type_int,
|
// (scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||||
// NULL);
|
// null);
|
||||||
// // 注意:[*] 与 [] 在AST中目前无法区分,都使用 size=NULL
|
// // 注意:[*] 与 [] 在AST中目前无法区分,都使用 size=null
|
||||||
// // 表示。如果解析器需要区分,可能需要特殊处理。 这里暂时假设解析器对
|
// // 表示。如果解析器需要区分,可能需要特殊处理。 这里暂时假设解析器对
|
||||||
// [*]
|
// [*]
|
||||||
// // 也生成 size=NULL 的数组节点。
|
// // 也生成 size=null 的数组节点。
|
||||||
// SCC_CHECK_AST(&array_of_int_var.base, "int [*]", scc_parse_type);
|
// SCC_CHECK_AST(&array_of_int_var.base, "int [*]", scc_parse_type);
|
||||||
|
|
||||||
// int [5][3] (二维数组)
|
// int [5][3] (二维数组)
|
||||||
@@ -1087,46 +1107,57 @@ static void test_parser_type(void) {
|
|||||||
// struct S (不完整类型)
|
// struct S (不完整类型)
|
||||||
scc_ast_type_t struct_tag;
|
scc_ast_type_t struct_tag;
|
||||||
scc_ast_type_struct_init(&struct_tag, "S",
|
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);
|
SCC_CHECK_AST(&struct_tag.base, "struct S", _scc_parse_type);
|
||||||
|
|
||||||
// struct { int x; } (匿名结构体定义)
|
// struct { int x; } (匿名结构体定义)
|
||||||
scc_ast_decl_t field;
|
scc_ast_decl_t field;
|
||||||
scc_ast_decl_val_init(
|
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_ast_decl_vec_t fields;
|
||||||
scc_vec_init(fields);
|
scc_vec_init(fields);
|
||||||
scc_vec_push(fields, &field);
|
scc_vec_push(fields, &field);
|
||||||
|
|
||||||
scc_ast_type_t struct_def;
|
scc_ast_decl_t struct_def;
|
||||||
scc_ast_type_struct_init(&struct_def, NULL,
|
scc_ast_decl_struct_init(&struct_def, null, &fields);
|
||||||
&fields); // name=NULL, members=fields
|
scc_ast_type_t struct_type;
|
||||||
SCC_CHECK_AST(&struct_def.base, "struct { int x; }", _scc_parse_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 (不完整类型)
|
// union U (不完整类型)
|
||||||
scc_ast_type_t union_tag;
|
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);
|
SCC_CHECK_AST(&union_tag.base, "union U", _scc_parse_type);
|
||||||
|
|
||||||
// union { int a; float b; } (匿名联合定义)
|
// union { int a; float b; } (匿名联合定义)
|
||||||
scc_ast_decl_t field_a, field_b;
|
scc_ast_decl_t field_a, field_b;
|
||||||
scc_ast_decl_val_init(
|
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(
|
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_ast_decl_vec_t fields_union;
|
||||||
scc_vec_init(fields_union);
|
scc_vec_init(fields_union);
|
||||||
scc_vec_push(fields_union, &field_a);
|
scc_vec_push(fields_union, &field_a);
|
||||||
scc_vec_push(fields_union, &field_b);
|
scc_vec_push(fields_union, &field_b);
|
||||||
|
|
||||||
scc_ast_type_t union_def;
|
scc_ast_decl_t union_def;
|
||||||
scc_ast_type_union_init(&union_def, NULL, &fields_union);
|
scc_ast_decl_union_init(&union_def, null, &fields_union);
|
||||||
SCC_CHECK_AST(&union_def.base, "union { int a; float b; }",
|
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);
|
_scc_parse_type);
|
||||||
|
|
||||||
// enum E (不完整类型)
|
// enum E (不完整类型)
|
||||||
scc_ast_type_t enum_tag;
|
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);
|
SCC_CHECK_AST(&enum_tag.base, "enum E", _scc_parse_type);
|
||||||
|
|
||||||
// enum { RED, GREEN, BLUE } (匿名枚举定义)
|
// enum { RED, GREEN, BLUE } (匿名枚举定义)
|
||||||
@@ -1140,9 +1171,15 @@ static void test_parser_type(void) {
|
|||||||
scc_vec_push(enumerators, &green);
|
scc_vec_push(enumerators, &green);
|
||||||
scc_vec_push(enumerators, &blue);
|
scc_vec_push(enumerators, &blue);
|
||||||
|
|
||||||
scc_ast_type_t enum_def;
|
scc_ast_decl_t enum_def;
|
||||||
scc_ast_type_enum_init(&enum_def, NULL, &enumerators);
|
scc_ast_decl_enum_init(&enum_def, null, &enumerators);
|
||||||
SCC_CHECK_AST(&enum_def.base, "enum { RED, GREEN, BLUE }",
|
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);
|
_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_CHECK_AST(&ptr_to_array.base, "const int * volatile (*)[10]",
|
||||||
_scc_parse_type);
|
_scc_parse_type);
|
||||||
|
|
||||||
// int (*(*)(int, ...))(float)
|
// float (*(*)(int, ...))()
|
||||||
// 1) float 类型作为内部函数返回类型
|
// 1) float 类型作为内部函数返回类型
|
||||||
// 2) 构建返回 float 的函数类型,无参数(或者参数为空)
|
// 2) 构建返回 float 的函数类型,无参数(或者参数为空)
|
||||||
scc_ast_type_t func_ret_float;
|
scc_ast_type_t func_ret_float;
|
||||||
scc_ast_type_function_init(
|
scc_ast_type_function_init(
|
||||||
&func_ret_float, (scc_ast_type_t *)&scc_ast_builtin_type_float,
|
&func_ret_float, (scc_ast_type_t *)&scc_ast_builtin_type_float,
|
||||||
NULL);
|
null);
|
||||||
|
|
||||||
// 3) 指针指向该函数
|
// 3) 指针指向该函数
|
||||||
scc_ast_type_t ptr_to_func_ret_float;
|
scc_ast_type_t ptr_to_func_ret_float;
|
||||||
@@ -1220,7 +1257,7 @@ static void test_parser_type(void) {
|
|||||||
// 5) 指针指向外层函数
|
// 5) 指针指向外层函数
|
||||||
scc_ast_type_t ptr_to_outer_func;
|
scc_ast_type_t ptr_to_outer_func;
|
||||||
scc_ast_type_pointer_init(&ptr_to_outer_func, &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);
|
_scc_parse_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1233,4 +1270,4 @@ TEST_LIST = {
|
|||||||
// {"parser_declaration", test_parser_declaration},
|
// {"parser_declaration", test_parser_declaration},
|
||||||
// {"parser_translation_unit", test_parser_translation_unit},
|
// {"parser_translation_unit", test_parser_translation_unit},
|
||||||
{null, null},
|
{null, null},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user