#include "ast.h" #include // strtoll #include /* ────────────────────────── * 内部小工具 * ──────────────────────────*/ 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; } /*—— init‑declarator 列表 ——*/ 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)); } /*—— type‑name / 抽象声明符 ——*/ 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)); // }