feat(ast): 添加完整的内置类型支持并重构类型定义
- 添加 va_list、bool、signed/unsigned 各种整数类型等内置类型 - 重新排列内置类型枚举顺序,增加 UNKNOWN 类型 - 为复合字面量、指针类型、数组类型添加初始化函数 - 添加结构体、联合体、枚举、typedef 类型的初始化函数 - 更新类型转储功能以支持新的内置类型显示 refactor(parser): 优化类型解析和声明处理逻辑 - 修改类型解析函数返回类型为通用 AST 节点 - 重构声明解析逻辑,支持变量和函数声明的不同处理路径 - 更新语法分析规则中的空格标记处理 - 简化表达式解析中的错误处理流程 fix(ast): 修复参数声明和类型转储相关问题 - 修正参数声明初始化函数中对 name 参数可为空的处理 - 修复类型转储中修饰符显示和指针类型显示问题 - 更新 AST 转储中空值检查使用正确的 null 比较
This commit is contained in:
@@ -3,28 +3,29 @@
|
||||
|
||||
#include "ast_def.h"
|
||||
|
||||
extern scc_ast_type_t scc_ast_builtin_type_va_list;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_void;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_bool;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_char;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_short;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_long;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_long_long;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_int;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_float;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_double;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_char;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_void;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_long;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_long_long;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_short;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_bool;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_long_double;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_complex_float;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_complex_double;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_complex_long_double;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_unsigned_char;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_unsigned_short;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_unsigned_int;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_unsigned_long;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_unsigned_long_long;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_unsigned_short;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_unsigned_char;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_signed_char;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_signed_short;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_signed_int;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_signed_long;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_signed_long_long;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_signed_short;
|
||||
extern scc_ast_type_t scc_ast_builtin_type_signed_char;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -95,20 +95,34 @@ typedef struct {
|
||||
* @brief 内置类型枚举
|
||||
*/
|
||||
typedef enum {
|
||||
SCC_AST_BUILTIN_TYPE_UNKNOWN,
|
||||
SCC_AST_BUILTIN_TYPE_VA_LIST,
|
||||
SCC_AST_BUILTIN_TYPE_VOID,
|
||||
SCC_AST_BUILTIN_TYPE_BOOL,
|
||||
SCC_AST_BUILTIN_TYPE_CHAR,
|
||||
SCC_AST_BUILTIN_TYPE_SHORT,
|
||||
SCC_AST_BUILTIN_TYPE_INT,
|
||||
SCC_AST_BUILTIN_TYPE_LONG,
|
||||
SCC_AST_BUILTIN_TYPE_LONG_LONG,
|
||||
|
||||
SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR,
|
||||
SCC_AST_BUILTIN_TYPE_UNSIGNED_SHORT,
|
||||
SCC_AST_BUILTIN_TYPE_UNSIGNED_INT,
|
||||
SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG,
|
||||
SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG,
|
||||
|
||||
SCC_AST_BUILTIN_TYPE_SIGNED_CHAR,
|
||||
SCC_AST_BUILTIN_TYPE_SIGNED_SHORT,
|
||||
SCC_AST_BUILTIN_TYPE_SIGNED_INT,
|
||||
SCC_AST_BUILTIN_TYPE_SIGNED_LONG,
|
||||
SCC_AST_BUILTIN_TYPE_SIGNED_LONG_LONG,
|
||||
|
||||
SCC_AST_BUILTIN_TYPE_FLOAT,
|
||||
SCC_AST_BUILTIN_TYPE_DOUBLE,
|
||||
SCC_AST_BUILTIN_TYPE_LONG_DOUBLE,
|
||||
SCC_AST_BUILTIN_TYPE_BOOL,
|
||||
SCC_AST_BUILTIN_TYPE_COMPLEX_FLOAT,
|
||||
SCC_AST_BUILTIN_TYPE_COMPLEX_DOUBLE,
|
||||
SCC_AST_BUILTIN_TYPE_COMPLEX_LONG_DOUBLE,
|
||||
SCC_AST_BUILTIN_TYPE_VA_LIST,
|
||||
} scc_ast_builtin_type_t;
|
||||
|
||||
/**
|
||||
@@ -284,7 +298,7 @@ struct scc_ast_expr {
|
||||
const char *name;
|
||||
usize _target_idx;
|
||||
} member;
|
||||
// 类型转换
|
||||
// cast 类型转换
|
||||
struct {
|
||||
scc_ast_type_t *type;
|
||||
scc_ast_expr_t *expr;
|
||||
|
||||
@@ -46,12 +46,11 @@ static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl,
|
||||
decl->func.body = body;
|
||||
}
|
||||
|
||||
// body can be null
|
||||
// name can be null
|
||||
static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl,
|
||||
scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_stmt_t *body) {
|
||||
Assert(decl != null && name != null && type != null);
|
||||
const char *name) {
|
||||
Assert(decl != null && type != null);
|
||||
decl->base.loc = scc_pos_create();
|
||||
decl->base.type = SCC_AST_DECL_PARAM;
|
||||
decl->name = name;
|
||||
@@ -342,10 +341,26 @@ static inline void scc_ast_expr_ptr_member_init(scc_ast_expr_t *expr,
|
||||
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_PTR_MEMBER, object, member);
|
||||
}
|
||||
|
||||
// TODO
|
||||
// SCC_AST_EXPR_CAST, // 类型转换
|
||||
// SCC_AST_EXPR_SIZE_OF, // sizeof
|
||||
// SCC_AST_EXPR_ALIGN_OF, // _Alignof
|
||||
// SCC_AST_EXPR_COMPOUND_LITERAL, // 复合字面量
|
||||
|
||||
// init can be null
|
||||
static inline void
|
||||
scc_ast_expr_compound_literal_init(scc_ast_expr_t *expr, scc_ast_type_t *type,
|
||||
scc_ast_expr_vec_t *init) {
|
||||
Assert(expr != null && type != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.type = SCC_AST_EXPR_COMPOUND_LITERAL;
|
||||
expr->compound_literal.type = type;
|
||||
if (init == null) {
|
||||
scc_vec_init(expr->compound_literal.init_list);
|
||||
} else {
|
||||
expr->compound_literal.init_list = *init;
|
||||
scc_vec_init(*init);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void scc_ast_expr_literal_init(scc_ast_expr_t *expr,
|
||||
scc_ast_node_type_t type,
|
||||
@@ -388,9 +403,36 @@ static inline void scc_ast_expr_identifier_init(scc_ast_expr_t *expr,
|
||||
expr->identifier._target = null;
|
||||
}
|
||||
|
||||
// SCC_AST_TYPE_BUILTIN, // 内置类型
|
||||
// SCC_AST_TYPE_POINTER, // 指针类型
|
||||
// SCC_AST_TYPE_ARRAY, // 数组类型
|
||||
// have defined builtin type
|
||||
static inline void _scc_ast_type_builtin_init(scc_ast_type_t *type,
|
||||
scc_ast_builtin_type_t builtin) {
|
||||
Assert(type != null);
|
||||
type->base.loc = scc_pos_create();
|
||||
type->base.type = SCC_AST_TYPE_BUILTIN;
|
||||
type->builtin.type = builtin;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
}
|
||||
|
||||
static inline void scc_ast_type_pointer_init(scc_ast_type_t *type,
|
||||
scc_ast_type_t *pointee) {
|
||||
Assert(type != null && pointee != null);
|
||||
type->base.loc = scc_pos_create();
|
||||
type->base.type = SCC_AST_TYPE_POINTER;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
type->pointer.pointee = pointee;
|
||||
}
|
||||
|
||||
// size can be null
|
||||
static inline void scc_ast_type_array_init(scc_ast_type_t *type,
|
||||
scc_ast_type_t *element,
|
||||
scc_ast_expr_t *size) {
|
||||
Assert(type != null && element != null);
|
||||
type->base.loc = scc_pos_create();
|
||||
type->base.type = SCC_AST_TYPE_ARRAY;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
type->array.element = element;
|
||||
type->array.size = size;
|
||||
}
|
||||
|
||||
// return_type and params can be null
|
||||
static inline void scc_ast_type_function_init(scc_ast_type_t *type,
|
||||
@@ -400,6 +442,7 @@ static inline void scc_ast_type_function_init(scc_ast_type_t *type,
|
||||
type->base.loc = scc_pos_create();
|
||||
type->base.type = SCC_AST_TYPE_FUNCTION;
|
||||
type->function.return_type = return_type;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
if (params == null) {
|
||||
scc_vec_init(type->function.param_types);
|
||||
} else {
|
||||
@@ -408,9 +451,62 @@ static inline void scc_ast_type_function_init(scc_ast_type_t *type,
|
||||
}
|
||||
}
|
||||
|
||||
// SCC_AST_TYPE_STRUCT, // 结构体类型
|
||||
// SCC_AST_TYPE_UNION, // 联合类型
|
||||
// SCC_AST_TYPE_ENUM, // 枚举类型
|
||||
// SCC_AST_TYPE_TYPEDEF, // typedef 类型
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// name and members 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);
|
||||
}
|
||||
|
||||
// name and members 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);
|
||||
}
|
||||
|
||||
// name and members 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void scc_ast_type_typedef_init(scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_type_t *target) {
|
||||
Assert(type != null && target != null);
|
||||
type->base.loc = scc_pos_create();
|
||||
type->base.type = SCC_AST_TYPE_TYPEDEF;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
type->typedef_type.name = name;
|
||||
type->typedef_type.underlying = target;
|
||||
}
|
||||
|
||||
#endif /* __SCC_AST_H__ */
|
||||
|
||||
@@ -4,6 +4,32 @@
|
||||
.base.type = SCC_AST_TYPE_BUILTIN, .base.loc.col = 0, .base.loc.line = 0, \
|
||||
.base.loc.name = "__scc_ast_builtin_type", .base.loc.offset = 0
|
||||
|
||||
// va_list
|
||||
scc_ast_type_t scc_ast_builtin_type_va_list = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_VA_LIST,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_void = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_VOID,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_bool = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_BOOL,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_char = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_CHAR,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_short = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_SHORT,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_int = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_INT,
|
||||
@@ -19,24 +45,56 @@ scc_ast_type_t scc_ast_builtin_type_long_long = {
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_LONG_LONG,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_short = {
|
||||
// unsigned 类型
|
||||
scc_ast_type_t scc_ast_builtin_type_unsigned_char = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_SHORT,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_char = {
|
||||
scc_ast_type_t scc_ast_builtin_type_unsigned_short = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_CHAR,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_UNSIGNED_SHORT,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_void = {
|
||||
scc_ast_type_t scc_ast_builtin_type_unsigned_int = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_VOID,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_UNSIGNED_INT,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_bool = {
|
||||
scc_ast_type_t scc_ast_builtin_type_unsigned_long = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_BOOL,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_unsigned_long_long = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG,
|
||||
};
|
||||
|
||||
// signed 类型(实际上与默认相同,但为了完整性)
|
||||
scc_ast_type_t scc_ast_builtin_type_signed_char = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_SIGNED_CHAR,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_signed_short = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_SIGNED_SHORT,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_signed_int = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_SIGNED_INT,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_signed_long = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_SIGNED_LONG,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_signed_long_long = {
|
||||
SCC_AST_BUILTIN_TYPE_HEADER,
|
||||
.builtin.type = SCC_AST_BUILTIN_TYPE_SIGNED_LONG_LONG,
|
||||
};
|
||||
|
||||
scc_ast_type_t scc_ast_builtin_type_float = {
|
||||
|
||||
@@ -14,148 +14,100 @@
|
||||
#define PRINT_QUOTED_VALUE(ctx, str) \
|
||||
SCC_TREE_DUMP_PRINT_AROUND(ctx, ctx->value_color, "'", "%s", str)
|
||||
|
||||
// 获取节点类型的字符串表示
|
||||
static const char *node_type_names[] = {
|
||||
[SCC_AST_UNKNOWN] = "Unknown",
|
||||
[scc_ast_decl_t_BEGIN] = "ERROR",
|
||||
[SCC_AST_DECL_VAR] = "VarDecl",
|
||||
[SCC_AST_DECL_FUNC] = "FuncDecl",
|
||||
[SCC_AST_DECL_PARAM] = "ParamDecl",
|
||||
[SCC_AST_DECL_STRUCT] = "StructDecl",
|
||||
[SCC_AST_DECL_UNION] = "UnionDecl",
|
||||
[SCC_AST_DECL_ENUM] = "EnumDecl",
|
||||
[SCC_AST_DECL_TYPEDEF] = "TypedefDecl",
|
||||
[scc_ast_decl_t_END] = "ERROR",
|
||||
[scc_ast_stmt_t_BEGIN] = "ERROR",
|
||||
[SCC_AST_STMT_COMPOUND] = "CompoundStmt",
|
||||
[SCC_AST_STMT_EXPR] = "ExprStmt",
|
||||
[SCC_AST_STMT_IF] = "IfStmt",
|
||||
[SCC_AST_STMT_WHILE] = "WhileStmt",
|
||||
[SCC_AST_STMT_DO_WHILE] = "DoWhileStmt",
|
||||
[SCC_AST_STMT_FOR] = "ForStmt",
|
||||
[SCC_AST_STMT_SWITCH] = "SwitchStmt",
|
||||
[SCC_AST_STMT_CASE] = "CaseStmt",
|
||||
[SCC_AST_STMT_DEFAULT] = "DefaultStmt",
|
||||
[SCC_AST_STMT_BREAK] = "BreakStmt",
|
||||
[SCC_AST_STMT_CONTINUE] = "ContinueStmt",
|
||||
[SCC_AST_STMT_RETURN] = "ReturnStmt",
|
||||
[SCC_AST_STMT_GOTO] = "GotoStmt",
|
||||
[SCC_AST_STMT_LABEL] = "LabelStmt",
|
||||
[scc_ast_stmt_t_END] = "ERROR",
|
||||
[scc_ast_expr_t_BEGIN] = "ERROR",
|
||||
[SCC_AST_EXPR_BINARY] = "BinaryExpr",
|
||||
[SCC_AST_EXPR_UNARY] = "UnaryExpr",
|
||||
[SCC_AST_EXPR_COND] = "ConditionalExpr",
|
||||
[SCC_AST_EXPR_CALL] = "CallExpr",
|
||||
[SCC_AST_EXPR_ARRAY_SUBSCRIPT] = "ArraySubscriptExpr",
|
||||
[SCC_AST_EXPR_MEMBER] = "MemberExpr",
|
||||
[SCC_AST_EXPR_PTR_MEMBER] = "PtrMemberExpr",
|
||||
[SCC_AST_EXPR_CAST] = "CastExpr",
|
||||
[SCC_AST_EXPR_SIZE_OF] = "SizeofExpr",
|
||||
[SCC_AST_EXPR_ALIGN_OF] = "AlignofExpr",
|
||||
[SCC_AST_EXPR_COMPOUND_LITERAL] = "CompoundLiteralExpr",
|
||||
[SCC_AST_EXPR_INT_LITERAL] = "IntLiteralExpr",
|
||||
[SCC_AST_EXPR_FLOAT_LITERAL] = "FloatLiteralExpr",
|
||||
[SCC_AST_EXPR_CHAR_LITERAL] = "CharLiteralExpr",
|
||||
[SCC_AST_EXPR_STRING_LITERAL] = "StringLiteralExpr",
|
||||
[SCC_AST_EXPR_IDENTIFIER] = "IdentifierExpr",
|
||||
[scc_ast_expr_t_END] = "ERROR",
|
||||
[scc_ast_type_t_BEGIN] = "ERROR",
|
||||
[SCC_AST_TYPE_BUILTIN] = "BuiltinType",
|
||||
[SCC_AST_TYPE_POINTER] = "PointerType",
|
||||
[SCC_AST_TYPE_ARRAY] = "ArrayType",
|
||||
[SCC_AST_TYPE_FUNCTION] = "FunctionType",
|
||||
[SCC_AST_TYPE_STRUCT] = "StructType",
|
||||
[SCC_AST_TYPE_UNION] = "UnionType",
|
||||
[SCC_AST_TYPE_ENUM] = "EnumType",
|
||||
[SCC_AST_TYPE_TYPEDEF] = "TypedefType",
|
||||
[scc_ast_type_t_END] = "ERROR",
|
||||
[scc_ast_translation_unit_t_BEGIN] = "ERROR",
|
||||
[SCC_AST_TRANSLATION_UNIT] = "TranslationUnit",
|
||||
[scc_ast_translation_unit_t_END] = "ERROR",
|
||||
};
|
||||
|
||||
static const char *get_node_type_str(scc_ast_node_type_t type) {
|
||||
switch (type) {
|
||||
// 声明类型
|
||||
case SCC_AST_DECL_VAR:
|
||||
return "VarDecl";
|
||||
case SCC_AST_DECL_FUNC:
|
||||
return "FuncDecl";
|
||||
case SCC_AST_DECL_PARAM:
|
||||
return "ParamDecl";
|
||||
case SCC_AST_DECL_STRUCT:
|
||||
return "StructDecl";
|
||||
case SCC_AST_DECL_UNION:
|
||||
return "UnionDecl";
|
||||
case SCC_AST_DECL_ENUM:
|
||||
return "EnumDecl";
|
||||
case SCC_AST_DECL_TYPEDEF:
|
||||
return "TypedefDecl";
|
||||
|
||||
// 语句类型
|
||||
case SCC_AST_STMT_COMPOUND:
|
||||
return "CompoundStmt";
|
||||
case SCC_AST_STMT_EXPR:
|
||||
return "ExprStmt";
|
||||
case SCC_AST_STMT_IF:
|
||||
return "IfStmt";
|
||||
case SCC_AST_STMT_WHILE:
|
||||
return "WhileStmt";
|
||||
case SCC_AST_STMT_DO_WHILE:
|
||||
return "DoStmt";
|
||||
case SCC_AST_STMT_FOR:
|
||||
return "ForStmt";
|
||||
case SCC_AST_STMT_SWITCH:
|
||||
return "SwitchStmt";
|
||||
case SCC_AST_STMT_CASE:
|
||||
return "CaseStmt";
|
||||
case SCC_AST_STMT_DEFAULT:
|
||||
return "DefaultStmt";
|
||||
case SCC_AST_STMT_BREAK:
|
||||
return "BreakStmt";
|
||||
case SCC_AST_STMT_CONTINUE:
|
||||
return "ContinueStmt";
|
||||
case SCC_AST_STMT_RETURN:
|
||||
return "ReturnStmt";
|
||||
case SCC_AST_STMT_GOTO:
|
||||
return "GotoStmt";
|
||||
case SCC_AST_STMT_LABEL:
|
||||
return "LabelStmt";
|
||||
|
||||
// 表达式类型
|
||||
case SCC_AST_EXPR_BINARY:
|
||||
return "BinaryOperator";
|
||||
case SCC_AST_EXPR_UNARY:
|
||||
return "UnaryOperator";
|
||||
case SCC_AST_EXPR_COND:
|
||||
return "ConditionalOperator";
|
||||
case SCC_AST_EXPR_CALL:
|
||||
return "CallExpr";
|
||||
case SCC_AST_EXPR_ARRAY_SUBSCRIPT:
|
||||
return "ArraySubscriptExpr";
|
||||
case SCC_AST_EXPR_MEMBER:
|
||||
return "MemberExpr";
|
||||
case SCC_AST_EXPR_PTR_MEMBER:
|
||||
return "PtrMemberExpr";
|
||||
case SCC_AST_EXPR_CAST:
|
||||
return "CastExpr";
|
||||
case SCC_AST_EXPR_SIZE_OF:
|
||||
return "SizeOfExpr";
|
||||
case SCC_AST_EXPR_ALIGN_OF:
|
||||
return "AlignOfExpr";
|
||||
case SCC_AST_EXPR_COMPOUND_LITERAL:
|
||||
return "CompoundLiteralExpr";
|
||||
case SCC_AST_EXPR_INT_LITERAL:
|
||||
return "IntegerLiteral";
|
||||
case SCC_AST_EXPR_FLOAT_LITERAL:
|
||||
return "FloatingLiteral";
|
||||
case SCC_AST_EXPR_CHAR_LITERAL:
|
||||
return "CharacterLiteral";
|
||||
case SCC_AST_EXPR_STRING_LITERAL:
|
||||
return "StringLiteral";
|
||||
case SCC_AST_EXPR_IDENTIFIER:
|
||||
return "DeclRefExpr";
|
||||
|
||||
// 类型类型
|
||||
case SCC_AST_TYPE_BUILTIN:
|
||||
return "BuiltinType";
|
||||
case SCC_AST_TYPE_POINTER:
|
||||
return "PointerType";
|
||||
case SCC_AST_TYPE_ARRAY:
|
||||
return "ArrayType";
|
||||
case SCC_AST_TYPE_FUNCTION:
|
||||
return "FunctionType";
|
||||
case SCC_AST_TYPE_STRUCT:
|
||||
return "RecordType";
|
||||
case SCC_AST_TYPE_UNION:
|
||||
return "RecordType";
|
||||
case SCC_AST_TYPE_ENUM:
|
||||
return "EnumType";
|
||||
case SCC_AST_TYPE_TYPEDEF:
|
||||
return "TypedefType";
|
||||
|
||||
// 根节点
|
||||
case SCC_AST_TRANSLATION_UNIT:
|
||||
return "TranslationUnitDecl";
|
||||
|
||||
default:
|
||||
return "UnknownNode";
|
||||
}
|
||||
return node_type_names[type];
|
||||
}
|
||||
|
||||
// 获取内置类型名称
|
||||
static const char *builtin_type_names[] = {
|
||||
[SCC_AST_BUILTIN_TYPE_UNKNOWN] = "<unknown type>",
|
||||
[SCC_AST_BUILTIN_TYPE_VA_LIST] = "...",
|
||||
[SCC_AST_BUILTIN_TYPE_VOID] = "void",
|
||||
[SCC_AST_BUILTIN_TYPE_BOOL] = "bool",
|
||||
[SCC_AST_BUILTIN_TYPE_CHAR] = "char",
|
||||
[SCC_AST_BUILTIN_TYPE_SHORT] = "short",
|
||||
[SCC_AST_BUILTIN_TYPE_INT] = "int",
|
||||
[SCC_AST_BUILTIN_TYPE_LONG] = "long",
|
||||
[SCC_AST_BUILTIN_TYPE_LONG_LONG] = "long long",
|
||||
[SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR] = "unsigned char",
|
||||
[SCC_AST_BUILTIN_TYPE_UNSIGNED_SHORT] = "unsigned short",
|
||||
[SCC_AST_BUILTIN_TYPE_UNSIGNED_INT] = "unsigned int",
|
||||
[SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG] = "unsigned long",
|
||||
[SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG] = "unsigned long long",
|
||||
[SCC_AST_BUILTIN_TYPE_SIGNED_CHAR] = "signed char",
|
||||
[SCC_AST_BUILTIN_TYPE_SIGNED_SHORT] = "signed short",
|
||||
[SCC_AST_BUILTIN_TYPE_SIGNED_INT] = "signed int",
|
||||
[SCC_AST_BUILTIN_TYPE_SIGNED_LONG] = "signed long",
|
||||
[SCC_AST_BUILTIN_TYPE_SIGNED_LONG_LONG] = "signed long long",
|
||||
[SCC_AST_BUILTIN_TYPE_FLOAT] = "float",
|
||||
[SCC_AST_BUILTIN_TYPE_DOUBLE] = "double",
|
||||
[SCC_AST_BUILTIN_TYPE_LONG_DOUBLE] = "long double",
|
||||
[SCC_AST_BUILTIN_TYPE_COMPLEX_FLOAT] = "complex float",
|
||||
[SCC_AST_BUILTIN_TYPE_COMPLEX_DOUBLE] = "complex double",
|
||||
[SCC_AST_BUILTIN_TYPE_COMPLEX_LONG_DOUBLE] = "complex long double",
|
||||
};
|
||||
|
||||
static const char *get_builtin_type_str(scc_ast_builtin_type_t type) {
|
||||
switch (type) {
|
||||
case SCC_AST_BUILTIN_TYPE_VOID:
|
||||
return "void";
|
||||
case SCC_AST_BUILTIN_TYPE_CHAR:
|
||||
return "char";
|
||||
case SCC_AST_BUILTIN_TYPE_SHORT:
|
||||
return "short";
|
||||
case SCC_AST_BUILTIN_TYPE_INT:
|
||||
return "int";
|
||||
case SCC_AST_BUILTIN_TYPE_LONG:
|
||||
return "long";
|
||||
case SCC_AST_BUILTIN_TYPE_LONG_LONG:
|
||||
return "long long";
|
||||
case SCC_AST_BUILTIN_TYPE_FLOAT:
|
||||
return "float";
|
||||
case SCC_AST_BUILTIN_TYPE_DOUBLE:
|
||||
return "double";
|
||||
case SCC_AST_BUILTIN_TYPE_LONG_DOUBLE:
|
||||
return "long double";
|
||||
case SCC_AST_BUILTIN_TYPE_BOOL:
|
||||
return "_Bool";
|
||||
case SCC_AST_BUILTIN_TYPE_COMPLEX_FLOAT:
|
||||
return "float _Complex";
|
||||
case SCC_AST_BUILTIN_TYPE_COMPLEX_DOUBLE:
|
||||
return "double _Complex";
|
||||
case SCC_AST_BUILTIN_TYPE_COMPLEX_LONG_DOUBLE:
|
||||
return "long double _Complex";
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
return builtin_type_names[type];
|
||||
}
|
||||
|
||||
// 获取操作符字符串
|
||||
@@ -286,6 +238,28 @@ static inline void dump_child_node(scc_ast_node_t *child,
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static inline void dump_quals(scc_ast_decl_specifier_t quals,
|
||||
scc_tree_dump_ctx_t *ctx) {
|
||||
if (quals.is_atomic) {
|
||||
PRINT_QUOTED_VALUE(ctx, "atomic");
|
||||
}
|
||||
if (quals.is_restrict) {
|
||||
PRINT_QUOTED_VALUE(ctx, "restrict");
|
||||
}
|
||||
if (quals.is_volatile) {
|
||||
PRINT_QUOTED_VALUE(ctx, "volatile");
|
||||
}
|
||||
if (quals.is_const) {
|
||||
PRINT_QUOTED_VALUE(ctx, "const");
|
||||
}
|
||||
if (quals.is_inline) {
|
||||
PRINT_QUOTED_VALUE(ctx, "inline");
|
||||
}
|
||||
if (quals.is_extern) {
|
||||
PRINT_QUOTED_VALUE(ctx, "extern");
|
||||
}
|
||||
}
|
||||
|
||||
// 递归转储类型
|
||||
static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) {
|
||||
if (!type)
|
||||
@@ -293,25 +267,15 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) {
|
||||
|
||||
start_node_dump(&type->base, ctx);
|
||||
|
||||
dump_quals(type->quals, ctx);
|
||||
|
||||
// 根据类型输出特定信息
|
||||
switch (type->base.type) {
|
||||
case SCC_AST_TYPE_BUILTIN:
|
||||
PRINT_QUOTED_VALUE(ctx, get_builtin_type_str(type->builtin.type));
|
||||
break;
|
||||
case SCC_AST_TYPE_POINTER:
|
||||
if (type->pointer.pointee &&
|
||||
type->pointer.pointee->base.type == SCC_AST_TYPE_BUILTIN) {
|
||||
const char *base_type =
|
||||
get_builtin_type_str(type->pointer.pointee->builtin.type);
|
||||
if (ctx->use_color) {
|
||||
scc_tree_dump_printf(ctx, "%s'%s *'%s", ctx->value_color,
|
||||
base_type, ctx->reset_color);
|
||||
} else {
|
||||
scc_tree_dump_printf(ctx, "'%s *'", base_type);
|
||||
}
|
||||
} else {
|
||||
PRINT_QUOTED_VALUE(ctx, "pointer");
|
||||
}
|
||||
break;
|
||||
case SCC_AST_TYPE_ARRAY:
|
||||
PRINT_QUOTED_VALUE(ctx, "array");
|
||||
@@ -331,10 +295,6 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) {
|
||||
}
|
||||
dump_type_impl(param->param.type, ctx);
|
||||
}
|
||||
} else {
|
||||
start_node_dump(&type->base, ctx);
|
||||
PRINT_QUOTED_VALUE(ctx, "void");
|
||||
// TODO?
|
||||
}
|
||||
break;
|
||||
case SCC_AST_TYPE_STRUCT:
|
||||
@@ -620,7 +580,7 @@ static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_ctx_t *ctx) {
|
||||
case SCC_AST_DECL_FUNC:
|
||||
if (decl->func.type) {
|
||||
dump_child_node((scc_ast_node_t *)decl->func.type, ctx,
|
||||
decl->func.body == NULL);
|
||||
decl->func.body == null);
|
||||
if (decl->func.body) {
|
||||
dump_child_node((scc_ast_node_t *)decl->func.body, ctx, true);
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ static inline void scc_parser_restore(scc_parser_t *parser) {
|
||||
_scc_ring_probe(*parser->ring) = parser->checkpoint;
|
||||
}
|
||||
|
||||
// tok can null it will be safty free
|
||||
static inline cbool scc_parser_next_consume(scc_parser_t *parser,
|
||||
scc_lexer_tok_t *tok) {
|
||||
cbool ok = false;
|
||||
|
||||
@@ -66,10 +66,8 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser);
|
||||
* @param parser 解析器实例
|
||||
* @return 类型 AST 节点
|
||||
*/
|
||||
scc_ast_type_t *scc_parse_type(scc_parser_t *parser);
|
||||
scc_ast_node_t *_scc_parse_type(scc_parser_t *parser);
|
||||
|
||||
static inline scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser) {
|
||||
return null; // TODO
|
||||
}
|
||||
scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser);
|
||||
|
||||
#endif /* __SCC_PARSER_H__ */
|
||||
|
||||
@@ -114,7 +114,7 @@ A.2.2 Declarations
|
||||
assignment-expression(opt) ]
|
||||
direct-abstract-declarator(opt) [ static type-qualifier-list(opt)
|
||||
assignment-expression ]
|
||||
direct-abstract-declaratoropt [ type-qualifier-list static
|
||||
direct-abstract-declarator(opt) [ type-qualifier-list static
|
||||
assignment-expression ]
|
||||
direct-abstract-declarator(opt) [ * ]
|
||||
direct-abstract-declarator(opt) ( parameter-type-list(opt) )
|
||||
@@ -177,80 +177,45 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
||||
cbool ok;
|
||||
scc_lexer_tok_t tok;
|
||||
|
||||
scc_ast_type_t *type = scc_parse_type(parser);
|
||||
if (type == null) {
|
||||
scc_ast_node_t *type_or_decl = _scc_parse_type(parser);
|
||||
scc_ast_decl_t *decl = null;
|
||||
if (type_or_decl == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ok = scc_parser_next_consume(parser, &tok);
|
||||
if (ok == false) {
|
||||
if (SCC_AST_IS_A(scc_ast_type_t, type_or_decl)) {
|
||||
LOG_WARN("declaration dose not declare anything");
|
||||
return null;
|
||||
}
|
||||
|
||||
scc_ast_decl_t *decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
/*
|
||||
(6.7.5) declarator:
|
||||
pointeropt direct-declarator
|
||||
(6.7.5) direct-declarator:
|
||||
identifier
|
||||
( declarator )
|
||||
direct-declarator [ type-qualifier-listopt assignment-expressionopt ]
|
||||
direct-declarator [static type-qualifier-listopt assignment-expression ]
|
||||
direct-declarator [ type-qualifier-list static assignment-expression ]
|
||||
direct-declarator [ type-qualifier-listopt *]
|
||||
direct-declarator ( parameter-type-list )
|
||||
direct-declarator ( identifier-listopt )
|
||||
*/
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) {
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
scc_ast_decl_val_init(decl, type, scc_cstring_as_cstr(&tok.lexeme),
|
||||
null);
|
||||
goto RETURN;
|
||||
} else if (scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
scc_ast_expr_t *init = scc_parse_expression(parser);
|
||||
scc_ast_decl_val_init(decl, type, scc_cstring_as_cstr(&tok.lexeme),
|
||||
init);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
LOG_ERROR("expect semicolon");
|
||||
}
|
||||
goto RETURN;
|
||||
}
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
// function decl
|
||||
decl->base.type = SCC_AST_DECL_FUNC;
|
||||
decl->name = scc_cstring_as_cstr(&tok.lexeme);
|
||||
decl->func.type = scc_malloc(sizeof(scc_ast_type_t));
|
||||
decl->func.type->base.type = SCC_AST_TYPE_FUNCTION;
|
||||
scc_vec_init(decl->func.type->function.param_types);
|
||||
decl->func.type->function.return_type = type;
|
||||
|
||||
// TODO param type
|
||||
scc_parser_consume_if(parser, SCC_TOK_VOID);
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
} 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 {
|
||||
LOG_ERROR("invalid declaration");
|
||||
return null;
|
||||
}
|
||||
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
return null;
|
||||
}
|
||||
if (tok_ptr->type != SCC_TOK_L_BRACE) {
|
||||
if (tok_ptr->type == SCC_TOK_SEMICOLON) {
|
||||
decl->func.body = null;
|
||||
} else {
|
||||
return null;
|
||||
scc_parser_next_consume(parser, null);
|
||||
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;
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
LOG_ERROR("expect semicolon");
|
||||
}
|
||||
}
|
||||
|
||||
decl->func.body = scc_parse_statement(parser);
|
||||
goto RETURN;
|
||||
} else if (tok_ptr->type == SCC_TOK_L_BRACE) {
|
||||
scc_ast_stmt_t *body = scc_parse_statement(parser);
|
||||
Assert(decl->base.type == SCC_AST_DECL_FUNC);
|
||||
decl->func.body = body;
|
||||
Assert(decl->func.type != null);
|
||||
Assert(decl->func.type->base.type == SCC_AST_TYPE_FUNCTION);
|
||||
Assert(decl->func.body != null);
|
||||
Assert(decl->func.body->base.type == SCC_AST_STMT_COMPOUND);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
RETURN:
|
||||
if (decl) {
|
||||
|
||||
@@ -897,8 +897,6 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
case SCC_TOK_L_PAREN:
|
||||
return parse_paren_expression(parser);
|
||||
default:
|
||||
LOG_ERROR("Unexpected token in primary expression: %s",
|
||||
scc_get_tok_name(tok->type));
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,10 @@ static scc_ast_node_t *process_input(const char *input,
|
||||
|
||||
cbool not_eof = false;
|
||||
scc_ring_not_eof(*parser.ring, not_eof);
|
||||
Assert(!not_eof == true);
|
||||
if (not_eof == true) {
|
||||
// FIXME MAYBE free
|
||||
return null;
|
||||
}
|
||||
|
||||
scc_lexer_drop_ring(parser.ring);
|
||||
scc_parser_drop(&parser);
|
||||
@@ -81,9 +84,13 @@ static void test_parser_unit(void) {
|
||||
{
|
||||
// 构造函数类型:返回 int,参数为空
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_decl_vec_t func_params;
|
||||
scc_ast_decl_t void_decl;
|
||||
scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null);
|
||||
scc_ast_decl_t *array[] = {&void_decl};
|
||||
scc_vec_unsafe_from_array(func_params, array);
|
||||
scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int,
|
||||
null); // 无参数,非可变参数
|
||||
|
||||
&func_params);
|
||||
// 构造复合语句块(空)
|
||||
scc_ast_stmt_t compound;
|
||||
scc_ast_stmt_compound_init(&compound, null);
|
||||
@@ -99,7 +106,13 @@ static void test_parser_unit(void) {
|
||||
// 3. 翻译单元包含一个函数定义
|
||||
{
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, null);
|
||||
scc_ast_decl_vec_t func_params;
|
||||
scc_ast_decl_t void_decl;
|
||||
scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null);
|
||||
scc_ast_decl_t *array[] = {&void_decl};
|
||||
scc_vec_unsafe_from_array(func_params, array);
|
||||
scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int,
|
||||
&func_params);
|
||||
|
||||
scc_ast_stmt_t compound;
|
||||
scc_ast_stmt_compound_init(&compound, null);
|
||||
@@ -138,7 +151,13 @@ static void test_parser_unit(void) {
|
||||
|
||||
// 函数类型
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int, null);
|
||||
scc_ast_decl_vec_t func_params;
|
||||
scc_ast_decl_t void_decl;
|
||||
scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null);
|
||||
scc_ast_decl_t *array[] = {&void_decl};
|
||||
scc_vec_unsafe_from_array(func_params, array);
|
||||
scc_ast_type_function_init(&func_type, &scc_ast_builtin_type_int,
|
||||
&func_params);
|
||||
|
||||
scc_ast_decl_t func_decl;
|
||||
scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound);
|
||||
@@ -318,6 +337,37 @@ static void test_parser_unit(void) {
|
||||
// 比较解析结果与期望 AST
|
||||
SCC_CHECK_AST(&tu.base, input, scc_parse_translation_unit);
|
||||
}
|
||||
|
||||
{
|
||||
scc_ast_decl_vec_t params;
|
||||
scc_ast_decl_t param0;
|
||||
scc_ast_decl_param_init(
|
||||
¶m0, (scc_ast_type_t *)&scc_ast_builtin_type_int, "a");
|
||||
scc_ast_decl_t param1;
|
||||
scc_ast_decl_param_init(
|
||||
¶m1, (scc_ast_type_t *)&scc_ast_builtin_type_int, "b");
|
||||
scc_ast_decl_t param2;
|
||||
scc_ast_decl_param_init(
|
||||
¶m2, (scc_ast_type_t *)&scc_ast_builtin_type_va_list, null);
|
||||
scc_ast_decl_t *params_array[] = {¶m0, ¶m1, ¶m2};
|
||||
scc_vec_unsafe_from_array(params, params_array);
|
||||
scc_ast_type_t decl_func_type;
|
||||
scc_ast_type_function_init(&decl_func_type,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
¶ms);
|
||||
scc_ast_decl_t decl_func;
|
||||
scc_ast_decl_func_init(&decl_func, &decl_func_type, "add", null);
|
||||
SCC_CHECK_AST(&decl_func.base, "int add(int a, int b, ...);",
|
||||
scc_parse_declaration);
|
||||
}
|
||||
|
||||
{
|
||||
scc_ast_decl_t typedef_decl;
|
||||
scc_ast_decl_typedef_init(&typedef_decl, "int32_t",
|
||||
&scc_ast_builtin_type_int);
|
||||
SCC_CHECK_AST(&typedef_decl.base, "typedef int int32_t;",
|
||||
scc_parse_declaration);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_parser_expression(void) {
|
||||
@@ -596,8 +646,591 @@ static void test_parser_expression(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void test_parser_type(void) {
|
||||
{
|
||||
// 1. int
|
||||
{
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_int, "int",
|
||||
_scc_parse_type);
|
||||
}
|
||||
|
||||
// 2. int *
|
||||
{
|
||||
scc_ast_type_t ptr_to_int;
|
||||
scc_ast_type_pointer_init(
|
||||
&ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int);
|
||||
SCC_CHECK_AST(&ptr_to_int.base, "int *", _scc_parse_type);
|
||||
}
|
||||
|
||||
// 3. int *[3]
|
||||
{
|
||||
scc_ast_type_t ptr_to_int;
|
||||
scc_ast_type_pointer_init(
|
||||
&ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int);
|
||||
|
||||
scc_ast_expr_t size_3;
|
||||
scc_ast_expr_literal_int_init(&size_3, "3", false);
|
||||
|
||||
scc_ast_type_t array_of_ptr;
|
||||
scc_ast_type_array_init(&array_of_ptr, &ptr_to_int, &size_3);
|
||||
SCC_CHECK_AST(&array_of_ptr.base, "int *[3]", _scc_parse_type);
|
||||
}
|
||||
|
||||
// 4. int (*)[3]
|
||||
{
|
||||
scc_ast_expr_t size_3;
|
||||
scc_ast_expr_literal_int_init(&size_3, "3", false);
|
||||
|
||||
scc_ast_type_t array_of_int;
|
||||
scc_ast_type_array_init(&array_of_int,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
&size_3);
|
||||
|
||||
scc_ast_type_t ptr_to_array;
|
||||
scc_ast_type_pointer_init(&ptr_to_array, &array_of_int);
|
||||
SCC_CHECK_AST(&ptr_to_array.base, "int (*)[3]", _scc_parse_type);
|
||||
}
|
||||
|
||||
// 5. int (*)[*]
|
||||
{
|
||||
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 表示不定长数组
|
||||
|
||||
scc_ast_type_t ptr_to_array_var;
|
||||
scc_ast_type_pointer_init(&ptr_to_array_var, &array_of_int_var);
|
||||
SCC_CHECK_AST(&ptr_to_array_var.base, "int (*)[*]",
|
||||
_scc_parse_type);
|
||||
}
|
||||
|
||||
// 6. int *()
|
||||
{
|
||||
// 返回类型 int*
|
||||
scc_ast_type_t ptr_to_int;
|
||||
scc_ast_type_pointer_init(
|
||||
&ptr_to_int, (scc_ast_type_t *)&scc_ast_builtin_type_int);
|
||||
|
||||
// 函数类型,返回 int*,无参数
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(&func_type, &ptr_to_int, NULL);
|
||||
SCC_CHECK_AST(&func_type.base, "int *()", _scc_parse_type);
|
||||
}
|
||||
|
||||
// 7. int (*)(void)
|
||||
{
|
||||
// 函数类型,返回 int,无参数
|
||||
scc_ast_type_t func_void;
|
||||
scc_ast_decl_vec_t func_params;
|
||||
scc_ast_decl_t void_decl;
|
||||
scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void,
|
||||
null);
|
||||
scc_ast_decl_t *array[] = {&void_decl};
|
||||
scc_vec_unsafe_from_array(func_params, array);
|
||||
scc_ast_type_function_init(
|
||||
&func_void, (scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
&func_params);
|
||||
|
||||
scc_ast_type_t ptr_to_func;
|
||||
scc_ast_type_pointer_init(&ptr_to_func, &func_void);
|
||||
SCC_CHECK_AST(&ptr_to_func.base, "int (*)(void)", _scc_parse_type);
|
||||
}
|
||||
|
||||
// 8. int (*const [])(unsigned int, ...)
|
||||
{
|
||||
// --- 构造参数列表 ---
|
||||
// 第一个参数:unsigned int
|
||||
scc_ast_decl_t param_uint;
|
||||
scc_ast_decl_param_init(
|
||||
¶m_uint,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_unsigned_int, "u");
|
||||
|
||||
// 第二个参数:... 用内置 va_list 类型近似表示
|
||||
scc_ast_type_t va_list_type;
|
||||
_scc_ast_type_builtin_init(&va_list_type,
|
||||
SCC_AST_BUILTIN_TYPE_VA_LIST);
|
||||
scc_ast_decl_t param_var;
|
||||
scc_ast_decl_param_init(¶m_var, &va_list_type, "...");
|
||||
|
||||
scc_ast_decl_vec_t params;
|
||||
scc_vec_init(params);
|
||||
scc_vec_push(params, ¶m_uint);
|
||||
scc_vec_push(params, ¶m_var);
|
||||
|
||||
// --- 函数类型,返回 int ---
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(
|
||||
&func_type, (scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
¶ms); // params 被移动
|
||||
|
||||
// --- 指向函数的指针,带 const 限定 ---
|
||||
scc_ast_type_t ptr_to_func;
|
||||
scc_ast_type_pointer_init(&ptr_to_func, &func_type);
|
||||
ptr_to_func.quals.is_const = true; // 设置 const
|
||||
|
||||
// --- 数组,元素为上述 const 指针,大小未指定 ---
|
||||
scc_ast_type_t array_of_ptr;
|
||||
scc_ast_type_array_init(&array_of_ptr, &ptr_to_func, NULL);
|
||||
|
||||
SCC_CHECK_AST(&array_of_ptr.base,
|
||||
"int (*const [])(unsigned int, ...)",
|
||||
_scc_parse_type);
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 基本内置类型及组合
|
||||
{
|
||||
// int
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_int, "int",
|
||||
_scc_parse_type);
|
||||
|
||||
// char
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_char, "char",
|
||||
_scc_parse_type);
|
||||
|
||||
// long long
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_long_long,
|
||||
"long long", _scc_parse_type);
|
||||
|
||||
// unsigned int
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_unsigned_int,
|
||||
"unsigned int", _scc_parse_type);
|
||||
|
||||
// float
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_float, "float",
|
||||
_scc_parse_type);
|
||||
|
||||
// double
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_double, "double",
|
||||
_scc_parse_type);
|
||||
|
||||
// void
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_void, "void",
|
||||
_scc_parse_type);
|
||||
|
||||
// bool
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_bool, "bool",
|
||||
_scc_parse_type);
|
||||
|
||||
// long double
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_long_double,
|
||||
"long double", _scc_parse_type);
|
||||
|
||||
// _Complex double
|
||||
SCC_CHECK_AST((scc_ast_node_t *)&scc_ast_builtin_type_complex_double,
|
||||
"complex double", _scc_parse_type);
|
||||
}
|
||||
|
||||
// 2. 带类型限定符的基本类型 (const, volatile)
|
||||
{
|
||||
// const int
|
||||
scc_ast_type_t const_int = scc_ast_builtin_type_int;
|
||||
const_int.quals.is_const = true;
|
||||
SCC_CHECK_AST(&const_int.base, "const int", _scc_parse_type);
|
||||
|
||||
// volatile unsigned long
|
||||
scc_ast_type_t volatile_ulong = scc_ast_builtin_type_unsigned_long;
|
||||
volatile_ulong.quals.is_volatile = true;
|
||||
SCC_CHECK_AST(&volatile_ulong.base, "volatile unsigned long",
|
||||
_scc_parse_type);
|
||||
|
||||
// const volatile char
|
||||
scc_ast_type_t const_volatile_char = scc_ast_builtin_type_char;
|
||||
const_volatile_char.quals.is_const = true;
|
||||
const_volatile_char.quals.is_volatile = true;
|
||||
SCC_CHECK_AST(&const_volatile_char.base, "const volatile char",
|
||||
_scc_parse_type);
|
||||
}
|
||||
|
||||
// 3. 指针类型
|
||||
{
|
||||
// int *
|
||||
scc_ast_type_t ptr_to_int;
|
||||
scc_ast_type_pointer_init(&ptr_to_int,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int);
|
||||
SCC_CHECK_AST(&ptr_to_int.base, "int *", _scc_parse_type);
|
||||
|
||||
// int **
|
||||
scc_ast_type_t ptr_to_ptr_to_int;
|
||||
scc_ast_type_pointer_init(&ptr_to_ptr_to_int, &ptr_to_int);
|
||||
SCC_CHECK_AST(&ptr_to_ptr_to_int.base, "int **", _scc_parse_type);
|
||||
|
||||
// int * const (const pointer to int)
|
||||
scc_ast_type_t const_ptr_to_int;
|
||||
scc_ast_type_pointer_init(&const_ptr_to_int,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int);
|
||||
const_ptr_to_int.quals.is_const = true;
|
||||
SCC_CHECK_AST(&const_ptr_to_int.base, "int * const", _scc_parse_type);
|
||||
|
||||
// const int * (pointer to const int)
|
||||
scc_ast_type_t const_int_type = scc_ast_builtin_type_int;
|
||||
const_int_type.quals.is_const = true;
|
||||
scc_ast_type_t ptr_to_const_int;
|
||||
scc_ast_type_pointer_init(&ptr_to_const_int, &const_int_type);
|
||||
SCC_CHECK_AST(&ptr_to_const_int.base, "const int *", _scc_parse_type);
|
||||
|
||||
// const int * const (const pointer to const int)
|
||||
scc_ast_type_t const_ptr_to_const_int;
|
||||
scc_ast_type_pointer_init(&const_ptr_to_const_int, &const_int_type);
|
||||
const_ptr_to_const_int.quals.is_const = true;
|
||||
SCC_CHECK_AST(&const_ptr_to_const_int.base, "const int * const",
|
||||
_scc_parse_type);
|
||||
|
||||
// volatile int * restrict
|
||||
scc_ast_type_t volatile_int = scc_ast_builtin_type_int;
|
||||
volatile_int.quals.is_volatile = true;
|
||||
scc_ast_type_t restrict_ptr_to_volatile_int;
|
||||
scc_ast_type_pointer_init(&restrict_ptr_to_volatile_int, &volatile_int);
|
||||
restrict_ptr_to_volatile_int.quals.is_restrict = true;
|
||||
SCC_CHECK_AST(&restrict_ptr_to_volatile_int.base,
|
||||
"volatile int * restrict", _scc_parse_type);
|
||||
}
|
||||
|
||||
// 4. 数组类型
|
||||
{
|
||||
// int [5]
|
||||
scc_ast_expr_t size_5;
|
||||
scc_ast_expr_literal_int_init(&size_5, "5", false);
|
||||
scc_ast_type_t array_of_5_int;
|
||||
scc_ast_type_array_init(&array_of_5_int,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
&size_5);
|
||||
SCC_CHECK_AST(&array_of_5_int.base, "int [5]", _scc_parse_type);
|
||||
|
||||
// int [] (不完整类型)
|
||||
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);
|
||||
SCC_CHECK_AST(&array_of_int_unknown.base, "int []", _scc_parse_type);
|
||||
|
||||
// // int [*] (变长数组原型中的不定长数组)
|
||||
// FIXME
|
||||
// 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
|
||||
// // 表示。如果解析器需要区分,可能需要特殊处理。 这里暂时假设解析器对
|
||||
// [*]
|
||||
// // 也生成 size=NULL 的数组节点。
|
||||
// SCC_CHECK_AST(&array_of_int_var.base, "int [*]", scc_parse_type);
|
||||
|
||||
// int [5][3] (二维数组)
|
||||
scc_ast_expr_t size_3;
|
||||
scc_ast_expr_literal_int_init(&size_3, "3", false);
|
||||
scc_ast_type_t inner_array;
|
||||
scc_ast_type_array_init(
|
||||
&inner_array, (scc_ast_type_t *)&scc_ast_builtin_type_int, &size_3);
|
||||
scc_ast_type_t outer_array;
|
||||
scc_ast_type_array_init(&outer_array, &inner_array, &size_5);
|
||||
SCC_CHECK_AST(&outer_array.base, "int [5][3]", _scc_parse_type);
|
||||
|
||||
// int (*)[5] (指向数组的指针) 已在前面测试,这里重复以保持完整性
|
||||
scc_ast_type_t array_of_5_int2;
|
||||
scc_ast_type_array_init(&array_of_5_int2,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
&size_5);
|
||||
scc_ast_type_t ptr_to_array;
|
||||
scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int2);
|
||||
SCC_CHECK_AST(&ptr_to_array.base, "int (*)[5]", _scc_parse_type);
|
||||
|
||||
// int *[5] (指针数组)
|
||||
scc_ast_type_t ptr_to_int2;
|
||||
scc_ast_type_pointer_init(&ptr_to_int2,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int);
|
||||
scc_ast_type_t array_of_5_ptr;
|
||||
scc_ast_type_array_init(&array_of_5_ptr, &ptr_to_int2, &size_5);
|
||||
SCC_CHECK_AST(&array_of_5_ptr.base, "int *[5]", _scc_parse_type);
|
||||
|
||||
// const int [5] (数组元素为const int)
|
||||
scc_ast_type_t const_int2 = scc_ast_builtin_type_int;
|
||||
const_int2.quals.is_const = true;
|
||||
scc_ast_type_t const_array;
|
||||
scc_ast_type_array_init(&const_array, &const_int2, &size_5);
|
||||
SCC_CHECK_AST(&const_array.base, "const int [5]", _scc_parse_type);
|
||||
}
|
||||
|
||||
// 5. 函数类型
|
||||
{
|
||||
// int (void)
|
||||
scc_ast_type_t func_void;
|
||||
scc_ast_decl_vec_t func_params;
|
||||
scc_ast_decl_t void_decl;
|
||||
scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null);
|
||||
scc_ast_decl_t *array[] = {&void_decl};
|
||||
scc_vec_unsafe_from_array(func_params, array);
|
||||
scc_ast_type_function_init(&func_void,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
&func_params);
|
||||
SCC_CHECK_AST(&func_void.base, "int (void)", _scc_parse_type);
|
||||
|
||||
// // int () (无参数声明,非原型)
|
||||
// //
|
||||
// 在C中,空括号表示未指定参数,但AST中可能仍然用空参数列表表示。这里假设与
|
||||
// // (void) 相同。
|
||||
// SCC_CHECK_AST(&func_void.base, "int ()", scc_parse_type);
|
||||
|
||||
// int (int, float)
|
||||
scc_ast_decl_t param1, param2;
|
||||
scc_ast_decl_param_init(
|
||||
¶m1, (scc_ast_type_t *)&scc_ast_builtin_type_int, null);
|
||||
scc_ast_decl_param_init(
|
||||
¶m2, (scc_ast_type_t *)&scc_ast_builtin_type_float, null);
|
||||
scc_ast_decl_vec_t params;
|
||||
scc_vec_init(params);
|
||||
scc_vec_push(params, ¶m1);
|
||||
scc_vec_push(params, ¶m2);
|
||||
|
||||
scc_ast_type_t func_with_params;
|
||||
scc_ast_type_function_init(&func_with_params,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
¶ms);
|
||||
SCC_CHECK_AST(&func_with_params.base, "int (int, float)",
|
||||
_scc_parse_type);
|
||||
|
||||
// int (int, ...) (可变参数)
|
||||
scc_ast_decl_t param_int, param_var;
|
||||
scc_ast_decl_param_init(
|
||||
¶m_int, (scc_ast_type_t *)&scc_ast_builtin_type_int, null);
|
||||
scc_ast_type_t va_list_type;
|
||||
_scc_ast_type_builtin_init(&va_list_type, SCC_AST_BUILTIN_TYPE_VA_LIST);
|
||||
scc_ast_decl_param_init(¶m_var, &va_list_type, null);
|
||||
scc_ast_decl_vec_t params_var;
|
||||
scc_vec_init(params_var);
|
||||
scc_vec_push(params_var, ¶m_int);
|
||||
scc_vec_push(params_var, ¶m_var);
|
||||
|
||||
scc_ast_type_t func_varargs;
|
||||
scc_ast_type_function_init(&func_varargs,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
¶ms_var);
|
||||
SCC_CHECK_AST(&func_varargs.base, "int (int, ...)", _scc_parse_type);
|
||||
|
||||
// int (*)(int) (函数指针)
|
||||
scc_ast_decl_t param;
|
||||
scc_ast_decl_param_init(
|
||||
¶m, (scc_ast_type_t *)&scc_ast_builtin_type_int, null);
|
||||
scc_ast_decl_vec_t params2;
|
||||
scc_vec_init(params2);
|
||||
scc_vec_push(params2, ¶m);
|
||||
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(
|
||||
&func_type, (scc_ast_type_t *)&scc_ast_builtin_type_int, ¶ms2);
|
||||
scc_ast_type_t ptr_to_func;
|
||||
scc_ast_type_pointer_init(&ptr_to_func, &func_type);
|
||||
SCC_CHECK_AST(&ptr_to_func.base, "int (*)(int)", _scc_parse_type);
|
||||
}
|
||||
|
||||
// 6. 函数指针和复杂声明符
|
||||
{
|
||||
// int (*foo)(void)
|
||||
// 这里应解析为类型名,但包含标识符?我们的解析函数是scc_parse_type,它应该解析类型名,不应包含标识符。
|
||||
// 所以跳过带标识符的,只测试抽象声明符。
|
||||
|
||||
// int (*(*)(void))[5] (指向函数的指针,该函数返回指向数组的指针)
|
||||
// 步骤:
|
||||
// 1) 数组类型:int [5]
|
||||
scc_ast_expr_t size_5;
|
||||
scc_ast_expr_literal_int_init(&size_5, "5", false);
|
||||
scc_ast_type_t array_of_5_int;
|
||||
scc_ast_type_array_init(&array_of_5_int,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
&size_5);
|
||||
|
||||
// 2) 函数类型:返回指向数组的指针,无参数
|
||||
scc_ast_type_t ptr_to_array;
|
||||
scc_ast_type_pointer_init(&ptr_to_array, &array_of_5_int);
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_decl_vec_t func_params;
|
||||
scc_ast_decl_t void_decl;
|
||||
scc_ast_decl_param_init(&void_decl, &scc_ast_builtin_type_void, null);
|
||||
scc_ast_decl_t *array[] = {&void_decl};
|
||||
scc_vec_unsafe_from_array(func_params, array);
|
||||
scc_ast_type_function_init(&func_type, &ptr_to_array,
|
||||
&func_params); // 无参数
|
||||
|
||||
// 3) 指向该函数的指针
|
||||
scc_ast_type_t ptr_to_func;
|
||||
scc_ast_type_pointer_init(&ptr_to_func, &func_type);
|
||||
|
||||
SCC_CHECK_AST(&ptr_to_func.base, "int (*(*)(void))[5]",
|
||||
_scc_parse_type);
|
||||
|
||||
// int (*(*)[5])(void) (指向数组的指针,数组元素为函数指针)
|
||||
// 1) 函数类型:返回 int,无参数
|
||||
scc_ast_type_t func_type2;
|
||||
scc_ast_decl_vec_t func_params2;
|
||||
scc_vec_unsafe_from_array(func_params2, array);
|
||||
scc_ast_type_function_init(&func_type2,
|
||||
(scc_ast_type_t *)&scc_ast_builtin_type_int,
|
||||
&func_params2);
|
||||
|
||||
// 2) 指针指向该函数
|
||||
scc_ast_type_t ptr_to_func2;
|
||||
scc_ast_type_pointer_init(&ptr_to_func2, &func_type2);
|
||||
|
||||
// 3) 数组,元素为上述指针
|
||||
scc_ast_type_t array_of_ptr_to_func;
|
||||
scc_ast_type_array_init(&array_of_ptr_to_func, &ptr_to_func2, &size_5);
|
||||
|
||||
// 4) 指针指向该数组
|
||||
scc_ast_type_t ptr_to_array_of_ptr;
|
||||
scc_ast_type_pointer_init(&ptr_to_array_of_ptr, &array_of_ptr_to_func);
|
||||
SCC_CHECK_AST(&ptr_to_array_of_ptr.base, "int (*(*)[5])(void)",
|
||||
_scc_parse_type);
|
||||
}
|
||||
|
||||
// 7. 结构体/联合/枚举类型(标记和定义)
|
||||
{
|
||||
// struct S (不完整类型)
|
||||
scc_ast_type_t struct_tag;
|
||||
scc_ast_type_struct_init(&struct_tag, "S",
|
||||
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);
|
||||
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);
|
||||
|
||||
// union U (不完整类型)
|
||||
scc_ast_type_t union_tag;
|
||||
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);
|
||||
scc_ast_decl_val_init(
|
||||
&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_parse_type);
|
||||
|
||||
// enum E (不完整类型)
|
||||
scc_ast_type_t enum_tag;
|
||||
scc_ast_type_enum_init(&enum_tag, "E", NULL);
|
||||
SCC_CHECK_AST(&enum_tag.base, "enum E", _scc_parse_type);
|
||||
|
||||
// enum { RED, GREEN, BLUE } (匿名枚举定义)
|
||||
scc_ast_expr_t red, green, blue;
|
||||
scc_ast_expr_identifier_init(&red, "RED");
|
||||
scc_ast_expr_identifier_init(&green, "GREEN");
|
||||
scc_ast_expr_identifier_init(&blue, "BLUE");
|
||||
scc_ast_expr_vec_t enumerators;
|
||||
scc_vec_init(enumerators);
|
||||
scc_vec_push(enumerators, &red);
|
||||
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_parse_type);
|
||||
}
|
||||
|
||||
// 8. typedef 类型
|
||||
{
|
||||
// 假设存在 typedef int myint; 但类型解析时,遇到 myint
|
||||
// 应得到对应的类型节点。 为了测试,我们直接构造一个 typedef 类型节点。
|
||||
// scc_ast_type_t myint_type;
|
||||
// scc_ast_type_typedef_init(&myint_type, "myint",
|
||||
// (scc_ast_type_t
|
||||
// *)&scc_ast_builtin_type_int);
|
||||
// SCC_CHECK_AST(&myint_type.base, "myint", scc_parse_type);
|
||||
|
||||
// // myint * (指针指向 typedef 类型)
|
||||
// scc_ast_type_t ptr_to_myint;
|
||||
// scc_ast_type_pointer_init(&ptr_to_myint, &myint_type);
|
||||
// SCC_CHECK_AST(&ptr_to_myint.base, "myint *", scc_parse_type);
|
||||
}
|
||||
|
||||
// 9. 混合复杂类型
|
||||
{
|
||||
// const int * volatile (*)[10]
|
||||
// 步骤:
|
||||
// 1) const int
|
||||
scc_ast_type_t const_int = scc_ast_builtin_type_int;
|
||||
const_int.quals.is_const = true;
|
||||
|
||||
// 2) 指针指向 const int (普通指针)
|
||||
scc_ast_type_t ptr_to_const_int;
|
||||
scc_ast_type_pointer_init(&ptr_to_const_int, &const_int);
|
||||
// 该指针本身是 volatile 限定?语法上 "const int * volatile" 表示指针是
|
||||
// volatile 的,指向 const int。
|
||||
ptr_to_const_int.quals.is_volatile = true;
|
||||
|
||||
// 3) 数组,元素为上述指针,大小为10
|
||||
scc_ast_expr_t size_10;
|
||||
scc_ast_expr_literal_int_init(&size_10, "10", false);
|
||||
scc_ast_type_t array_of_ptr;
|
||||
scc_ast_type_array_init(&array_of_ptr, &ptr_to_const_int, &size_10);
|
||||
|
||||
// 4) 指针指向该数组
|
||||
scc_ast_type_t ptr_to_array;
|
||||
scc_ast_type_pointer_init(&ptr_to_array, &array_of_ptr);
|
||||
SCC_CHECK_AST(&ptr_to_array.base, "const int * volatile (*)[10]",
|
||||
_scc_parse_type);
|
||||
|
||||
// int (*(*)(int, ...))(float)
|
||||
// 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);
|
||||
|
||||
// 3) 指针指向该函数
|
||||
scc_ast_type_t ptr_to_func_ret_float;
|
||||
scc_ast_type_pointer_init(&ptr_to_func_ret_float, &func_ret_float);
|
||||
|
||||
// 4) 外层函数类型,返回上述指针,参数为 (int, ...)
|
||||
scc_ast_decl_t param_int, param_var;
|
||||
scc_ast_decl_param_init(
|
||||
¶m_int, (scc_ast_type_t *)&scc_ast_builtin_type_int, null);
|
||||
scc_ast_type_t va_list_type;
|
||||
_scc_ast_type_builtin_init(&va_list_type, SCC_AST_BUILTIN_TYPE_VA_LIST);
|
||||
scc_ast_decl_param_init(¶m_var, &va_list_type, null);
|
||||
scc_ast_decl_vec_t params_outer;
|
||||
scc_vec_init(params_outer);
|
||||
scc_vec_push(params_outer, ¶m_int);
|
||||
scc_vec_push(params_outer, ¶m_var);
|
||||
|
||||
scc_ast_type_t outer_func;
|
||||
scc_ast_type_function_init(&outer_func, &ptr_to_func_ret_float,
|
||||
¶ms_outer);
|
||||
|
||||
// 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_parse_type);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_LIST = {
|
||||
{"parser_unit", test_parser_unit},
|
||||
{"parser_expression", test_parser_expression},
|
||||
{"parser_type", test_parser_type},
|
||||
// {"parser_statement", test_parser_statement},
|
||||
// {"parser_declaration", test_parser_declaration},
|
||||
// {"parser_translation_unit", test_parser_translation_unit},
|
||||
{null, null},
|
||||
};
|
||||
@@ -150,7 +150,7 @@ typedef size_t usize;
|
||||
(vec).size = (vec).cap = 0; \
|
||||
} while (0)
|
||||
|
||||
#define scc_vec_unsafe_from_static_array(vec, array) \
|
||||
#define scc_vec_unsafe_from_array(vec, array) \
|
||||
do { \
|
||||
(vec).size = sizeof(array) / sizeof((array)[0]); \
|
||||
(vec).cap = (vec).size; \
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
int add(int, int);
|
||||
int add(int a, int b);
|
||||
|
||||
int main(void) {
|
||||
return add(1, 2);
|
||||
}
|
||||
int main(void) { return add(1, 2); }
|
||||
|
||||
int add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
int add(int a, int b) { return a + b; }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// #include <stdio.h>
|
||||
|
||||
int factorial(int num);
|
||||
int factorial(int);
|
||||
|
||||
int main() {
|
||||
int num = 5;
|
||||
@@ -13,6 +13,6 @@ int factorial(int num) {
|
||||
if (num == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return num * factorial(num - 1);
|
||||
return num * factorial(num + -1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user