stage1 整理代码 提供更多错误信息
This commit is contained in:
@@ -67,10 +67,17 @@ void spl_comp_reset(spl_comp_t *ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void spl_comp_error(spl_comp_t *ctx, const char *fmt, ...) {
|
void spl_comp_error(spl_comp_t *ctx, const char *fmt, ...) {
|
||||||
|
const char *loc = spl_tok_loc_str(ctx);
|
||||||
|
int loc_len = (int)strlen(loc);
|
||||||
|
memcpy(ctx->error_msg, loc, loc_len);
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vsnprintf(ctx->error_msg, COMP_ERROR_MAX - 1, fmt, args);
|
int n = vsnprintf(ctx->error_msg + loc_len, COMP_ERROR_MAX - loc_len - 1, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
if (n >= 0 && loc_len + n < COMP_ERROR_MAX - 2) {
|
||||||
|
ctx->error_msg[loc_len + n] = '\n';
|
||||||
|
ctx->error_msg[loc_len + n + 1] = '\0';
|
||||||
|
}
|
||||||
ctx->has_error = 1;
|
ctx->has_error = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,53 +216,7 @@ int spl_add_global_data(spl_comp_t *ctx, void *data, usize size) {
|
|||||||
return spl_prog_add_data(&ctx->prog, data, size);
|
return spl_prog_add_data(&ctx->prog, data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- Defer ---- */
|
|
||||||
|
|
||||||
void spl_emit_defer(spl_comp_t *ctx) {
|
|
||||||
if (ctx->defer_count >= DEFER_MAX)
|
|
||||||
return;
|
|
||||||
|
|
||||||
spl_val_t jmp_skip = emit_jmp_here(&ctx->emit);
|
|
||||||
|
|
||||||
spl_defer_entry_t *e = &ctx->defer_stack[ctx->defer_count];
|
|
||||||
e->body_start = jmp_skip + 1;
|
|
||||||
e->jmp_exit = 0;
|
|
||||||
e->depth = ctx->scope_depth;
|
|
||||||
e->count_at_decl = ctx->defer_count;
|
|
||||||
ctx->defer_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spl_emit_defer_epilogue(spl_comp_t *ctx, int depth) {
|
|
||||||
for (int i = 0; i < ctx->defer_count; i++) {
|
|
||||||
if (ctx->defer_stack[i].depth != depth)
|
|
||||||
continue;
|
|
||||||
spl_defer_entry_t *e = &ctx->defer_stack[i];
|
|
||||||
|
|
||||||
spl_val_t skip_addr = e->body_start - 1;
|
|
||||||
spl_val_t skip_target = e->jmp_exit + 1;
|
|
||||||
emit_patch(&ctx->emit, skip_addr, skip_target - skip_addr - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = ctx->defer_count - 1; i >= 0; i--) {
|
|
||||||
if (ctx->defer_stack[i].depth != depth)
|
|
||||||
continue;
|
|
||||||
spl_defer_entry_t *e = &ctx->defer_stack[i];
|
|
||||||
|
|
||||||
spl_val_t here = vec_size(ctx->prog.insns);
|
|
||||||
spl_val_t jmp_offset = (spl_val_t)((isize)e->body_start - (isize)here - 1);
|
|
||||||
emit_jmp(&ctx->emit, jmp_offset);
|
|
||||||
|
|
||||||
if (e->jmp_exit > 0)
|
|
||||||
emit_patch(&ctx->emit, e->jmp_exit, here + 1 - e->jmp_exit - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int new_count = 0;
|
|
||||||
for (int i = 0; i < ctx->defer_count; i++) {
|
|
||||||
if (ctx->defer_stack[i].depth != depth)
|
|
||||||
ctx->defer_stack[new_count++] = ctx->defer_stack[i];
|
|
||||||
}
|
|
||||||
ctx->defer_count = new_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Register runtime natives ---- */
|
/* ---- Register runtime natives ---- */
|
||||||
|
|
||||||
|
|||||||
@@ -196,9 +196,6 @@ int spl_add_global_data(spl_comp_t *ctx, void *data, usize size);
|
|||||||
void spl_push_scope(spl_comp_t *ctx);
|
void spl_push_scope(spl_comp_t *ctx);
|
||||||
void spl_pop_scope(spl_comp_t *ctx);
|
void spl_pop_scope(spl_comp_t *ctx);
|
||||||
|
|
||||||
/* Defer */
|
|
||||||
void spl_emit_defer(spl_comp_t *ctx);
|
|
||||||
void spl_emit_defer_epilogue(spl_comp_t *ctx, int depth);
|
|
||||||
|
|
||||||
/* Register runtime natives (stub) */
|
/* Register runtime natives (stub) */
|
||||||
void spl_comp_register(spl_prog_t *prog);
|
void spl_comp_register(spl_prog_t *prog);
|
||||||
|
|||||||
@@ -231,3 +231,49 @@ void spl_emit_store_init(spl_comp_t *ctx, int var_offset, int var_type_idx) {
|
|||||||
emit_store_to_laddr(&ctx->emit, var_offset, bt);
|
emit_store_to_laddr(&ctx->emit, var_offset, bt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void spl_emit_defer(spl_comp_t *ctx) {
|
||||||
|
if (ctx->defer_count >= DEFER_MAX)
|
||||||
|
return;
|
||||||
|
|
||||||
|
spl_val_t jmp_skip = emit_jmp_here(&ctx->emit);
|
||||||
|
|
||||||
|
spl_defer_entry_t *e = &ctx->defer_stack[ctx->defer_count];
|
||||||
|
e->body_start = jmp_skip + 1;
|
||||||
|
e->jmp_exit = 0;
|
||||||
|
e->depth = ctx->scope_depth;
|
||||||
|
e->count_at_decl = ctx->defer_count;
|
||||||
|
ctx->defer_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spl_emit_defer_epilogue(spl_comp_t *ctx, int depth) {
|
||||||
|
for (int i = 0; i < ctx->defer_count; i++) {
|
||||||
|
if (ctx->defer_stack[i].depth != depth)
|
||||||
|
continue;
|
||||||
|
spl_defer_entry_t *e = &ctx->defer_stack[i];
|
||||||
|
|
||||||
|
spl_val_t skip_addr = e->body_start - 1;
|
||||||
|
spl_val_t skip_target = e->jmp_exit + 1;
|
||||||
|
emit_patch(&ctx->emit, skip_addr, skip_target - skip_addr - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = ctx->defer_count - 1; i >= 0; i--) {
|
||||||
|
if (ctx->defer_stack[i].depth != depth)
|
||||||
|
continue;
|
||||||
|
spl_defer_entry_t *e = &ctx->defer_stack[i];
|
||||||
|
|
||||||
|
spl_val_t here = vec_size(ctx->prog.insns);
|
||||||
|
spl_val_t jmp_offset = (spl_val_t)((isize)e->body_start - (isize)here - 1);
|
||||||
|
emit_jmp(&ctx->emit, jmp_offset);
|
||||||
|
|
||||||
|
if (e->jmp_exit > 0)
|
||||||
|
emit_patch(&ctx->emit, e->jmp_exit, here + 1 - e->jmp_exit - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_count = 0;
|
||||||
|
for (int i = 0; i < ctx->defer_count; i++) {
|
||||||
|
if (ctx->defer_stack[i].depth != depth)
|
||||||
|
ctx->defer_stack[new_count++] = ctx->defer_stack[i];
|
||||||
|
}
|
||||||
|
ctx->defer_count = new_count;
|
||||||
|
}
|
||||||
|
|||||||
@@ -149,5 +149,7 @@ void emit_patch_call_fixups(spl_emit_t *e, spl_prog_t *prog);
|
|||||||
struct spl_comp;
|
struct spl_comp;
|
||||||
void spl_emit_ret(struct spl_comp *ctx, int ret_type_idx);
|
void spl_emit_ret(struct spl_comp *ctx, int ret_type_idx);
|
||||||
void spl_emit_store_init(struct spl_comp *ctx, int var_offset, int var_type_idx);
|
void spl_emit_store_init(struct spl_comp *ctx, int var_offset, int var_type_idx);
|
||||||
|
void spl_emit_defer(struct spl_comp *ctx);
|
||||||
|
void spl_emit_defer_epilogue(struct spl_comp *ctx, int depth);
|
||||||
|
|
||||||
#endif /* __SPL_EMIT_H__ */
|
#endif /* __SPL_EMIT_H__ */
|
||||||
|
|||||||
@@ -618,9 +618,9 @@ static void spl_check_arg_type(spl_comp_t *ctx, const char *fname, int arg_type_
|
|||||||
strcmp(spl_type_name(&ctx->tctx, arg_type_idx),
|
strcmp(spl_type_name(&ctx->tctx, arg_type_idx),
|
||||||
spl_type_name(&ctx->tctx, spl_type_elem_type(&ctx->tctx, param_type_idx))) == 0) {
|
spl_type_name(&ctx->tctx, spl_type_elem_type(&ctx->tctx, param_type_idx))) == 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: warning: argument %d of '%s' expects '%s*', "
|
"%s warning: argument %d of '%s' expects '%s*', "
|
||||||
"got '%s' (missing '&'?)\n",
|
"got '%s' (missing '&'?)\n",
|
||||||
ctx->fname, arg_idx + 1, fname,
|
spl_tok_loc_str(ctx), arg_idx + 1, fname,
|
||||||
spl_type_name(&ctx->tctx, spl_type_elem_type(&ctx->tctx, param_type_idx)),
|
spl_type_name(&ctx->tctx, spl_type_elem_type(&ctx->tctx, param_type_idx)),
|
||||||
spl_type_name(&ctx->tctx, arg_type_idx));
|
spl_type_name(&ctx->tctx, arg_type_idx));
|
||||||
}
|
}
|
||||||
@@ -781,6 +781,7 @@ static spl_expr_result_t parse_prefix_op(spl_comp_t *ctx) {
|
|||||||
if (!right.is_lvalue) {
|
if (!right.is_lvalue) {
|
||||||
spl_comp_error(ctx, "cannot take address of rvalue");
|
spl_comp_error(ctx, "cannot take address of rvalue");
|
||||||
}
|
}
|
||||||
|
right.type_idx = spl_type_ptr(&ctx->tctx, right.type_idx);
|
||||||
break;
|
break;
|
||||||
case TOK_MUL:
|
case TOK_MUL:
|
||||||
if (right.type_idx >= 0 && spl_type_kind(&ctx->tctx, right.type_idx) == TYPE_PTR &&
|
if (right.type_idx >= 0 && spl_type_kind(&ctx->tctx, right.type_idx) == TYPE_PTR &&
|
||||||
@@ -871,6 +872,18 @@ static spl_expr_result_t parse_primary_expr(spl_comp_t *ctx) {
|
|||||||
emit_dbg_void(&ctx->emit);
|
emit_dbg_void(&ctx->emit);
|
||||||
}
|
}
|
||||||
return (spl_expr_result_t){spl_type_basic(&ctx->tctx, SPL_VOID), 0};
|
return (spl_expr_result_t){spl_type_basic(&ctx->tctx, SPL_VOID), 0};
|
||||||
|
} else if (strcmp(bname, "sizeof") == 0) {
|
||||||
|
expect(ctx, TOK_L_PAREN);
|
||||||
|
int ti = spl_type_parse(&ctx->tctx, ctx);
|
||||||
|
expect(ctx, TOK_R_PAREN);
|
||||||
|
if (ti < 0) {
|
||||||
|
spl_comp_error(ctx, "@sizeof: invalid type");
|
||||||
|
spl_expr_result_t r = { -1, 0 };
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
usize sz = spl_type_size(&ctx->tctx, ti);
|
||||||
|
emit_push_usize(&ctx->emit, sz);
|
||||||
|
return (spl_expr_result_t){spl_type_basic(&ctx->tctx, SPL_USIZE), 0};
|
||||||
} else {
|
} else {
|
||||||
spl_comp_error(ctx, "unknown builtin '@%s'", bname);
|
spl_comp_error(ctx, "unknown builtin '@%s'", bname);
|
||||||
spl_expr_result_t r = {-1, 0};
|
spl_expr_result_t r = {-1, 0};
|
||||||
@@ -935,7 +948,8 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
|
|||||||
int nargs = 0;
|
int nargs = 0;
|
||||||
|
|
||||||
int is_instance = 0;
|
int is_instance = 0;
|
||||||
if (func->nparams > 0 && func->param_type_indices[0] >= 0 &&
|
if (func->nparams > 0 && func->param_type_indices &&
|
||||||
|
func->param_type_indices[0] >= 0 &&
|
||||||
spl_type_kind(&ctx->tctx, func->param_type_indices[0]) == TYPE_PTR &&
|
spl_type_kind(&ctx->tctx, func->param_type_indices[0]) == TYPE_PTR &&
|
||||||
spl_type_elem_type(&ctx->tctx, func->param_type_indices[0]) ==
|
spl_type_elem_type(&ctx->tctx, func->param_type_indices[0]) ==
|
||||||
methods_type_idx) {
|
methods_type_idx) {
|
||||||
@@ -954,10 +968,6 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
|
|||||||
{
|
{
|
||||||
int *cp = func->param_type_indices;
|
int *cp = func->param_type_indices;
|
||||||
int cn = func->nparams;
|
int cn = func->nparams;
|
||||||
if (is_instance && cn > 0) {
|
|
||||||
cp++;
|
|
||||||
cn--;
|
|
||||||
}
|
|
||||||
nargs += parse_call_args_checked(ctx, func->name, cp, cn);
|
nargs += parse_call_args_checked(ctx, func->name, cp, cn);
|
||||||
}
|
}
|
||||||
expect(ctx, TOK_R_PAREN);
|
expect(ctx, TOK_R_PAREN);
|
||||||
|
|||||||
@@ -122,3 +122,11 @@ usize spl_tok_copy_name(spl_tok_t *tok, char *buf, usize buf_size) {
|
|||||||
buf[nlen] = '\0';
|
buf[nlen] = '\0';
|
||||||
return nlen;
|
return nlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *spl_tok_loc_str(spl_comp_t *ctx) {
|
||||||
|
static char buf[256];
|
||||||
|
spl_tok_t *tok = peek(ctx);
|
||||||
|
snprintf(buf, sizeof(buf), "%s:%zu:%zu: ", tok->fname ? tok->fname : "?", tok->line,
|
||||||
|
tok->col);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ void spl_tok_dump(spl_tok_t *tok);
|
|||||||
void spl_tok_vec_dump(spl_tok_vec_t *toks);
|
void spl_tok_vec_dump(spl_tok_vec_t *toks);
|
||||||
void spl_tok_vec_drop(spl_tok_vec_t *toks);
|
void spl_tok_vec_drop(spl_tok_vec_t *toks);
|
||||||
usize spl_tok_copy_name(spl_tok_t *tok, char *buf, usize buf_size);
|
usize spl_tok_copy_name(spl_tok_t *tok, char *buf, usize buf_size);
|
||||||
|
const char *spl_tok_loc_str(spl_comp_t *ctx);
|
||||||
|
|
||||||
/* Parse an integer literal value, handling optional '-' prefix for negatives.
|
/* Parse an integer literal value, handling optional '-' prefix for negatives.
|
||||||
* Returns 1 on success (value in *val), 0 if current token isn't an integer.
|
* Returns 1 on success (value in *val), 0 if current token isn't an integer.
|
||||||
|
|||||||
@@ -46,6 +46,17 @@ static int parse_params_decl(spl_comp_t *ctx, char pnames[][256], int ptypes[])
|
|||||||
static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, int ret_type_idx, int nparams,
|
static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, int ret_type_idx, int nparams,
|
||||||
char pnames[][256], int ptypes[], int is_pub) {
|
char pnames[][256], int ptypes[], int is_pub) {
|
||||||
int fi = spl_declare_func(ctx, fn_name, ret_type_idx, nparams, 0, is_pub);
|
int fi = spl_declare_func(ctx, fn_name, ret_type_idx, nparams, 0, is_pub);
|
||||||
|
|
||||||
|
{
|
||||||
|
spl_func_info_t *f = &vec_at(ctx->funcs, fi);
|
||||||
|
f->param_type_indices = calloc(nparams, sizeof(int));
|
||||||
|
f->param_names = calloc(nparams, sizeof(char *));
|
||||||
|
for (int i = 0; i < nparams; i++) {
|
||||||
|
f->param_type_indices[i] = ptypes[i];
|
||||||
|
f->param_names[i] = strdup(pnames[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctx->current_func_idx = fi;
|
ctx->current_func_idx = fi;
|
||||||
ctx->current_ret_type_idx = ret_type_idx;
|
ctx->current_ret_type_idx = ret_type_idx;
|
||||||
fa_init(&ctx->emit.frame);
|
fa_init(&ctx->emit.frame);
|
||||||
@@ -87,16 +98,6 @@ static int parse_fn_body(spl_comp_t *ctx, const char *fn_name, int ret_type_idx,
|
|||||||
spl_emit_defer_epilogue(ctx, ctx->scope_depth);
|
spl_emit_defer_epilogue(ctx, ctx->scope_depth);
|
||||||
spl_pop_scope(ctx);
|
spl_pop_scope(ctx);
|
||||||
|
|
||||||
{
|
|
||||||
spl_func_info_t *f = &vec_at(ctx->funcs, fi);
|
|
||||||
f->param_type_indices = calloc(nparams, sizeof(int));
|
|
||||||
f->param_names = calloc(nparams, sizeof(char *));
|
|
||||||
for (int i = 0; i < nparams; i++) {
|
|
||||||
f->param_type_indices[i] = ptypes[i];
|
|
||||||
f->param_names[i] = strdup(pnames[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit_return(&ctx->emit, &ctx->tctx, ctx->current_ret_type_idx);
|
emit_return(&ctx->emit, &ctx->tctx, ctx->current_ret_type_idx);
|
||||||
spl_prog_end_func(&ctx->prog, fi);
|
spl_prog_end_func(&ctx->prog, fi);
|
||||||
ctx->current_func_idx = -1;
|
ctx->current_func_idx = -1;
|
||||||
@@ -207,10 +208,13 @@ static void skip_type_decl(spl_comp_t *ctx) {
|
|||||||
int bd = 1;
|
int bd = 1;
|
||||||
advance(ctx);
|
advance(ctx);
|
||||||
while (bd > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
|
while (bd > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
|
||||||
if (peek(ctx)->type == TOK_L_BRACE)
|
spl_tok_type_t tt = peek(ctx)->type;
|
||||||
|
if (tt == TOK_L_BRACE)
|
||||||
bd++;
|
bd++;
|
||||||
else if (peek(ctx)->type == TOK_R_BRACE)
|
else if (tt == TOK_R_BRACE)
|
||||||
bd--;
|
bd--;
|
||||||
|
else if (tt == TOK_EOF)
|
||||||
|
break;
|
||||||
advance(ctx);
|
advance(ctx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -247,6 +251,8 @@ static void parse_type_body(spl_comp_t *ctx, int container_type_idx, int is_enum
|
|||||||
advance(ctx);
|
advance(ctx);
|
||||||
} else if (tt == KW_TYPE && depth == 1) {
|
} else if (tt == KW_TYPE && depth == 1) {
|
||||||
parse_type_decl(ctx);
|
parse_type_decl(ctx);
|
||||||
|
} else if (tt == TOK_EOF) {
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
advance(ctx);
|
advance(ctx);
|
||||||
}
|
}
|
||||||
@@ -276,10 +282,34 @@ static void parse_type_body(spl_comp_t *ctx, int container_type_idx, int is_enum
|
|||||||
spl_tok_t *name_tok = advance(ctx);
|
spl_tok_t *name_tok = advance(ctx);
|
||||||
char mname[256];
|
char mname[256];
|
||||||
spl_tok_copy_name(name_tok, mname, sizeof(mname));
|
spl_tok_copy_name(name_tok, mname, sizeof(mname));
|
||||||
|
|
||||||
|
/* Count parameters for forward reference */
|
||||||
|
int pcount = 0;
|
||||||
|
if (peek(ctx)->type == TOK_L_PAREN) {
|
||||||
|
advance(ctx); /* ( */
|
||||||
|
skip_nl(ctx);
|
||||||
|
if (peek(ctx)->type != TOK_R_PAREN) {
|
||||||
|
pcount = 1;
|
||||||
|
for (;;) {
|
||||||
|
advance(ctx); /* skip param name or type token */
|
||||||
|
skip_nl(ctx);
|
||||||
|
if (peek(ctx)->type == TOK_R_PAREN) break;
|
||||||
|
if (peek(ctx)->type == TOK_COMMA) {
|
||||||
|
advance(ctx); /* , */
|
||||||
|
skip_nl(ctx);
|
||||||
|
pcount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
advance(ctx); /* ) */
|
||||||
|
}
|
||||||
|
|
||||||
char qualified[512];
|
char qualified[512];
|
||||||
snprintf(qualified, sizeof(qualified), "%s.%s", cname, mname);
|
snprintf(qualified, sizeof(qualified), "%s.%s", cname, mname);
|
||||||
int fi = spl_declare_func(ctx, qualified, -1, 0, 0, 0);
|
int fi = spl_declare_func(ctx, qualified, -1, pcount, 0, 0);
|
||||||
spl_type_add_method(&ctx->tctx, container_type_idx, mname, fi);
|
spl_type_add_method(&ctx->tctx, container_type_idx, mname, fi);
|
||||||
|
} else if (tt == TOK_EOF) {
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
advance(ctx);
|
advance(ctx);
|
||||||
}
|
}
|
||||||
@@ -335,6 +365,8 @@ static void parse_type_body(spl_comp_t *ctx, int container_type_idx, int is_enum
|
|||||||
spl_tok_copy_name(vtok, vname, sizeof(vname));
|
spl_tok_copy_name(vtok, vname, sizeof(vname));
|
||||||
spl_type_add_variant(&ctx->tctx, container_type_idx, vname,
|
spl_type_add_variant(&ctx->tctx, container_type_idx, vname,
|
||||||
dtype >= 0 ? dtype : -1);
|
dtype >= 0 ? dtype : -1);
|
||||||
|
} else if (tt == TOK_EOF) {
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
char vname[256];
|
char vname[256];
|
||||||
spl_tok_copy_name(vtok, vname, sizeof(vname));
|
spl_tok_copy_name(vtok, vname, sizeof(vname));
|
||||||
@@ -480,7 +512,7 @@ void spl_parse_prog(spl_comp_t *ctx) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
int prev = ctx->tok_idx;
|
usize prev = ctx->tok_idx;
|
||||||
spl_parse_stmt(ctx);
|
spl_parse_stmt(ctx);
|
||||||
if (ctx->tok_idx == prev)
|
if (ctx->tok_idx == prev)
|
||||||
advance(ctx);
|
advance(ctx);
|
||||||
|
|||||||
Reference in New Issue
Block a user