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:
+35
-2
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user