feat: 枚举关联数据 ADT — enum Option { Some(i64), None }
This commit is contained in:
+32
-5
@@ -187,15 +187,21 @@ static AstNode* parse_struct_init(Parser* p, const Token* name, ErrorInfo* error
|
||||
static AstNode* parse_ident_or_call(Parser* p, ErrorInfo* error) {
|
||||
const Token* name = advance(p);
|
||||
|
||||
// 枚举变体引用: Name::Variant
|
||||
// 枚举变体引用: Name::Variant 或 Name::Variant(payload)
|
||||
if (peek(p)->kind == TOK_COLON_COLON) {
|
||||
advance(p); // 跳过 ::
|
||||
const Token* variant = expect(p, TOK_IDENT, error, "枚举变体名");
|
||||
if (!variant) return NULL;
|
||||
AstNode* payload = NULL;
|
||||
if (match(p, TOK_LPAREN)) {
|
||||
payload = parse_expr(p, error);
|
||||
if (!payload) return NULL;
|
||||
if (!expect(p, TOK_RPAREN, error, "缺少 ')'")) return NULL;
|
||||
}
|
||||
return ast_make_enum_variant(p->arena,
|
||||
arena_strdup_impl(p->arena, name->start, name->length),
|
||||
arena_strdup_impl(p->arena, variant->start, variant->length),
|
||||
tok_loc(name));
|
||||
payload, tok_loc(name));
|
||||
}
|
||||
|
||||
// 结构体初始化: Name { field: val, ... }
|
||||
@@ -898,18 +904,39 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
|
||||
const Token* name = expect(&p, TOK_IDENT, error, "enum 后应为枚举名");
|
||||
if (!name) return NULL;
|
||||
if (!expect(&p, TOK_LBRACE, error, "缺少 '{'")) return NULL;
|
||||
const char* variants[64]; int vcount = 0;
|
||||
const char* variants[64];
|
||||
TypeKind payload_types[64];
|
||||
const char* payload_snames[64];
|
||||
int vcount = 0;
|
||||
while (peek(&p)->kind != TOK_RBRACE && !error->message) {
|
||||
if (vcount >= 64) { error->message = "枚举变体过多(最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
||||
const Token* vname = expect(&p, TOK_IDENT, error, "变体名");
|
||||
if (!vname) return NULL;
|
||||
variants[vcount++] = arena_strdup_impl(p.arena, vname->start, vname->length);
|
||||
variants[vcount] = arena_strdup_impl(p.arena, vname->start, vname->length);
|
||||
payload_types[vcount] = TYPE_VOID;
|
||||
payload_snames[vcount] = NULL;
|
||||
// 可选 payload: Variant(Type)
|
||||
if (peek(&p)->kind == TOK_LPAREN) {
|
||||
advance(&p);
|
||||
TypeInfo pti = parse_type_expr(&p, error);
|
||||
if (pti.kind == TYPE_ERROR) return NULL;
|
||||
payload_types[vcount] = pti.kind;
|
||||
payload_snames[vcount] = pti.struct_name;
|
||||
if (!expect(&p, TOK_RPAREN, error, "缺少 ')'")) return NULL;
|
||||
}
|
||||
vcount++;
|
||||
if (peek(&p)->kind == TOK_COMMA) advance(&p); else break;
|
||||
}
|
||||
if (!expect(&p, TOK_RBRACE, error, "缺少 '}'")) return NULL;
|
||||
const char** v_arr = arena_alloc_impl(p.arena, vcount * sizeof(const char*));
|
||||
memcpy(v_arr, variants, vcount * sizeof(const char*));
|
||||
AstNode* enum_decl = ast_make_enum_decl(p.arena, arena_strdup_impl(p.arena, name->start, name->length), v_arr, vcount, tok_loc(name));
|
||||
TypeKind* pt_arr = arena_alloc_impl(p.arena, vcount * sizeof(TypeKind));
|
||||
memcpy(pt_arr, payload_types, vcount * sizeof(TypeKind));
|
||||
const char** ps_arr = arena_alloc_impl(p.arena, vcount * sizeof(const char*));
|
||||
memcpy(ps_arr, payload_snames, vcount * sizeof(const char*));
|
||||
AstNode* enum_decl = ast_make_enum_decl(p.arena,
|
||||
arena_strdup_impl(p.arena, name->start, name->length),
|
||||
v_arr, pt_arr, ps_arr, vcount, tok_loc(name));
|
||||
if (enum_count >= 64) { error->message = "枚举过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
||||
enums[enum_count++] = enum_decl;
|
||||
} else if (peek(&p)->kind == TOK_EXTEND) {
|
||||
|
||||
Reference in New Issue
Block a user