stage1 实现06测试
This commit is contained in:
@@ -1,28 +1,30 @@
|
||||
/* spl_parser.c — Top-level parser: function declarations, type declarations, etc. */
|
||||
|
||||
#include "spl_comp.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static spl_tok_t *peek(spl_comp_t *ctx) {
|
||||
return &vec_at(ctx->toks, ctx->tok_idx);
|
||||
}
|
||||
static 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 *t = &vec_at(ctx->toks, ctx->tok_idx);
|
||||
if (t->type != TOK_EOF) ctx->tok_idx++;
|
||||
if (t->type != TOK_EOF)
|
||||
ctx->tok_idx++;
|
||||
return t;
|
||||
}
|
||||
|
||||
static int expect(spl_comp_t *ctx, spl_tok_type_t type) {
|
||||
if (peek(ctx)->type == type) { advance(ctx); return 1; }
|
||||
spl_comp_error(ctx, "expected '%s', got '%s'", spl_tok_type_name(type), spl_tok_type_name(peek(ctx)->type));
|
||||
if (peek(ctx)->type == type) {
|
||||
advance(ctx);
|
||||
return 1;
|
||||
}
|
||||
spl_comp_error(ctx, "expected '%s', got '%s'", spl_tok_type_name(type),
|
||||
spl_tok_type_name(peek(ctx)->type));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void skip_nl(spl_comp_t *ctx) {
|
||||
while (peek(ctx)->type == TOK_ENDLINE) advance(ctx);
|
||||
while (peek(ctx)->type == TOK_ENDLINE)
|
||||
advance(ctx);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
@@ -38,7 +40,8 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) {
|
||||
spl_tok_t *fname_tok = advance(ctx);
|
||||
char fn_name[256];
|
||||
usize fnl = fname_tok->len < 255 ? fname_tok->len : 255;
|
||||
memcpy(fn_name, fname_tok->lexeme, fnl); fn_name[fnl] = '\0';
|
||||
memcpy(fn_name, fname_tok->lexeme, fnl);
|
||||
fn_name[fnl] = '\0';
|
||||
|
||||
skip_nl(ctx);
|
||||
expect(ctx, TOK_L_PAREN);
|
||||
@@ -65,8 +68,15 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) {
|
||||
}
|
||||
nparams++;
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_COMMA) { advance(ctx); skip_nl(ctx); continue; }
|
||||
if (peek(ctx)->type == TOK_ELLIPSIS) { advance(ctx); skip_nl(ctx); }
|
||||
if (peek(ctx)->type == TOK_COMMA) {
|
||||
advance(ctx);
|
||||
skip_nl(ctx);
|
||||
continue;
|
||||
}
|
||||
if (peek(ctx)->type == TOK_ELLIPSIS) {
|
||||
advance(ctx);
|
||||
skip_nl(ctx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -77,7 +87,8 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) {
|
||||
spl_type_info_t *ret_type = spl_type_basic(SPL_VOID);
|
||||
if (peek(ctx)->type != TOK_SEMICOLON && peek(ctx)->type != TOK_L_BRACE) {
|
||||
ret_type = spl_parse_type(ctx);
|
||||
if (!ret_type) ret_type = spl_type_basic(SPL_VOID);
|
||||
if (!ret_type)
|
||||
ret_type = spl_type_basic(SPL_VOID);
|
||||
skip_nl(ctx);
|
||||
}
|
||||
|
||||
@@ -88,7 +99,8 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) {
|
||||
int found = -1;
|
||||
vec_for(ctx->prog.natives, ni) {
|
||||
if (strcmp(vec_at(ctx->prog.natives, ni).name, fn_name) == 0) {
|
||||
found = (int)ni; break;
|
||||
found = (int)ni;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found < 0) {
|
||||
@@ -99,7 +111,8 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) {
|
||||
nat.impl_fn = NULL; /* resolved by VM at runtime */
|
||||
vec_push(ctx->prog.natives, nat);
|
||||
}
|
||||
if (peek(ctx)->type == TOK_SEMICOLON) advance(ctx);
|
||||
if (peek(ctx)->type == TOK_SEMICOLON)
|
||||
advance(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -170,7 +183,8 @@ void parse_type_decl(spl_comp_t *ctx) {
|
||||
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';
|
||||
memcpy(tname, name_tok->lexeme, tnl);
|
||||
tname[tnl] = '\0';
|
||||
|
||||
skip_nl(ctx);
|
||||
expect(ctx, TOK_ASSIGN);
|
||||
@@ -192,13 +206,18 @@ void parse_type_decl(spl_comp_t *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';
|
||||
memcpy(fname, ftok->lexeme, fnl);
|
||||
fname[fnl] = '\0';
|
||||
spl_type_add_field(st, fname, ftype);
|
||||
}
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_COMMA) { advance(ctx); skip_nl(ctx); }
|
||||
if (peek(ctx)->type == TOK_COMMA) {
|
||||
advance(ctx);
|
||||
skip_nl(ctx);
|
||||
}
|
||||
}
|
||||
if (peek(ctx)->type == TOK_R_BRACE) advance(ctx);
|
||||
if (peek(ctx)->type == TOK_R_BRACE)
|
||||
advance(ctx);
|
||||
}
|
||||
spl_type_compute_layout(st);
|
||||
map_put(ctx->type_defs, strdup(tname), st);
|
||||
@@ -218,22 +237,29 @@ void parse_type_decl(spl_comp_t *ctx) {
|
||||
spl_type_info_t *dtype = spl_parse_type(ctx);
|
||||
char vname[256];
|
||||
usize vnl = vtok->len < 255 ? vtok->len : 255;
|
||||
memcpy(vname, vtok->lexeme, vnl); vname[vnl] = '\0';
|
||||
memcpy(vname, vtok->lexeme, vnl);
|
||||
vname[vnl] = '\0';
|
||||
spl_type_add_variant(et, vname, dtype);
|
||||
} else {
|
||||
char vname[256];
|
||||
usize vnl = vtok->len < 255 ? vtok->len : 255;
|
||||
memcpy(vname, vtok->lexeme, vnl); vname[vnl] = '\0';
|
||||
memcpy(vname, vtok->lexeme, vnl);
|
||||
vname[vnl] = '\0';
|
||||
spl_type_add_variant(et, vname, NULL);
|
||||
}
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_COMMA) { advance(ctx); skip_nl(ctx); }
|
||||
if (peek(ctx)->type == TOK_COMMA) {
|
||||
advance(ctx);
|
||||
skip_nl(ctx);
|
||||
}
|
||||
}
|
||||
if (peek(ctx)->type == TOK_R_BRACE) advance(ctx);
|
||||
if (peek(ctx)->type == TOK_R_BRACE)
|
||||
advance(ctx);
|
||||
}
|
||||
spl_type_compute_layout(et);
|
||||
map_put(ctx->type_defs, strdup(tname), et);
|
||||
} else if (peek(ctx)->type == TOK_IDENT || (peek(ctx)->type >= KW_AS && peek(ctx)->type <= KW_ANY)) {
|
||||
} 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);
|
||||
if (base) {
|
||||
spl_type_info_t *alias = spl_type_clone(base);
|
||||
@@ -244,7 +270,8 @@ void parse_type_decl(spl_comp_t *ctx) {
|
||||
}
|
||||
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_SEMICOLON) advance(ctx);
|
||||
if (peek(ctx)->type == TOK_SEMICOLON)
|
||||
advance(ctx);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
@@ -254,7 +281,8 @@ void parse_type_decl(spl_comp_t *ctx) {
|
||||
void spl_parse_prog(spl_comp_t *ctx) {
|
||||
while (peek(ctx)->type != TOK_EOF) {
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_EOF) break;
|
||||
if (peek(ctx)->type == TOK_EOF)
|
||||
break;
|
||||
|
||||
switch (peek(ctx)->type) {
|
||||
case KW_FN:
|
||||
@@ -266,8 +294,10 @@ void spl_parse_prog(spl_comp_t *ctx) {
|
||||
case KW_PUB: {
|
||||
advance(ctx); /* skip pub */
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == KW_FN) parse_fn_decl(ctx, 0, 1);
|
||||
else if (peek(ctx)->type == KW_TYPE) parse_type_decl(ctx);
|
||||
if (peek(ctx)->type == KW_FN)
|
||||
parse_fn_decl(ctx, 0, 1);
|
||||
else if (peek(ctx)->type == KW_TYPE)
|
||||
parse_type_decl(ctx);
|
||||
break;
|
||||
}
|
||||
case TOK_SHARP:
|
||||
@@ -275,18 +305,22 @@ void spl_parse_prog(spl_comp_t *ctx) {
|
||||
advance(ctx); /* # */
|
||||
if (peek(ctx)->type == TOK_L_BRACKET) {
|
||||
advance(ctx); /* [ */
|
||||
while (peek(ctx)->type != TOK_R_BRACKET && peek(ctx)->type != TOK_EOF) advance(ctx);
|
||||
if (peek(ctx)->type == TOK_R_BRACKET) advance(ctx);
|
||||
while (peek(ctx)->type != TOK_R_BRACKET && peek(ctx)->type != TOK_EOF)
|
||||
advance(ctx);
|
||||
if (peek(ctx)->type == TOK_R_BRACKET)
|
||||
advance(ctx);
|
||||
}
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == KW_FN) parse_fn_decl(ctx, 1, 0);
|
||||
if (peek(ctx)->type == KW_FN)
|
||||
parse_fn_decl(ctx, 1, 0);
|
||||
break;
|
||||
default: {
|
||||
int prev = ctx->tok_idx;
|
||||
/* Try to parse as a statement */
|
||||
spl_parse_stmt(ctx);
|
||||
/* Safety: prevent infinite loop on unrecognized tokens */
|
||||
if (ctx->tok_idx == prev) advance(ctx);
|
||||
if (ctx->tok_idx == prev)
|
||||
advance(ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user