feat: 枚举 enum (P1 #7)

- lexer: TOK_ENUM, TOK_COLON_COLON
- ast: AST_ENUM_DECL, AST_ENUM_VARIANT + AST_PROGRAM enums数组
- parser: enum Name { A, B } + Enum::Variant语法
- sema: SYM_ENUM, 变体验证, enum→i64类型兼容
- codegen: TYPE_ENUM→i64, 变体→ConstInt(索引值)
- 新增集成测试: 17_enum.l

测试: 121 通过 (41+15+47+18)
This commit is contained in:
2026-06-05 14:01:47 +08:00
parent ab88ea2753
commit 5237398245
14 changed files with 267 additions and 21 deletions
+35 -2
View File
@@ -144,6 +144,17 @@ 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
if (peek(p)->kind == TOK_COLON_COLON) {
advance(p); // 跳过 ::
const Token* variant = expect(p, TOK_IDENT, error, "枚举变体名");
if (!variant) 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));
}
// 结构体初始化: Name { field: val, ... }
// 用提前看来区别 struct init 和 block
// struct init → { IDENT COLON ... block → { 可能是 let/if/while/...
@@ -553,6 +564,7 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
AstNode* functions[256]; int fn_count = 0;
AstNode* structs[64]; int struct_count = 0;
AstNode* aliases[64]; int alias_count = 0;
AstNode* enums[64]; int enum_count = 0;
while (peek(&p)->kind != TOK_EOF && !error->message) {
if (peek(&p)->kind == TOK_STRUCT) {
if (struct_count >= 64) { error->message = "结构体过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
@@ -569,11 +581,30 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
aliases[alias_count++] = ast_make_type_alias(a,
arena_strdup_impl(a, alias_name->start, alias_name->length),
rti.kind, rti.struct_name, tok_loc(type_tok));
} else if (peek(&p)->kind == TOK_ENUM) {
advance(&p);
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;
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);
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));
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_FN) {
if (fn_count >= 256) { error->message = "函数过多 (最多256)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
functions[fn_count++] = parse_function(&p, error);
} else {
error->message = "顶层只允许 fn、struct 或 type";
error->message = "顶层只允许 fn、struct、type 或 enum";
error->filename = p.filename;
error->line = peek(&p)->line;
error->col = peek(&p)->col;
@@ -587,6 +618,8 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
memcpy(st_arr, structs, struct_count * sizeof(AstNode*));
AstNode** al_arr = arena_alloc_impl(a, alias_count * sizeof(AstNode*));
memcpy(al_arr, aliases, alias_count * sizeof(AstNode*));
AstNode** en_arr = arena_alloc_impl(a, enum_count * sizeof(AstNode*));
memcpy(en_arr, enums, enum_count * sizeof(AstNode*));
return ast_make_program(a, fn_arr, fn_count, st_arr, struct_count,
al_arr, alias_count, loc_at(0, 0));
al_arr, alias_count, en_arr, enum_count, loc_at(0, 0));
}