Files
Compiler/ast.cpp
2025-11-16 21:04:02 +08:00

810 lines
23 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.

#include "ast.h"
#include <cstdlib> // strtoll
#include <cstring>
/* ──────────────────────────
* 内部小工具
* ──────────────────────────*/
namespace {
inline ASTNode* make(ASTTag tag) {
return new ASTNode(tag);
}
// 若左节点已经是某 tag 的列表,则直接 push否则新建列表结点
ASTNode* append_to_list(ASTTag tag, ASTNode* list_or_node, ASTNode* item) {
if (list_or_node && list_or_node->tag == tag) {
list_or_node->kids.push_back(item);
return list_or_node;
}
auto* n = make(tag);
n->kids.reserve(4);
n->kids.push_back(list_or_node);
n->kids.push_back(item);
return n;
}
}
/* ──────────────────────────
* 基本原子节点
* ──────────────────────────*/
ASTNode* new_id_node(const char* name, SourceLoc loc)
{
auto* n = make(ASTTag::ID);
n->loc = loc;
n->text = name;
return n;
}
ASTNode* new_const_node(const char* literal, SourceLoc loc)
{
auto* n = make(ASTTag::CONST);
n->loc = loc;
n->text = literal;
char* endp = nullptr;
n->ival = std::strtoll(literal, &endp, 0);
return n;
}
ASTNode* new_string_node(const char* literal, SourceLoc loc)
{
auto* n = make(ASTTag::STRING);
n->loc = loc;
n->text = literal;
return n;
}
/* ──────────────────────────
* 后缀、调用、成员访问
* ──────────────────────────*/
ASTNode* new_array_ref_node(ASTNode* array, ASTNode* index, SourceLoc loc)
{
auto* n = make(ASTTag::ARRAY_REF);
n->kids = {array, index};
n->loc = loc;
return n;
}
ASTNode* new_func_call_node(ASTNode* callee, ASTNode* arg_list, SourceLoc loc)
{
auto* n = make(ASTTag::FUNC_CALL);
n->kids = {callee};
n->loc = loc;
if (arg_list) n->kids.push_back(arg_list);
return n;
}
ASTNode* new_struct_ref_node(ASTNode* base, const char* field, bool is_ptr_op, SourceLoc loc)
{
auto* n = make(ASTTag::STRUCT_REF);
n->kids = {base};
n->loc = loc;
n->text = field;
n->flag = is_ptr_op;
return n;
}
/* ──────────────────────────
* 自增 / 复合字面量
* ──────────────────────────*/
ASTNode* new_post_inc_node(ASTNode* expr, SourceLoc loc) {
auto* n = make(ASTTag::POST_INC);
n->kids = {expr};
n->loc = loc;
return n;
}
ASTNode* new_post_dec_node(ASTNode* expr, SourceLoc loc) {
auto* n = make(ASTTag::POST_DEC);
n->kids = {expr};
n->loc = loc;
return n;
}
ASTNode* new_pre_inc_node (ASTNode* expr, SourceLoc loc) {
auto* n = make(ASTTag::PRE_INC );
n->kids = {expr};
n->loc = loc;
return n;
}
ASTNode* new_pre_dec_node (ASTNode* expr, SourceLoc loc) {
auto* n = make(ASTTag::PRE_DEC );
n->kids = {expr};
n->loc = loc;
return n;
}
ASTNode* new_compound_literal_node(ASTNode* type_name, ASTNode* init_list, SourceLoc loc)
{
auto* n = make(ASTTag::COMPOUND_LITERAL);
n->kids = {type_name, init_list};
n->loc = loc;
return n;
}
/* ──────────────────────────
* 参数 / 实参与逗号表达式
* ──────────────────────────*/
ASTNode* new_arg_list(ASTNode* first_arg, SourceLoc loc)
{
auto* n = make(ASTTag::ARG_LIST);
n->kids.push_back(first_arg);
n->loc = loc;
return n;
}
ASTNode* append_arg_list(ASTNode* list, ASTNode* arg, SourceLoc loc)
{
ASTNode* n = append_to_list(ASTTag::ARG_LIST, list, arg);
n->loc = loc;
return n;
}
ASTNode* new_expr_list(ASTNode* left, ASTNode* right, SourceLoc loc)
{
ASTNode* n = append_to_list(ASTTag::ARG_LIST, left, right);
n->loc = loc;
return n;
}
/* ──────────────────────────
* 一元 / 二元 / 条件 / 逻辑 / 赋值
* ──────────────────────────*/
ASTNode* new_unary_op_node(int op, ASTNode* operand, SourceLoc loc)
{
auto* n = make(ASTTag::UNARY);
n->loc = loc;
n->ival = op;
n->kids = {operand};
return n;
}
ASTNode* new_sizeof_node(ASTNode* target, bool is_type_name, SourceLoc loc)
{
auto* n = make(ASTTag::SIZEOF_EXPR);
n->flag = is_type_name;
n->loc = loc;
n->kids = {target};
return n;
}
ASTNode* new_cast_node(ASTNode* type_name, ASTNode* expr, SourceLoc loc)
{
auto* n = make(ASTTag::CAST_EXPR);
n->kids = {type_name, expr};
n->loc = loc;
return n;
}
ASTNode* new_binop_node(int op, ASTNode* lhs, ASTNode* rhs, SourceLoc loc)
{
auto* n = make(ASTTag::BINARY);
n->loc = loc;
n->ival = op;
n->kids = {lhs, rhs};
return n;
}
ASTNode* new_logical_and_node(ASTNode* lhs, ASTNode* rhs, SourceLoc loc)
{
auto* n = make(ASTTag::LOGIC_AND);
n->kids = {lhs, rhs};
n->loc = loc;
return n;
}
ASTNode* new_logical_or_node(ASTNode* lhs, ASTNode* rhs, SourceLoc loc)
{
auto* n = make(ASTTag::LOGIC_OR);
n->kids = {lhs, rhs};
n->loc = loc;
return n;
}
ASTNode* new_conditional_node(ASTNode* cond, ASTNode* then_expr, ASTNode* else_expr, SourceLoc loc)
{
auto* n = make(ASTTag::COND);
n->kids = {cond, then_expr, else_expr};
n->loc = loc;
return n;
}
ASTNode* new_assign_node(ASTNode* lhs, int op, ASTNode* rhs, SourceLoc loc)
{
auto* n = make(ASTTag::ASSIGN);
n->loc = loc;
n->ival = op;
n->kids = {lhs, rhs};
return n;
}
/* ──────────────────────────
* 4. 声明 & 类型系统
* ──────────────────────────*/
static ASTNode* new_leaf(ASTTag list_tag, int enum_val, SourceLoc loc)
{
auto* leaf = make(ASTTag::SPECIFIER);
leaf->ival = enum_val;
leaf->loc = loc;
return append_to_list(list_tag, nullptr, leaf);
}
/*—— 声明与说明符 ——*/
ASTNode* new_spec_list(int spec, SourceLoc loc) {
return new_leaf(ASTTag::SPEC_LIST, spec, loc);
}
ASTNode* append_spec_list(ASTNode* list, int spec, SourceLoc loc) {
return append_to_list(ASTTag::SPEC_LIST, list, new_leaf(ASTTag::SPEC_LIST, spec, loc)->kids[0]);
}
ASTNode* new_declaration(ASTNode* spec_list, ASTNode* init_list, SourceLoc loc)
{
auto* n = make(ASTTag::DECLARATION);
n->kids = {spec_list};
n->loc = loc;
if (init_list) n->kids.push_back(init_list);
return n;
}
/*—— initdeclarator 列表 ——*/
ASTNode* new_init_decl(ASTNode* declarator, ASTNode* initializer, SourceLoc loc)
{
auto* n = make(ASTTag::INIT_DECL);
n->kids = {declarator};
n->loc = loc;
if (initializer) n->kids.push_back(initializer);
return n;
}
ASTNode* new_init_list(ASTNode* init_decl, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::INIT_DECL_LIST,nullptr,init_decl);
n->loc = loc;
return n;
}
ASTNode* append_init_list(ASTNode* list, ASTNode* init_decl, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::INIT_DECL_LIST,list,init_decl);
n->loc = loc;
return n;
}
/*—— struct / union / enum ——*/
ASTNode* new_struct_su_node(StructUnionKind su, const char* id, ASTNode* decl_list, SourceLoc loc)
{
auto* n = make(ASTTag::SU_SPEC);
n->ival = su;
n->loc = loc;
if (id) n->text = id;
if (decl_list) n->kids.push_back(decl_list);
return n;
}
ASTNode* new_sdecl_list(ASTNode* sdecl, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::STRUCT_DECL_LIST,nullptr,sdecl);
n->loc = loc;
return n;
}
ASTNode* append_sdecl_list(ASTNode* list, ASTNode* sdecl, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::STRUCT_DECL_LIST, list, sdecl);
n->loc = loc;
return n;
}
ASTNode* new_struct_decl(ASTNode* specq_list, ASTNode* sdecl_list, SourceLoc loc)
{
auto* n = make(ASTTag::STRUCT_DECL);
n->kids = {specq_list, sdecl_list};
n->loc = loc;
return n;
}
ASTNode* new_specq_list(int sq, SourceLoc loc) {
return new_leaf(ASTTag::SPECQ_LIST, sq, loc);
}
ASTNode* append_specq_list(ASTNode* list, int sq, SourceLoc loc) {
return append_to_list(ASTTag::SPECQ_LIST, list, new_leaf(ASTTag::SPECQ_LIST, sq, loc)->kids[0]);
}
ASTNode* new_sdeclarator_list(ASTNode* sdec, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::STRUCT_DECLARATOR_LIST,nullptr,sdec);
n->loc = loc;
return n;
}
ASTNode* append_sdeclarator_list(ASTNode* list, ASTNode* sdec, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::STRUCT_DECLARATOR_LIST, list, sdec);
n->loc = loc;
return n;
}
ASTNode* new_bitfield_node(ASTNode* declarator, ASTNode* width, SourceLoc loc)
{
auto* n = make(ASTTag::BITFIELD);
if (declarator) n->kids.push_back(declarator);
n->kids.push_back(width);
n->loc = loc;
return n;
}
ASTNode* new_enum_node(const char* id, ASTNode* enumerator_list, SourceLoc loc)
{
auto* n = make(ASTTag::ENUM_SPEC);
n->loc = loc;
if (id) n->text = id;
if (enumerator_list) n->kids.push_back(enumerator_list);
return n;
}
ASTNode* new_enum_const(const char* id, ASTNode* val, SourceLoc loc)
{
auto* n = make(ASTTag::ENUM_CONST);
n->text = id;
n->loc = loc;
if (val) n->kids.push_back(val);
return n;
}
ASTNode* new_enum_list(ASTNode* e, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::ENUM_LIST,nullptr,e);
n->loc = loc;
return n;
}
ASTNode* append_enum_list(ASTNode* list, ASTNode* e, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::ENUM_LIST, list,e);
n->loc = loc;
return n;
}
/*—— 类型限定符列表 ——*/
ASTNode* new_tq_list(int tq, SourceLoc loc) {
return new_leaf(ASTTag::TQ_LIST,tq, loc);
}
ASTNode* append_tq_list(ASTNode* list, int tq, SourceLoc loc) {
return append_to_list(ASTTag::TQ_LIST,list,new_leaf(ASTTag::TQ_LIST,tq, loc)->kids[0]);
}
/*—— declarator / pointer / array / func ——*/
ASTNode* new_declarator_node(ASTNode* pointer, ASTNode* direct_decl, SourceLoc loc)
{
auto* n = make(ASTTag::DECLARATOR);
if (pointer) n->kids.push_back(pointer);
n->kids.push_back(direct_decl);
n->loc = loc;
return n;
}
ASTNode* new_decl_ident(const char* id, SourceLoc loc)
{
auto* n = make(ASTTag::DECLARATOR);
n->text = id;
n->loc = loc;
return n;
}
ASTNode* new_array_decl(ASTNode* decl, ASTNode* tq_list,
ASTNode* size_expr, bool is_static, bool is_star, SourceLoc loc)
{
auto* n = make(ASTTag::ARRAY_DECL);
n->kids = {decl};
n->loc = loc;
if (tq_list) n->kids.push_back(tq_list);
if (size_expr) n->kids.push_back(size_expr);
n->flag = is_static || is_star; // 粗略放一起,用位标记也行
return n;
}
ASTNode* new_func_decl(ASTNode* decl, ASTNode* param_type_list, SourceLoc loc)
{
auto* n = make(ASTTag::FUNC_DECL);
n->kids = {decl};
n->loc = loc;
if (param_type_list) n->kids.push_back(param_type_list);
return n;
}
ASTNode* new_oldstyle_func_decl(ASTNode* decl, ASTNode* id_list, SourceLoc loc)
{
auto* n = make(ASTTag::OLD_FUNC_DECL);
n->kids = {decl, id_list};
n->loc = loc;
return n;
}
ASTNode* new_pointer(ASTNode* tq_list, SourceLoc loc)
{
auto* n = make(ASTTag::POINTER);
n->loc = loc;
if (tq_list) n->kids.push_back(tq_list);
return n;
}
ASTNode* prepend_pointer(ASTNode* tq_list, ASTNode* existing, SourceLoc loc)
{
auto* n = make(ASTTag::POINTER);
n->loc = loc;
if (tq_list) n->kids.push_back(tq_list);
n->kids.push_back(existing);
return n;
}
/*—— 参数列表 & 声明 ——*/
ASTNode* new_param_decl(ASTNode* decl_spec, ASTNode* declarator, SourceLoc loc)
{
auto* n = make(ASTTag::PARAM_DECL);
n->kids = {decl_spec};
n->loc = loc;
if (declarator) n->kids.push_back(declarator);
return n;
}
ASTNode* new_param_list(ASTNode* p, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::PARAM_LIST,nullptr,p);
n->loc = loc;
return n;
}
ASTNode* append_param_list(ASTNode* list, ASTNode* p ,SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::PARAM_LIST,list,p);
n->loc = loc;
return n;
}
ASTNode* new_param_list_ellipsis(ASTNode* list, SourceLoc loc)
{
auto* ellip = make(ASTTag::PARAM_LIST_ELIPS);
ellip->loc = loc;
return append_to_list(ASTTag::PARAM_LIST, list, ellip);
}
/*—— 标识符列表 ——*/
ASTNode* new_id_list(const char* id, SourceLoc loc) {
return append_to_list(ASTTag::ID_LIST,nullptr,new_id_node(id, loc));
}
ASTNode* append_id_list(ASTNode* list, const char* id, SourceLoc loc) {
return append_to_list(ASTTag::ID_LIST,list,new_id_node(id, loc));
}
/*—— typename / 抽象声明符 ——*/
ASTNode* new_type_name(ASTNode* specq_list, ASTNode* abs_decl, SourceLoc loc)
{
auto* n = make(ASTTag::TYPE_NAME_NODE);
n->kids = {specq_list};
n->loc = loc;
if (abs_decl) n->kids.push_back(abs_decl);
return n;
}
ASTNode* new_abs_decl(ASTNode* pointer, ASTNode* direct_abs_decl, SourceLoc loc)
{
auto* n = make(ASTTag::ABS_DECL);
n->loc = loc;
if (pointer) n->kids.push_back(pointer);
if (direct_abs_decl) n->kids.push_back(direct_abs_decl);
return n;
}
ASTNode* new_abs_array(ASTNode* size, bool is_star, SourceLoc loc)
{
auto* n = make(ASTTag::ABS_ARRAY);
n->loc = loc;
if (size) n->kids.push_back(size);
n->flag = is_star;
return n;
}
ASTNode* new_abs_array_child(ASTNode* parent, ASTNode* size, bool is_star, SourceLoc loc)
{
ASTNode* n = append_to_list(ASTTag::ABS_ARRAY_CHILD, parent, new_abs_array(size,is_star, loc));
n->loc = loc;
return n;
}
ASTNode* new_abs_func(ASTNode* param_list, SourceLoc loc)
{
auto* n = make(ASTTag::ABS_FUNC);
n->loc = loc;
if (param_list) n->kids.push_back(param_list);
return n;
}
ASTNode* new_abs_func_child(ASTNode* parent, ASTNode* param_list, SourceLoc loc)
{
ASTNode* n = append_to_list(ASTTag::ABS_FUNC_CHILD, parent, new_abs_func(param_list, loc));
n->loc = loc;
return n;
}
/* ──────────────────────────
* 5. 初始化 & 设计化初始化
* ──────────────────────────*/
ASTNode* new_init_expr(ASTNode* expr, SourceLoc loc) {
auto* n = make(ASTTag::INIT_EXPR);
n->kids = {expr};
n->loc = loc;
return n;
}
ASTNode* new_init_item_list(ASTNode* init, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::INIT_ITEM_LIST,nullptr,init);
n->loc = loc;
return n;
}
ASTNode* append_init_item(ASTNode* list, ASTNode* init, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::INIT_ITEM_LIST,list,init);
n->loc = loc;
return n;
}
ASTNode* new_init_list_node(ASTNode* item_list, SourceLoc loc)
{
auto* n = make(ASTTag::INIT_LIST_NODE);
n->kids = {item_list};
n->loc = loc;
return n;
}
/*── 指定化初始化器 ──*/
ASTNode* new_designator_list(ASTNode* d, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::DESIGNATOR_LIST,nullptr,d);
n->loc = loc;
return n;
}
ASTNode* append_designator_list(ASTNode* list, ASTNode* d, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::DESIGNATOR_LIST,list,d);
n->loc = loc;
return n;
}
ASTNode* new_array_designator(ASTNode* const_expr, SourceLoc loc)
{
auto* n = make(ASTTag::ARRAY_DESIGNATOR);
n->kids = {const_expr};
n->loc = loc;
return n;
}
ASTNode* new_field_designator(const char* field, SourceLoc loc)
{
auto* n = make(ASTTag::FIELD_DESIGNATOR);
n->text = field;
n->loc = loc;
return n;
}
ASTNode* new_designated_init(ASTNode* designator_list, ASTNode* initializer, SourceLoc loc)
{
auto* n = make(ASTTag::DESIGNATED_INIT);
n->kids = {designator_list, initializer};
n->loc = loc;
return n;
}
/* ──────────────────────────
* 6. 语句
* ──────────────────────────*/
ASTNode* new_labeled_stmt_id(const char* id, ASTNode* stmt, SourceLoc loc) {
auto* n = make(ASTTag::LABELED_ID_STMT);
n->text=id;
n->loc = loc;
n->kids={stmt};
return n;
}
ASTNode* new_case_stmt(ASTNode* expr, ASTNode* stmt, SourceLoc loc) {
auto* n = make(ASTTag::CASE_STMT);
n->kids={expr,stmt};
n->loc = loc;
return n;
}
ASTNode* new_default_stmt(ASTNode* stmt, SourceLoc loc) {
auto* n = make(ASTTag::DEFAULT_STMT);
n->kids={stmt};
n->loc = loc;
return n;
}
ASTNode* new_compound_stmt(ASTNode* block_item_list, SourceLoc loc)
{
auto* n = make(ASTTag::COMPOUND_STMT);
n->loc = loc;
if (block_item_list) n->kids.push_back(block_item_list);
return n;
}
ASTNode* new_block_item_list(ASTNode* item, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::BLOCK_ITEM_LIST,nullptr,item);
n->loc = loc;
return n;
}
ASTNode* append_block_item_list(ASTNode* list, ASTNode* item, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::BLOCK_ITEM_LIST,list,item);
n->loc = loc;
return n;
}
ASTNode* new_block_decl(ASTNode* decl, SourceLoc loc) {
auto* n = make(ASTTag::BLOCK_DECL);
n->kids={decl};
n->loc = loc;
return n;
}
ASTNode* new_block_stmt(ASTNode* stmt, SourceLoc loc) {
auto* n = make(ASTTag::BLOCK_STMT);
n->kids={stmt};
n->loc = loc;
return n;
}
ASTNode* new_expr_stmt(ASTNode* expr, SourceLoc loc) {
if(!expr) return make(ASTTag::EXPR_STMT);
auto* n=make(ASTTag::EXPR_STMT);
n->kids={expr};
n->loc = loc;
return n;
}
ASTNode* new_if_stmt(ASTNode* cond, ASTNode* then_s, ASTNode* else_s, SourceLoc loc)
{
auto* n = make(ASTTag::IF_STMT);
n->loc = loc;
n->kids = {cond, then_s};
if (else_s) n->kids.push_back(else_s);
return n;
}
ASTNode* new_switch_stmt(ASTNode* expr, ASTNode* body, SourceLoc loc) {
auto* n = make(ASTTag::SWITCH_STMT);
n->kids={expr,body};
n->loc = loc;
return n;
}
ASTNode* new_while_stmt(ASTNode* cond, ASTNode* body, SourceLoc loc) {
auto* n = make(ASTTag::WHILE_STMT);
n->kids={cond,body};
n->loc = loc;
return n;
}
ASTNode* new_do_while_stmt(ASTNode* body, ASTNode* cond, SourceLoc loc) {
auto* n = make(ASTTag::DO_WHILE_STMT);
n->kids={body,cond};
n->loc = loc;
return n;
}
ASTNode* new_for_stmt(ASTNode* init, ASTNode* cond, ASTNode* iter, ASTNode* body, SourceLoc loc)
{
auto* n = make(ASTTag::FOR_STMT);
n->kids = {init, cond};
n->loc = loc;
if (iter) n->kids.push_back(iter);
n->kids.push_back(body);
return n;
}
ASTNode* new_for_decl_stmt(ASTNode* decl, ASTNode* cond, ASTNode* iter, ASTNode* body, SourceLoc loc)
{
auto* n = make(ASTTag::FOR_DECL_STMT);
n->kids = {decl, cond};
n->loc = loc;
if (iter) n->kids.push_back(iter);
n->kids.push_back(body);
return n;
}
ASTNode* new_goto_stmt(const char* id, SourceLoc loc) {
auto* n = make(ASTTag::GOTO_STMT);
n->text=id;
n->loc = loc;
return n;
}
ASTNode* new_continue_stmt(SourceLoc loc) {
auto* n = make(ASTTag::CONTINUE_STMT);
n->loc = loc;
return n;
}
ASTNode* new_break_stmt(SourceLoc loc) {
auto* n = make(ASTTag::BREAK_STMT);
n->loc = loc;
return n;
}
ASTNode* new_return_stmt(ASTNode* expr, SourceLoc loc) {
auto* n = make(ASTTag::RETURN_STMT);
n->loc = loc;
if(expr)n->kids={expr};
return n;
}
/* ──────────────────────────
* 7. 翻译单元 / 顶层
* ──────────────────────────*/
ASTNode* new_translation_unit(ASTNode* prev, ASTNode* ext_decl, SourceLoc loc)
{
if (!prev) {
auto* n=make(ASTTag::TRANSL_UNIT);
n->kids={ext_decl};
n->loc = loc;
return n;
}
prev->kids.push_back(ext_decl);
return prev;
}
ASTNode* new_decl_stmt(ASTNode* declaration, SourceLoc loc)
{
auto* n = make(ASTTag::DECL_STMT);
n->loc=loc;
n->kids={declaration};
return n;
}
ASTNode* new_function_def(ASTNode* decl_spec, ASTNode* declarator,
ASTNode* decl_list, ASTNode* comp_stmt, SourceLoc loc)
{
auto* n = make(ASTTag::FUNCTION_DEF);
n->loc=loc;
n->kids = {decl_spec, declarator};
if (decl_list) n->kids.push_back(decl_list);
n->kids.push_back(comp_stmt);
return n;
}
ASTNode* new_declaration_list(ASTNode* decl, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::DECL_LIST,nullptr,decl);
n->loc=loc;
return n;
}
ASTNode* append_declaration_list(ASTNode* list, ASTNode* decl, SourceLoc loc) {
ASTNode* n = append_to_list(ASTTag::DECL_LIST,list,decl);
n->loc=loc;
return n;
}
/*───────── overload: enum ↔ node ─────────*/
ASTNode* new_spec_list(ASTNode* spec_node, SourceLoc loc)
{
ASTNode* n = append_to_list(ASTTag::SPEC_LIST, nullptr, spec_node);
n->loc=loc;
return n;
}
ASTNode* append_spec_list(ASTNode* list, ASTNode* spec_node, SourceLoc loc)
{
ASTNode* n = append_to_list(ASTTag::SPEC_LIST, list, spec_node);
n->loc=loc;
return n;
}
/* 设计化初始化: 追加 (designator = initializer) */
ASTNode* append_designated_init(ASTNode* list,
ASTNode* designator_list,
ASTNode* initializer, SourceLoc loc)
{
auto* di = new_designated_init(designator_list, initializer, loc);
return append_init_item(list, di, loc);
}
/* 若你用到了 specq_list同理加 overload */
ASTNode* new_specq_list(ASTNode* node, SourceLoc loc)
{
auto* n = append_to_list(ASTTag::SPECQ_LIST, nullptr, node);
n->loc=loc;
return n;
}
ASTNode* append_specq_list(ASTNode* list, ASTNode* node, SourceLoc loc)
{
ASTNode* n = append_to_list(ASTTag::SPECQ_LIST, list, node);
n->loc=loc;
return n;
}
/* ── spec_list overload (node) ───────────────────────────*/
// ASTNode* new_spec_list(ASTNode* spec_node) {
// return append_to_list(ASTTag::SPEC_LIST, nullptr, spec_node);
// }
// ASTNode* append_spec_list(ASTNode* list, ASTNode* spec_node) {
// return append_to_list(ASTTag::SPEC_LIST, list, spec_node);
// }
//
// /* ── specq_list overload (node) ─────────────────────────*/
// ASTNode* new_specq_list(ASTNode* node) {
// return append_to_list(ASTTag::SPECQ_LIST, nullptr, node);
// }
// ASTNode* append_specq_list(ASTNode* list, ASTNode* node) {
// return append_to_list(ASTTag::SPECQ_LIST, list, node);
// }
//
// /* ── 追加指定化初始化器 ───────────────────────────────*/
// ASTNode* append_designated_init(ASTNode* list,
// ASTNode* designator_list,
// ASTNode* initializer)
// {
// return append_init_item(list,
// new_designated_init(designator_list, initializer));
// }