Files
scc/libs/ast/include/scc_ast.h
zzy 5f915ba8d3 refactor(ast): 移除内置类型头文件并优化类型初始化
移除了独立的ast_builtin.h头文件,将内置类型定义整合到现有结构中,
同时修复了类型初始化函数命名不一致的问题。

BREAKING CHANGE: 原有的ast_builtin.h头文件已被移除,
相关内置类型声明已重构为新的接口形式。

fix(parser): 修复表达式解析中的位置信息处理

确保条件表达式和逗号表达式的解析正确获取并传递位置信息,
避免在语法树构建过程中丢失源码位置。

refactor(ir): 修复IR转储中的类型转换问题

添加必要的类型转换以防止整数溢出,并优化代码格式以提高可读性。

feat(parser): 添加表达式解析测试套件

引入全面的表达式解析测试框架,覆盖从基本表达式到复杂嵌套表达式
的各种场景,确保解析器功能的正确性和稳定性。
2026-03-18 12:18:56 +08:00

615 lines
24 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifndef __SCC_AST_H__
#define __SCC_AST_H__
#include "ast_def.h"
#include "ast_dump.h"
// decls can be null but maybe warning
static inline void
scc_ast_translation_unit_init(scc_ast_translation_unit_t *translation_unit,
scc_ast_decl_vec_t *decls, scc_pos_t loc) {
Assert(translation_unit != null);
translation_unit->base.type = SCC_AST_TRANSLATION_UNIT;
translation_unit->base.loc = loc;
if (decls == null) {
scc_vec_init(translation_unit->declarations);
} else {
translation_unit->declarations = *decls;
scc_vec_init(*decls);
}
}
static inline void scc_ast_decl_list_init(scc_ast_decl_t *decl,
scc_ast_decl_vec_t *list_move,
scc_pos_t loc) {
Assert(decl != null && list_move != null);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_LIST;
decl->name = null;
decl->list.vars = *list_move;
scc_vec_init(*list_move);
}
// name and var_init can be null
static inline void scc_ast_decl_unsafe_val_init(scc_ast_decl_t *decl,
scc_ast_type_t *type,
const char *name,
scc_ast_expr_t *var_init,
scc_pos_t loc) {
Assert(decl != null && type != null);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_VAR;
decl->name = name;
decl->var.type = type;
decl->var.init = var_init;
}
// var_init can be null
static inline void scc_ast_decl_val_init(scc_ast_decl_t *decl,
scc_ast_type_t *type, const char *name,
scc_ast_expr_t *var_init,
scc_pos_t loc) {
Assert(decl != null && name != null && type != null);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_VAR;
decl->name = name;
decl->var.type = type;
decl->var.init = var_init;
}
// body can be null
static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl,
scc_ast_type_t *type,
const char *name,
scc_ast_stmt_t *body, scc_pos_t loc) {
Assert(decl != null && name != null && type != null);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_FUNC;
decl->name = name;
decl->func.type = type;
Assert(type->base.type == SCC_AST_TYPE_FUNCTION);
decl->func.body = body;
}
// 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_pos_t loc) {
Assert(decl != null && type != null);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_PARAM;
decl->name = name;
decl->param.type = type;
}
// name and fields can be null
static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_decl_vec_t *fields_move,
scc_pos_t loc) {
Assert(decl != null);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_STRUCT;
decl->name = name;
if (fields_move == null) {
scc_vec_init(decl->record.fields);
} else {
decl->record.fields = *fields_move;
scc_vec_init(*fields_move);
}
}
// name and fields can be null
static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_decl_vec_t *fields_move,
scc_pos_t loc) {
Assert(decl != null);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_UNION;
decl->name = name;
if (fields_move == null) {
scc_vec_init(decl->record.fields);
} else {
decl->record.fields = *fields_move;
scc_vec_init(*fields_move);
}
}
// name and fields can be null
static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_expr_vec_t *fields_move,
scc_pos_t loc) {
Assert(decl != null);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_ENUM;
decl->name = name;
if (fields_move == null) {
scc_vec_init(decl->enumeration.enumerators);
} else {
decl->enumeration.enumerators = *fields_move;
scc_vec_init(*fields_move);
}
}
static inline void scc_ast_decl_typedef_init(scc_ast_decl_t *decl,
const char *name,
scc_ast_type_t *type,
scc_pos_t loc) {
Assert(decl != null && name != null && type != null);
decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_TYPEDEF;
decl->name = name;
decl->typedef_decl.type = type;
}
// items can be null
static inline void scc_ast_stmt_compound_init(
scc_ast_stmt_t *stmt, scc_ast_block_item_vec_t *items_move, scc_pos_t loc) {
Assert(stmt != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_COMPOUND;
if (items_move == null) {
scc_vec_init(stmt->compound.block_items);
} else {
stmt->compound.block_items = *items_move;
scc_vec_init(*items_move);
}
}
// expr can be null
static inline void scc_ast_stmt_expr_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *expr, scc_pos_t loc) {
Assert(stmt != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_EXPR;
stmt->expr.expr = expr;
}
// opt_else can be null
static inline void scc_ast_stmt_if_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *then,
scc_ast_stmt_t *opt_else,
scc_pos_t loc) {
Assert(stmt != null && cond != null && then != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_IF;
stmt->if_stmt.cond = cond;
stmt->if_stmt.then_stmt = then;
stmt->if_stmt.opt_else_stmt = opt_else;
}
static inline void scc_ast_stmt_while_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *body,
scc_pos_t loc) {
Assert(stmt != null && cond != null && body != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_WHILE;
stmt->while_stmt.cond = cond;
stmt->while_stmt.body = body;
}
static inline void scc_ast_stmt_do_while_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *body,
scc_pos_t loc) {
Assert(stmt != null && cond != null && body != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_DO_WHILE;
stmt->while_stmt.cond = cond;
stmt->while_stmt.body = body;
}
// FIXME
static inline void scc_ast_stmt_for_init(scc_ast_stmt_t *stmt,
scc_ast_type_t *init,
scc_ast_expr_t *cond,
scc_ast_expr_t *incr,
scc_ast_stmt_t *body, scc_pos_t loc) {
Assert(stmt != null && body != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_FOR;
stmt->for_stmt.init = init;
stmt->for_stmt.cond = cond;
stmt->for_stmt.incr = incr;
stmt->for_stmt.body = body;
}
static inline void scc_ast_stmt_switch_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *body,
scc_pos_t loc) {
Assert(stmt != null && cond != null && body != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_SWITCH;
stmt->switch_stmt.cond = cond;
stmt->switch_stmt.body = body;
}
static inline void scc_ast_stmt_case_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond,
scc_ast_stmt_t *body, scc_pos_t loc) {
Assert(stmt != null && cond != null && body != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_CASE;
stmt->case_stmt.expr = cond;
stmt->case_stmt.stmt = body;
}
static inline void scc_ast_stmt_default_init(scc_ast_stmt_t *stmt,
scc_ast_stmt_t *body,
scc_pos_t loc) {
Assert(stmt != null && body != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_DEFAULT;
stmt->default_stmt.stmt = body;
}
static inline void scc_ast_stmt_break_init(scc_ast_stmt_t *stmt,
scc_pos_t loc) {
Assert(stmt != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_BREAK;
stmt->jump._target = null;
}
static inline void scc_ast_stmt_continue_init(scc_ast_stmt_t *stmt,
scc_pos_t loc) {
Assert(stmt != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_CONTINUE;
stmt->jump._target = null;
}
// expr can be null
static inline void scc_ast_stmt_return_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *expr,
scc_pos_t loc) {
Assert(stmt != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_RETURN;
stmt->return_stmt.expr = expr;
}
static inline void scc_ast_stmt_goto_init(scc_ast_stmt_t *stmt,
const char *label, scc_pos_t loc) {
Assert(stmt != null && label != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_GOTO;
stmt->goto_stmt.label = label;
stmt->goto_stmt._target = null;
}
static inline void scc_ast_stmt_label_init(scc_ast_stmt_t *stmt,
const char *label,
scc_ast_stmt_t *body,
scc_pos_t loc) {
Assert(stmt != null);
stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_LABEL;
stmt->label_stmt.label = label;
stmt->label_stmt.stmt = body;
}
static inline void scc_ast_expr_binary_init(scc_ast_expr_t *expr,
scc_ast_expr_op_t op,
scc_ast_expr_t *lhs,
scc_ast_expr_t *rhs,
scc_pos_t loc) {
Assert(expr != null && lhs != null && rhs != null);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_BINARY;
expr->binary.op = op;
expr->binary.lhs = lhs;
expr->binary.rhs = rhs;
}
static inline void scc_ast_expr_unary_init(scc_ast_expr_t *expr,
scc_ast_expr_op_t op,
scc_ast_expr_t *operand,
scc_pos_t loc) {
Assert(expr != null && operand != null);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_UNARY;
expr->unary.op = op;
expr->unary.operand = operand;
}
static inline void scc_ast_expr_cond_init(scc_ast_expr_t *expr,
scc_ast_expr_t *cond,
scc_ast_expr_t *then_expr,
scc_ast_expr_t *else_expr,
scc_pos_t loc) {
Assert(expr != null && cond != null && then_expr != null &&
else_expr != null);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_COND;
expr->cond.cond = cond;
expr->cond.then_expr = then_expr;
expr->cond.else_expr = else_expr;
}
// args can be null
static inline void scc_ast_expr_call_init(scc_ast_expr_t *expr,
scc_ast_expr_t *callee,
scc_ast_expr_vec_t *args,
scc_pos_t loc) {
Assert(expr != null && callee != null);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_CALL;
expr->call.callee = callee;
if (args == null) {
scc_vec_init(expr->call.args);
} else {
expr->call.args = *args;
}
}
// SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标
static inline void scc_ast_expr_array_subscript_init(scc_ast_expr_t *expr,
scc_ast_expr_t *array,
scc_ast_expr_t *index,
scc_pos_t loc) {
Assert(expr != null && array != null && index != null);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_ARRAY_SUBSCRIPT;
expr->subscript.array = array;
expr->subscript.index = index;
}
static inline void _scc_ast_expr_member_init(scc_ast_expr_t *expr,
scc_ast_node_type_t type,
scc_ast_expr_t *object,
const char *member,
scc_pos_t loc) {
Assert(expr != null && object != null && member != null);
expr->base.loc = loc;
expr->base.type = type;
expr->member.base = object;
expr->member.name = member;
expr->member._target_idx = 0;
}
static inline void scc_ast_expr_member_init(scc_ast_expr_t *expr,
scc_ast_expr_t *object,
const char *member, scc_pos_t loc) {
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_MEMBER, object, member, loc);
}
static inline void scc_ast_expr_ptr_member_init(scc_ast_expr_t *expr,
scc_ast_expr_t *object,
const char *member,
scc_pos_t loc) {
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_PTR_MEMBER, object, member,
loc);
}
static inline void scc_ast_expr_cast_init(scc_ast_expr_t *expr,
scc_ast_type_t *type,
scc_ast_expr_t *operand,
scc_pos_t loc) {
Assert(expr != null && type != null && operand != null);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_CAST;
expr->cast.type = type;
expr->cast.expr = operand;
}
// type and target_expr can be null but it only one of them can be null
static inline void scc_ast_expr_sizeof_init(scc_ast_expr_t *expr,
scc_ast_type_t *type,
scc_ast_expr_t *target_expr,
scc_pos_t loc) {
Assert(expr != null);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_SIZE_OF;
expr->attr_of.type = type;
expr->attr_of.expr = target_expr;
}
// type and target_expr can be null but it only one of them can be null
static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr,
scc_ast_type_t *type,
scc_ast_expr_t *target_expr,
scc_pos_t loc) {
Assert(expr != null);
expr->base.loc = loc;
expr->base.type =
SCC_AST_EXPR_SIZE_OF; // 注意:这里使用了 SIZE_OF可能需要改为 ALIGN_OF
expr->attr_of.type = type;
expr->attr_of.expr = target_expr;
}
// lhs_exprs and rhs_exprs can be null
static inline void scc_ast_expr_compound_init(scc_ast_expr_t *expr,
scc_ast_expr_t *base,
scc_ast_expr_vec_t *lhs_exprs,
scc_ast_expr_vec_t *rhs_exprs,
scc_pos_t loc) {
Assert(expr != null && base != null);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_COMPOUND;
expr->compound.base = base;
if (lhs_exprs == null) {
scc_vec_init(expr->compound.lhs_exprs);
} else {
expr->compound.lhs_exprs = *lhs_exprs;
scc_vec_init(*lhs_exprs);
}
if (rhs_exprs == null) {
scc_vec_init(expr->compound.rhs_exprs);
} else {
expr->compound.rhs_exprs = *rhs_exprs;
scc_vec_init(*rhs_exprs);
}
}
static inline void scc_ast_expr_literal_init(scc_ast_expr_t *expr,
scc_ast_node_type_t type,
const char *value, cbool owned,
scc_pos_t loc) {
Assert(expr != null && value != null);
expr->base.loc = loc;
expr->base.type = type;
expr->literal.lexme = value;
expr->literal.owned = owned;
}
static inline void scc_ast_expr_literal_int_init(scc_ast_expr_t *expr,
const char *value, cbool owned,
scc_pos_t loc) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_INT_LITERAL, value, owned,
loc);
}
static inline void scc_ast_expr_literal_float_init(scc_ast_expr_t *expr,
const char *value,
cbool owned, scc_pos_t loc) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_FLOAT_LITERAL, value, owned,
loc);
}
static inline void scc_ast_expr_literal_char_init(scc_ast_expr_t *expr,
const char *value,
cbool owned, scc_pos_t loc) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_CHAR_LITERAL, value, owned,
loc);
}
static inline void scc_ast_expr_literal_string_init(scc_ast_expr_t *expr,
const char *value,
cbool owned,
scc_pos_t loc) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_STRING_LITERAL, value, owned,
loc);
}
static inline void scc_ast_expr_identifier_init(scc_ast_expr_t *expr,
const char *name,
scc_pos_t loc) {
Assert(expr != null && name != null);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_IDENTIFIER;
expr->identifier.name = name;
expr->identifier._target = null;
}
static inline void scc_ast_expr_lvalue_init(scc_ast_expr_t *expr,
scc_ast_type_t *type,
scc_pos_t loc) {
Assert(expr != null && type != null);
expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_LVALUE;
expr->lvalue.type = type;
}
// have defined builtin type
static inline void scc_ast_type_builtin_init(scc_ast_type_t *type,
scc_ast_builtin_type_t builtin,
scc_pos_t loc) {
Assert(type != null);
type->base.loc = loc;
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,
scc_pos_t loc) {
Assert(type != null && pointee != null);
type->base.loc = loc;
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,
scc_pos_t loc) {
Assert(type != null && element != null);
type->base.loc = loc;
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,
scc_ast_type_t *return_type,
scc_ast_decl_vec_t *params,
scc_pos_t loc) {
Assert(type != null);
type->base.loc = loc;
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.params);
} else {
type->function.params = *params;
scc_vec_init(*params);
}
}
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_t *decl,
scc_pos_t loc) {
Assert(type != null);
type->base.loc = loc;
type->base.type = type_kind;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->record.name = name;
type->record.decl = decl;
}
// name and decl can be null
static inline void scc_ast_type_struct_init(scc_ast_type_t *type,
const char *name,
scc_ast_decl_t *decl,
scc_pos_t loc) {
_scc_ast_type_record_init(type, SCC_AST_TYPE_STRUCT, name, decl, loc);
}
// name and decl can be null
static inline void scc_ast_type_union_init(scc_ast_type_t *type,
const char *name,
scc_ast_decl_t *decl,
scc_pos_t loc) {
_scc_ast_type_record_init(type, SCC_AST_TYPE_UNION, name, decl, loc);
}
// name and decl can be null
static inline void scc_ast_type_enum_init(scc_ast_type_t *type,
const char *name,
scc_ast_decl_t *decl, scc_pos_t loc) {
Assert(type != null);
type->base.loc = loc;
type->base.type = SCC_AST_TYPE_ENUM;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->enumeration.name = name;
type->enumeration.decl = decl;
}
static inline void scc_ast_type_typedef_init(scc_ast_type_t *type,
const char *name,
scc_ast_decl_t *target,
scc_pos_t loc) {
Assert(type != null && target != null);
type->base.loc = loc;
type->base.type = SCC_AST_TYPE_TYPEDEF;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->typedef_type.name = name;
type->typedef_type.decl = target;
}
#endif /* __SCC_AST_H__ */