stage1 完成11-13测试
This commit is contained in:
@@ -3,9 +3,9 @@
|
||||
#include "spl_comp.h"
|
||||
#include <string.h>
|
||||
|
||||
static spl_tok_t *peek(spl_comp_t *ctx) { return &vec_at(ctx->toks, ctx->tok_idx); }
|
||||
spl_tok_t *peek(spl_comp_t *ctx) { return &vec_at(ctx->toks, ctx->tok_idx); }
|
||||
|
||||
static spl_tok_t *advance(spl_comp_t *ctx) {
|
||||
spl_tok_t *advance(spl_comp_t *ctx) {
|
||||
spl_tok_t *t = &vec_at(ctx->toks, ctx->tok_idx);
|
||||
if (t->type != TOK_EOF)
|
||||
ctx->tok_idx++;
|
||||
@@ -173,31 +173,55 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) {
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Parse type declaration
|
||||
* type Name = struct/enum { ... };
|
||||
* type Name = ExistingType;
|
||||
* Parse struct/union body (shared for struct and union containers)
|
||||
*
|
||||
* Body supports:
|
||||
* var name: type; — field declarations
|
||||
* name: type, — field declarations (old-style)
|
||||
* type Name = ...; — nested type declarations
|
||||
* fn name(...) type { } — methods (skipped)
|
||||
* ============================================================ */
|
||||
|
||||
void parse_type_decl(spl_comp_t *ctx) {
|
||||
advance(ctx); /* type */
|
||||
spl_tok_t *name_tok = advance(ctx);
|
||||
char tname[256];
|
||||
usize tnl = name_tok->len < 255 ? name_tok->len : 255;
|
||||
memcpy(tname, name_tok->lexeme, tnl);
|
||||
tname[tnl] = '\0';
|
||||
static void parse_struct_body(spl_comp_t *ctx, spl_type_info_t *st) {
|
||||
if (peek(ctx)->type != TOK_L_BRACE)
|
||||
return;
|
||||
advance(ctx); /* { */
|
||||
|
||||
skip_nl(ctx);
|
||||
expect(ctx, TOK_ASSIGN);
|
||||
skip_nl(ctx);
|
||||
/* === Pass 1: Parse all nested type declarations first ===
|
||||
* This allows field declarations to reference types defined later in the body. */
|
||||
{
|
||||
usize saved = ctx->tok_idx;
|
||||
int depth = 1;
|
||||
while (depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
|
||||
spl_tok_type_t tt = peek(ctx)->type;
|
||||
if (tt == TOK_L_BRACE) { depth++; advance(ctx); }
|
||||
else if (tt == TOK_R_BRACE) { depth--; if (depth == 0) break; advance(ctx); }
|
||||
else if (tt == KW_TYPE && depth == 1) {
|
||||
parse_type_decl(ctx);
|
||||
} else {
|
||||
advance(ctx);
|
||||
}
|
||||
}
|
||||
/* Reset to start of body for second pass */
|
||||
ctx->tok_idx = saved;
|
||||
}
|
||||
|
||||
if (peek(ctx)->type == KW_STRUCT) {
|
||||
advance(ctx);
|
||||
spl_type_info_t *st = spl_type_struct(tname);
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_L_BRACE) {
|
||||
advance(ctx); /* { */
|
||||
/* === Pass 2: Parse fields and methods === */
|
||||
{
|
||||
int depth = 1;
|
||||
while (depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
|
||||
skip_nl(ctx);
|
||||
while (peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
|
||||
spl_tok_type_t tt = peek(ctx)->type;
|
||||
if (tt == TOK_L_BRACE) { depth++; advance(ctx); }
|
||||
else if (tt == TOK_R_BRACE) { depth--; if (depth == 0) { advance(ctx); break; } advance(ctx); }
|
||||
else if (tt == KW_TYPE && depth == 1) {
|
||||
/* Nested type — already parsed in pass 1, skip by re-parsing */
|
||||
parse_type_decl(ctx);
|
||||
}
|
||||
else if (tt == KW_VAR && depth == 1) {
|
||||
/* var name: type; */
|
||||
advance(ctx); /* var */
|
||||
skip_nl(ctx);
|
||||
spl_tok_t *ftok = advance(ctx);
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_COLON) {
|
||||
@@ -211,24 +235,103 @@ void parse_type_decl(spl_comp_t *ctx) {
|
||||
spl_type_add_field(st, fname, ftype);
|
||||
}
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_COMMA) {
|
||||
if (peek(ctx)->type == TOK_SEMICOLON || peek(ctx)->type == TOK_COMMA)
|
||||
advance(ctx);
|
||||
}
|
||||
else if (tt == TOK_IDENT && depth == 1) {
|
||||
/* Old-style field: name: type, */
|
||||
spl_tok_t *ftok = advance(ctx);
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_COLON) {
|
||||
advance(ctx); /* : */
|
||||
skip_nl(ctx);
|
||||
spl_type_info_t *ftype = spl_parse_type(ctx);
|
||||
char fname[256];
|
||||
usize fnl = ftok->len < 255 ? ftok->len : 255;
|
||||
memcpy(fname, ftok->lexeme, fnl);
|
||||
fname[fnl] = '\0';
|
||||
spl_type_add_field(st, fname, ftype);
|
||||
}
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_SEMICOLON || peek(ctx)->type == TOK_COMMA)
|
||||
advance(ctx);
|
||||
}
|
||||
else if (tt == KW_FN && depth == 1) {
|
||||
/* Method — skip over fn name(params) rettype { body } */
|
||||
advance(ctx); /* fn */
|
||||
while (ctx->tok_idx < vec_size(ctx->toks)) {
|
||||
spl_tok_type_t mt = peek(ctx)->type;
|
||||
if (mt == TOK_SEMICOLON) { advance(ctx); break; }
|
||||
if (mt == TOK_L_BRACE) {
|
||||
/* Skip function body counting braces */
|
||||
advance(ctx);
|
||||
int bd = 1;
|
||||
while (bd > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
|
||||
if (peek(ctx)->type == TOK_L_BRACE) bd++;
|
||||
else if (peek(ctx)->type == TOK_R_BRACE) bd--;
|
||||
advance(ctx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
advance(ctx);
|
||||
}
|
||||
}
|
||||
if (peek(ctx)->type == TOK_R_BRACE)
|
||||
else {
|
||||
advance(ctx);
|
||||
}
|
||||
}
|
||||
spl_type_compute_layout(st);
|
||||
map_put(ctx->type_defs, strdup(tname), st);
|
||||
} else if (peek(ctx)->type == KW_ENUM) {
|
||||
advance(ctx);
|
||||
spl_type_info_t *et = spl_type_enum(tname);
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_L_BRACE) {
|
||||
advance(ctx); /* { */
|
||||
}
|
||||
|
||||
spl_type_compute_layout(st);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Parse enum body
|
||||
*
|
||||
* Body supports:
|
||||
* Name — simple variant
|
||||
* Name: Type — variant with data
|
||||
* var name: type; — field-style variant
|
||||
* type Name = ...; — nested type declarations
|
||||
* fn name(...) type { } — methods (skipped)
|
||||
* ============================================================ */
|
||||
|
||||
static void parse_enum_body(spl_comp_t *ctx, spl_type_info_t *et) {
|
||||
if (peek(ctx)->type != TOK_L_BRACE)
|
||||
return;
|
||||
advance(ctx); /* { */
|
||||
|
||||
/* === Pass 1: Parse all nested type declarations first === */
|
||||
{
|
||||
usize saved = ctx->tok_idx;
|
||||
int depth = 1;
|
||||
while (depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
|
||||
spl_tok_type_t tt = peek(ctx)->type;
|
||||
if (tt == TOK_L_BRACE) { depth++; advance(ctx); }
|
||||
else if (tt == TOK_R_BRACE) { depth--; if (depth == 0) break; advance(ctx); }
|
||||
else if (tt == KW_TYPE && depth == 1) {
|
||||
parse_type_decl(ctx);
|
||||
} else {
|
||||
advance(ctx);
|
||||
}
|
||||
}
|
||||
ctx->tok_idx = saved;
|
||||
}
|
||||
|
||||
/* === Pass 2: Parse variants and methods === */
|
||||
{
|
||||
int depth = 1;
|
||||
while (depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
|
||||
skip_nl(ctx);
|
||||
while (peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
|
||||
spl_tok_type_t tt = peek(ctx)->type;
|
||||
if (tt == TOK_L_BRACE) { depth++; advance(ctx); }
|
||||
else if (tt == TOK_R_BRACE) { depth--; if (depth == 0) { advance(ctx); break; } advance(ctx); }
|
||||
else if (tt == KW_TYPE && depth == 1) {
|
||||
/* Already parsed in pass 1, re-parse to skip */
|
||||
parse_type_decl(ctx);
|
||||
}
|
||||
else if (tt == TOK_IDENT && depth == 1) {
|
||||
/* Variant: Name or Name: Type */
|
||||
spl_tok_t *vtok = advance(ctx);
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_COLON) {
|
||||
@@ -248,16 +351,77 @@ void parse_type_decl(spl_comp_t *ctx) {
|
||||
spl_type_add_variant(et, vname, NULL);
|
||||
}
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_COMMA) {
|
||||
if (peek(ctx)->type == TOK_SEMICOLON || peek(ctx)->type == TOK_COMMA)
|
||||
advance(ctx);
|
||||
}
|
||||
else if (tt == KW_FN && depth == 1) {
|
||||
/* Method — skip */
|
||||
advance(ctx); /* fn */
|
||||
while (ctx->tok_idx < vec_size(ctx->toks)) {
|
||||
spl_tok_type_t mt = peek(ctx)->type;
|
||||
if (mt == TOK_SEMICOLON) { advance(ctx); break; }
|
||||
if (mt == TOK_L_BRACE) {
|
||||
advance(ctx);
|
||||
int bd = 1;
|
||||
while (bd > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
|
||||
if (peek(ctx)->type == TOK_L_BRACE) bd++;
|
||||
else if (peek(ctx)->type == TOK_R_BRACE) bd--;
|
||||
advance(ctx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
advance(ctx);
|
||||
skip_nl(ctx);
|
||||
}
|
||||
}
|
||||
if (peek(ctx)->type == TOK_R_BRACE)
|
||||
else {
|
||||
advance(ctx);
|
||||
}
|
||||
}
|
||||
spl_type_compute_layout(et);
|
||||
}
|
||||
|
||||
spl_type_compute_layout(et);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Parse type declaration
|
||||
* type Name = struct { ... };
|
||||
* type Name = union { ... };
|
||||
* type Name = enum { ... };
|
||||
* type Name = ExistingType;
|
||||
* ============================================================ */
|
||||
|
||||
void parse_type_decl(spl_comp_t *ctx) {
|
||||
advance(ctx); /* type */
|
||||
spl_tok_t *name_tok = advance(ctx);
|
||||
char tname[256];
|
||||
usize tnl = name_tok->len < 255 ? name_tok->len : 255;
|
||||
memcpy(tname, name_tok->lexeme, tnl);
|
||||
tname[tnl] = '\0';
|
||||
|
||||
skip_nl(ctx);
|
||||
expect(ctx, TOK_ASSIGN);
|
||||
skip_nl(ctx);
|
||||
|
||||
if (peek(ctx)->type == KW_STRUCT) {
|
||||
advance(ctx);
|
||||
spl_type_info_t *st = spl_type_struct(tname);
|
||||
/* Register type early to allow self-referential fields */
|
||||
map_put(ctx->type_defs, strdup(tname), st);
|
||||
skip_nl(ctx);
|
||||
parse_struct_body(ctx, st);
|
||||
} else if (peek(ctx)->type == KW_UNION) {
|
||||
advance(ctx);
|
||||
spl_type_info_t *ut = spl_type_union(tname);
|
||||
map_put(ctx->type_defs, strdup(tname), ut);
|
||||
skip_nl(ctx);
|
||||
parse_struct_body(ctx, ut);
|
||||
} else if (peek(ctx)->type == KW_ENUM) {
|
||||
advance(ctx);
|
||||
spl_type_info_t *et = spl_type_enum(tname);
|
||||
/* Register type early to allow self-referential variants */
|
||||
map_put(ctx->type_defs, strdup(tname), et);
|
||||
skip_nl(ctx);
|
||||
parse_enum_body(ctx, et);
|
||||
} else if (peek(ctx)->type == TOK_IDENT ||
|
||||
(peek(ctx)->type >= KW_AS && peek(ctx)->type <= KW_ANY)) {
|
||||
spl_type_info_t *base = spl_parse_type(ctx);
|
||||
|
||||
Reference in New Issue
Block a user