Files
l-language/src/parser/parser.c
T

1223 lines
56 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "parser.h"
#include "lexer.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
const Token* tokens;
size_t count;
size_t pos;
const char* filename;
Arena* arena;
} Parser;
// === 递归深度限制 ===
static int parse_depth = 0;
#define MAX_PARSE_DEPTH 1000
// === 向前看 ===
static const Token* peek(const Parser* p) { return &p->tokens[p->pos]; }
static const Token* advance(Parser* p) { return &p->tokens[p->pos++]; }
static bool match(Parser* p, TokenKind k) {
if (peek(p)->kind == k) { p->pos++; return true; }
return false;
}
static const Token* expect(Parser* p, TokenKind k, ErrorInfo* e, const char* msg) {
if (peek(p)->kind == k) return advance(p);
e->message = msg; e->filename = p->filename;
e->line = peek(p)->line; e->col = peek(p)->col;
return NULL;
}
// === 运算符优先级定义 ===
typedef enum {
PREC_NONE = 0,
PREC_PIPE = 10,
PREC_OR = 20,
PREC_AND = 30,
PREC_COMPARE = 40,
PREC_TERM = 50,
PREC_FACTOR = 60,
PREC_UNARY = 70,
PREC_POSTFIX = 80, // .field, call()
} Precedence;
static Precedence tok_to_prec(TokenKind kind) {
switch (kind) {
case TOK_PIPE_PIPE: return PREC_OR;
case TOK_AND_AND: return PREC_AND;
case TOK_EQ_EQ: case TOK_BANG_EQ:
case TOK_LT: case TOK_GT: case TOK_LT_EQ: case TOK_GT_EQ: return PREC_COMPARE;
case TOK_PLUS: case TOK_MINUS: return PREC_TERM;
case TOK_STAR: case TOK_SLASH: case TOK_PERCENT: return PREC_FACTOR;
default: return PREC_NONE;
}
}
static BinaryOp tok_to_binop(TokenKind kind) {
switch (kind) {
case TOK_PLUS: return OP_ADD; case TOK_MINUS: return OP_SUB;
case TOK_STAR: return OP_MUL; case TOK_SLASH: return OP_DIV;
case TOK_PERCENT: return OP_MOD;
case TOK_EQ_EQ: return OP_EQ; case TOK_BANG_EQ: return OP_NE;
case TOK_LT: return OP_LT; case TOK_GT: return OP_GT;
case TOK_LT_EQ: return OP_LE; case TOK_GT_EQ: return OP_GE;
case TOK_AND_AND: return OP_AND; case TOK_PIPE_PIPE: return OP_OR;
default: return OP_ADD;
}
}
// 向前声明
static AstNode* parse_expr(Parser* p, ErrorInfo* error);
static AstNode* parse_expr_prec(Parser* p, Precedence prec, ErrorInfo* error);
static AstNode* parse_block(Parser* p, ErrorInfo* error);
static AstNode* parse_statement(Parser* p, ErrorInfo* error);
static AstNode* parse_function(Parser* p, bool is_pub, ErrorInfo* error);
// === 前缀解析 ===
static AstNode* parse_unary(Parser* p, ErrorInfo* error) {
const Token* op = advance(p);
AstNode* operand = parse_expr_prec(p, PREC_UNARY, error);
if (!operand) return NULL;
BinaryOp uop = (op->kind == TOK_MINUS) ? OP_NEG : OP_NOT;
return ast_make_unary(p->arena, uop, operand, tok_loc(op));
}
static AstNode* parse_group(Parser* p, ErrorInfo* error) {
advance(p); // 跳过 (
AstNode* expr = parse_expr(p, error);
if (!expr) return NULL;
if (!expect(p, TOK_RPAREN, error, "缺少 ')'")) return NULL;
return expr;
}
static AstNode* parse_literal(Parser* p, ErrorInfo* error) {
const Token* t = advance(p);
switch (t->kind) {
case TOK_INT_LIT: return ast_make_literal_i64(p->arena, tok_int_value(t), tok_loc(t));
case TOK_FLOAT_LIT: return ast_make_literal_f64(p->arena, tok_float_value(t), tok_loc(t));
case TOK_CHAR_LIT: {
int64_t val = 0;
if (t->length >= 2 && t->start[0] == '\\') {
switch (t->start[1]) {
case 'n': val = '\n'; break;
case 't': val = '\t'; break;
case '\\': val = '\\'; break;
case '\'': val = '\''; break;
default: val = t->start[1]; break;
}
} else {
val = (unsigned char)t->start[0];
}
return ast_make_literal_char(p->arena, (int)val, tok_loc(t));
}
case TOK_TRUE: return ast_make_literal_bool(p->arena, true, tok_loc(t));
case TOK_FALSE: return ast_make_literal_bool(p->arena, false, tok_loc(t));
case TOK_STR_LIT: {
char* str = arena_alloc_impl(p->arena, t->length + 1);
memcpy(str, t->start, t->length);
str[t->length] = '\0';
// 字符串插值: "Hello, \(name)!" → "Hello, " + name + "!"
char* interp = strstr(str, "\\(");
if (interp) {
*interp = '\0'; // 截断前半部分
char* pre = str;
char* expr_start = interp + 2; // 跳过 \(
char* close = strchr(expr_start, ')');
if (!close) {
error->message = "字符串插值缺少 ')'"; error->filename = p->filename;
error->line = t->line; error->col = t->col; return NULL;
}
*close = '\0';
char* post = close + 1;
// 生成: pre + expr + post
AstNode* result = ast_make_literal_str(p->arena,
arena_strdup_impl(p->arena, pre, strlen(pre)), tok_loc(t));
// 将插值表达式按标识符解析
AstNode* expr = ast_make_ident(p->arena,
arena_strdup_impl(p->arena, expr_start, strlen(expr_start)), tok_loc(t));
result = ast_make_binary(p->arena, OP_ADD, result, expr, tok_loc(t));
if (post[0] != '\0') {
AstNode* post_str = ast_make_literal_str(p->arena,
arena_strdup_impl(p->arena, post, strlen(post)), tok_loc(t));
result = ast_make_binary(p->arena, OP_ADD, result, post_str, tok_loc(t));
}
return result;
}
return ast_make_literal_str(p->arena, str, tok_loc(t));
}
default: return NULL;
}
}
// === 结构体初始化解析: Name { field: val, ... } ===
static AstNode* parse_struct_init(Parser* p, const Token* name, ErrorInfo* error) {
advance(p); // 跳过 '{'
const char* fnames[32];
AstNode* fvals[32];
int fcount = 0;
while (peek(p)->kind != TOK_RBRACE && !error->message) {
if (fcount >= 32) { error->message = "结构体初始化字段过多 (最多32)"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; }
const Token* fname = expect(p, TOK_IDENT, error, "字段名");
if (!fname) return NULL;
if (!expect(p, TOK_COLON, error, "缺少 ':'")) return NULL;
AstNode* val = parse_expr(p, error);
if (!val) return NULL;
fnames[fcount] = arena_strdup_impl(p->arena, fname->start, fname->length);
fvals[fcount] = val;
fcount++;
if (peek(p)->kind == TOK_COMMA) advance(p);
else break;
}
if (!expect(p, TOK_RBRACE, error, "缺少 '}'")) return NULL;
const char** n_arr = arena_alloc_impl(p->arena, fcount * sizeof(const char*));
memcpy(n_arr, fnames, fcount * sizeof(const char*));
AstNode** v_arr = arena_alloc_impl(p->arena, fcount * sizeof(AstNode*));
memcpy(v_arr, fvals, fcount * sizeof(AstNode*));
return ast_make_struct_init(p->arena,
arena_strdup_impl(p->arena, name->start, name->length),
n_arr, v_arr, fcount, tok_loc(name));
}
// === 标识符 / 函数调用 / 结构体初始化 ===
static AstNode* parse_ident_or_call(Parser* p, ErrorInfo* error) {
const Token* name = advance(p);
// 枚举变体或模块函数: Name::Variant 或 Name::fn
if (peek(p)->kind == TOK_COLON_COLON) {
advance(p); // 跳过 ::
const Token* variant = expect(p, TOK_IDENT, error, "枚举变体名");
if (!variant) return NULL;
// Name::fn 或 Name::Variant 或 Name::Variant(payload)
if (peek(p)->kind == TOK_LPAREN) {
// 前进探测: 检查括号内是否有多参数或命名参数(→函数调用)还是单表达式(→枚举payload)
size_t probe = p->pos + 1;
int paren_depth = 1;
bool has_comma = false, has_named = false;
while (paren_depth > 0 && p->tokens[probe].kind != TOK_EOF) {
if (p->tokens[probe].kind == TOK_LPAREN) paren_depth++;
else if (p->tokens[probe].kind == TOK_RPAREN) { paren_depth--; if (paren_depth == 0) break; }
else if (paren_depth == 1 && p->tokens[probe].kind == TOK_COMMA) has_comma = true;
else if (paren_depth == 1 && p->tokens[probe].kind == TOK_COLON) has_named = true;
probe++;
}
if (has_comma || has_named) {
// 模块函数调用: Name::fn(a, b) 或 Name::fn(x: 1)
advance(p); // 跳过 '('
AstNode* args[16]; const char* arg_names[16]; int arg_count = 0;
bool seen_named = false;
while (peek(p)->kind != TOK_RPAREN && !error->message) {
if (arg_count >= 16) { error->message = "参数过多"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; }
if (peek(p)->kind == TOK_IDENT && (p->tokens[p->pos + 1].kind == TOK_COLON)) {
const Token* aname = advance(p); advance(p);
arg_names[arg_count] = arena_strdup_impl(p->arena, aname->start, aname->length);
seen_named = true;
} else {
if (seen_named) { error->message = "命名参数必须放在位置参数之后"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; }
arg_names[arg_count] = NULL;
}
args[arg_count] = parse_expr(p, error);
if (!args[arg_count]) return NULL;
arg_count++;
if (peek(p)->kind == TOK_COMMA) advance(p); else break;
}
if (!expect(p, TOK_RPAREN, error, "缺少 ')'")) return NULL;
AstNode** arg_arr = arena_alloc_impl(p->arena, arg_count * sizeof(AstNode*));
memcpy(arg_arr, args, arg_count * sizeof(AstNode*));
const char** name_arr = seen_named
? memcpy(arena_alloc_impl(p->arena, arg_count * sizeof(const char*)), arg_names, arg_count * sizeof(const char*))
: NULL;
char* full_name = arena_alloc_impl(p->arena, name->length + variant->length + 4);
sprintf(full_name, "%.*s::%.*s", name->length, name->start, variant->length, variant->start);
return ast_make_call(p->arena, full_name, arg_arr, name_arr, arg_count, tok_loc(name));
}
}
// 枚举 payload: Name::Variant 或 Name::Variant(expr)
AstNode* payload = NULL;
if (match(p, TOK_LPAREN)) {
payload = parse_expr(p, error);
if (!payload) return NULL;
if (!expect(p, TOK_RPAREN, error, "缺少 ')'")) 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),
payload, tok_loc(name));
}
// 结构体初始化: Name { field: val, ... }
// 用提前看来区别 struct init 和 block
// struct init → { IDENT COLON ... block → { 可能是 let/if/while/...
if (peek(p)->kind == TOK_LBRACE) {
const Token* after_brace = &p->tokens[p->pos + 1];
if (after_brace->kind == TOK_IDENT) {
const Token* after_fname = &p->tokens[p->pos + 2];
if (after_fname->kind == TOK_COLON) {
return parse_struct_init(p, name, error);
}
}
}
// 函数调用: name(...)
if (match(p, TOK_LPAREN)) {
AstNode* args[16]; const char* arg_names[16]; int arg_count = 0;
bool seen_named = false;
while (peek(p)->kind != TOK_RPAREN && !error->message) {
if (arg_count >= 16) {
error->message = "函数参数过多"; error->filename = p->filename;
error->line = peek(p)->line; error->col = peek(p)->col; return NULL;
}
// 命名参数: name: expr
if (peek(p)->kind == TOK_IDENT && (p->tokens[p->pos + 1].kind == TOK_COLON)) {
const Token* aname = advance(p); advance(p); // 跳过标识符和 ':'
arg_names[arg_count] = arena_strdup_impl(p->arena, aname->start, aname->length);
seen_named = true;
} else {
if (seen_named) {
error->message = "命名参数必须放在位置参数之后"; error->filename = p->filename;
error->line = peek(p)->line; error->col = peek(p)->col; return NULL;
}
arg_names[arg_count] = NULL;
}
args[arg_count] = parse_expr(p, error);
if (!args[arg_count]) return NULL;
arg_count++;
if (peek(p)->kind == TOK_COMMA) advance(p);
else break;
}
if (!expect(p, TOK_RPAREN, error, "缺少 ')'")) return NULL;
AstNode** arg_arr = arena_alloc_impl(p->arena, arg_count * sizeof(AstNode*));
memcpy(arg_arr, args, arg_count * sizeof(AstNode*));
const char** name_arr = seen_named
? memcpy(arena_alloc_impl(p->arena, arg_count * sizeof(const char*)), arg_names, arg_count * sizeof(const char*))
: NULL;
return ast_make_call(p->arena, arena_strdup_impl(p->arena, name->start, name->length),
arg_arr, name_arr, arg_count, tok_loc(name));
}
return ast_make_ident(p->arena,
arena_strdup_impl(p->arena, name->start, name->length),
tok_loc(name));
}
// === Pratt 主循环 ===
static AstNode* parse_expr_prec(Parser* p, Precedence min_prec, ErrorInfo* error) {
const Token* tok = peek(p);
AstNode* left = NULL;
// 前缀解析
if (tok->kind == TOK_IF) {
const Token* if_tok = advance(p);
// if let: if let Pattern = expr { then } else { else } → 去糖为 let+if
if (peek(p)->kind == TOK_LET) {
advance(p); // 跳过 let
// 解析模式: Enum::Variant 或 Enum::Variant(var)
AstNode* pattern = parse_expr(p, error); // 解析枚举变体
if (!pattern) return NULL;
if (!expect(p, TOK_ASSIGN, error, "if let 缺少 '='")) return NULL;
AstNode* match_expr = parse_expr(p, error);
if (!match_expr) return NULL;
AstNode* then_block = parse_block(p, error);
if (!then_block) return NULL;
AstNode* else_block = NULL;
if (match(p, TOK_ELSE)) {
if (peek(p)->kind == TOK_IF)
else_block = parse_expr_prec(p, min_prec, error);
else
else_block = parse_block(p, error);
if (!else_block) return NULL;
}
// 去糖: { let __match = expr; if __match == pattern { then } else { else } }
static int iflet_counter = 0;
char vname_buf[32];
snprintf(vname_buf, sizeof(vname_buf), "__iflet_%d", iflet_counter++);
const char* vname = arena_strdup_impl(p->arena, vname_buf, strlen(vname_buf));
AstNode* let_stmt = ast_make_let(p->arena,
vname, TYPE_UNKNOWN,
false, false, match_expr, NULL, 0, NULL, 0, tok_loc(if_tok));
AstNode* cond = ast_make_binary(p->arena, OP_EQ,
ast_make_ident(p->arena, vname, tok_loc(if_tok)),
pattern, tok_loc(if_tok));
AstNode* if_stmt = ast_make_if(p->arena, cond, then_block, else_block, tok_loc(if_tok));
AstNode* stmts[2] = { let_stmt, if_stmt };
AstNode** arr = arena_alloc_impl(p->arena, 2 * sizeof(AstNode*));
memcpy(arr, stmts, 2 * sizeof(AstNode*));
left = ast_make_block(p->arena, arr, 2, tok_loc(if_tok));
} else {
// if-expr: if cond { then } else { else }
AstNode* cond = parse_expr(p, error);
if (!cond) return NULL;
AstNode* then_block = parse_block(p, error);
if (!then_block) return NULL;
AstNode* else_block = NULL;
if (match(p, TOK_ELSE)) {
if (peek(p)->kind == TOK_IF)
else_block = parse_expr_prec(p, min_prec, error);
else
else_block = parse_block(p, error);
if (!else_block) return NULL;
}
left = ast_make_if(p->arena, cond, then_block, else_block, tok_loc(if_tok));
}
} else if (tok->kind == TOK_MINUS || tok->kind == TOK_BANG) {
left = parse_unary(p, error);
} else if (tok->kind == TOK_LPAREN) {
left = parse_group(p, error);
} else if (tok->kind == TOK_INT_LIT || tok->kind == TOK_FLOAT_LIT ||
tok->kind == TOK_CHAR_LIT ||
tok->kind == TOK_TRUE || tok->kind == TOK_FALSE ||
tok->kind == TOK_STR_LIT) {
left = parse_literal(p, error);
} else if (tok->kind == TOK_IDENT) {
left = parse_ident_or_call(p, error);
} else {
error->message = "无法识别的表达式"; error->filename = p->filename;
error->line = tok->line; error->col = tok->col;
return NULL;
}
if (!left) return NULL;
// 中缀/后置解析循环
while (!error->message) {
TokenKind kind = peek(p)->kind;
// 管道: expr |> func(args...) → func(args..., expr)
if (kind == TOK_PIPE) {
Precedence prec = PREC_PIPE;
if (prec <= min_prec) break;
const Token* op = advance(p);
// RHS 必须是函数调用(不带管道时解析)
AstNode* right = parse_expr_prec(p, prec, error);
if (!right) return NULL;
if (right->kind != AST_CALL_EXPR) {
error->message = "管道右侧必须是函数调用"; error->filename = p->filename;
error->line = op->line; error->col = op->col;
return NULL;
}
// 将 left 作为第一个参数插入(F#/Elixir 风格)
if (right->as.call.arg_count >= 16) {
error->message = "管道参数过多"; error->filename = p->filename;
error->line = op->line; error->col = op->col; return NULL;
}
AstNode** new_args = arena_alloc_impl(p->arena, (right->as.call.arg_count + 1) * sizeof(AstNode*));
new_args[0] = left;
memcpy(new_args + 1, right->as.call.args, right->as.call.arg_count * sizeof(AstNode*));
right->as.call.args = new_args;
right->as.call.arg_count++;
left = right;
continue;
}
// 后置字段访问: expr.field 或 expr.method(args)
if (kind == TOK_DOT) {
advance(p); // 跳过 '.'
const Token* field = expect(p, TOK_IDENT, error, "缺少字段名");
if (!field) return NULL;
const char* member_name = arena_strdup_impl(p->arena, field->start, field->length);
// 方法调用: expr.method(args)
if (peek(p)->kind == TOK_LPAREN) {
advance(p); // 跳过 '('
AstNode* args[16]; const char* arg_names[16]; int arg_count = 0;
bool seen_named = false;
while (peek(p)->kind != TOK_RPAREN && !error->message) {
if (arg_count >= 16) { error->message = "参数过多"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; }
if (peek(p)->kind == TOK_IDENT && (p->tokens[p->pos + 1].kind == TOK_COLON)) {
const Token* aname = advance(p); advance(p);
arg_names[arg_count] = arena_strdup_impl(p->arena, aname->start, aname->length);
seen_named = true;
} else {
if (seen_named) { error->message = "命名参数必须放在位置参数之后"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; }
arg_names[arg_count] = NULL;
}
args[arg_count] = parse_expr(p, error);
if (!args[arg_count]) return NULL;
arg_count++;
if (peek(p)->kind == TOK_COMMA) advance(p); else break;
}
if (!expect(p, TOK_RPAREN, error, "缺少 ')'")) return NULL;
AstNode** arg_arr = arena_alloc_impl(p->arena, arg_count * sizeof(AstNode*));
memcpy(arg_arr, args, arg_count * sizeof(AstNode*));
const char** name_arr = seen_named
? memcpy(arena_alloc_impl(p->arena, arg_count * sizeof(const char*)), arg_names, arg_count * sizeof(const char*))
: NULL;
left = ast_make_method_call(p->arena, left, member_name, arg_arr, name_arr, arg_count, tok_loc(field));
} else {
left = ast_make_field_access(p->arena, left, member_name, tok_loc(field));
}
continue;
}
// 后置索引: expr[expr]
if (kind == TOK_LBRACKET) {
const Token* lbrack = advance(p); // 跳过 '['
AstNode* index = parse_expr(p, error);
if (!index) return NULL;
if (!expect(p, TOK_RBRACKET, error, "缺少 ']'")) return NULL;
left = ast_make_index_expr(p->arena, left, index, tok_loc(lbrack));
continue;
}
// 中缀运算符
Precedence prec = tok_to_prec(kind);
if (prec <= min_prec) break;
const Token* op = advance(p);
AstNode* right = parse_expr_prec(p, prec, error);
if (!right) return NULL;
left = ast_make_binary(p->arena, tok_to_binop(kind), left, right, tok_loc(op));
}
return left;
}
static AstNode* parse_expr(Parser* p, ErrorInfo* error) {
return parse_expr_prec(p, PREC_NONE, error);
}
// === 类型工具 ===
static TypeKind token_to_type(TokenKind k) {
switch (k) {
case TOK_I32: return TYPE_I32;
case TOK_I64: return TYPE_I64;
case TOK_U64: return TYPE_U64;
case TOK_F64: return TYPE_F64;
case TOK_BOOL: return TYPE_BOOL;
case TOK_CHAR: return TYPE_CHAR;
case TOK_STR: return TYPE_STR;
default: return TYPE_VOID;
}
}
// === 类型表达式解析(内置类型/结构体名/数组类型)===
// 数组支持后置语法: T[N], T[N][M] 等
static TypeInfo parse_type_expr(Parser* p, ErrorInfo* error) {
const Token* t = peek(p);
TypeInfo ti = {0};
// Self 类型(trait 中引用实现者自身类型)
if (t->kind == TOK_SELF) {
advance(p);
ti.kind = TYPE_STRUCT;
ti.struct_name = "Self";
return ti;
}
// 解析基础类型
if (tok_is_type(t->kind)) {
advance(p);
ti.kind = token_to_type(t->kind);
} else if (t->kind == TOK_IDENT) {
advance(p);
ti.kind = TYPE_STRUCT;
ti.struct_name = arena_strdup_impl(p->arena, t->start, t->length);
} else {
error->message = "无效的类型"; error->filename = p->filename;
error->line = t->line; error->col = t->col;
ti.kind = TYPE_ERROR;
return ti;
}
// 后置数组维度: Type[N] → TYPE_ARRAY
if (peek(p)->kind == TOK_LBRACKET) {
advance(p); // 跳过 '['
const Token* size_tok = expect(p, TOK_INT_LIT, error, "数组大小必须是整数常量");
if (!size_tok) { ti.kind = TYPE_ERROR; return ti; }
int64_t size = tok_int_value(size_tok);
if (!expect(p, TOK_RBRACKET, error, "缺少 ']'")) {
ti.kind = TYPE_ERROR; return ti;
}
TypeInfo arr_ti = {0};
arr_ti.kind = TYPE_ARRAY;
arr_ti.element_type = ti.kind;
arr_ti.element_struct_name = ti.struct_name;
arr_ti.array_size = size;
return arr_ti;
}
return ti;
}
// === 结构体声明解析 ===
static AstNode* parse_struct_decl(Parser* p, ErrorInfo* error) {
const Token* s_tok = advance(p); // 跳过 'struct'
const Token* name = expect(p, TOK_IDENT, error, "struct 后应为结构体名");
if (!name) return NULL;
if (!expect(p, TOK_LBRACE, error, "缺少 '{'")) return NULL;
AstNode* fields[32]; int fcount = 0;
while (peek(p)->kind != TOK_RBRACE && !error->message) {
if (fcount >= 32) { error->message = "结构体字段过多 (最多32)"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; }
const Token* fname = expect(p, TOK_IDENT, error, "字段名");
if (!fname) return NULL;
if (!expect(p, TOK_COLON, error, "缺少 ':'")) return NULL;
TypeInfo fti = parse_type_expr(p, error);
if (fti.kind == TYPE_ERROR) {
error->filename = p->filename;
return NULL;
}
fields[fcount++] = ast_make_parameter(p->arena,
arena_strdup_impl(p->arena, fname->start, fname->length),
fti.kind, fti.struct_name, tok_loc(fname));
if (peek(p)->kind == TOK_COMMA) advance(p);
else break;
}
if (!expect(p, TOK_RBRACE, error, "缺少 '}'")) return NULL;
AstNode** farr = arena_alloc_impl(p->arena, fcount * sizeof(AstNode*));
memcpy(farr, fields, fcount * sizeof(AstNode*));
return ast_make_struct_decl(p->arena,
arena_strdup_impl(p->arena, name->start, name->length),
farr, fcount, tok_loc(s_tok));
}
// === match 语句解析(脱糖为 let + if-else 链)===
// match <expr> { pat1 => { body1 }, pat2 => { body2 }, _ => { body_default } }
// → { let __match_val = <expr>; if __match_val == pat1 { body1 } else if __match_val == pat2 { body2 } else { body_default } }
static AstNode* parse_match_stmt(Parser* p, ErrorInfo* error) {
const Token* match_tok = advance(p); // 跳过 'match'
// 解析被匹配的表达式
AstNode* matched = parse_expr(p, error);
if (!matched) return NULL;
if (!expect(p, TOK_LBRACE, error, "match 后缺少 '{'")) return NULL;
// 分配临时变量名
const char* varname = arena_strdup_impl(p->arena, "__match_val", 12);
// 收集所有分支
enum { MAX_ARMS = 64 };
bool arm_is_wildcard[MAX_ARMS];
AstNode* arm_pattern[MAX_ARMS];
AstNode* arm_body[MAX_ARMS];
int arm_count = 0;
while (peek(p)->kind != TOK_RBRACE && !error->message) {
if (arm_count >= MAX_ARMS) {
error->message = "match 分支过多 (最多64)";
error->filename = p->filename;
error->line = peek(p)->line; error->col = peek(p)->col;
return NULL;
}
if (peek(p)->kind == TOK_UNDERSCORE) {
arm_is_wildcard[arm_count] = true;
arm_pattern[arm_count] = NULL;
advance(p); // 跳过 '_'
} else {
arm_is_wildcard[arm_count] = false;
arm_pattern[arm_count] = parse_expr(p, error);
if (!arm_pattern[arm_count]) return NULL;
}
// 解析 '=>'
if (!expect(p, TOK_MATCH_ARROW, error, "match 分支缺少 '=>'")) return NULL;
// 解析分支体(必须是一个代码块)
arm_body[arm_count] = parse_block(p, error);
if (!arm_body[arm_count]) return NULL;
arm_count++;
// 跳过可选逗号
if (peek(p)->kind == TOK_COMMA) advance(p);
}
if (!expect(p, TOK_RBRACE, error, "缺少 '}'")) return NULL;
if (arm_count == 0) {
error->message = "match 表达式至少需要一个分支";
error->filename = p->filename;
error->line = match_tok->line; error->col = match_tok->col;
return NULL;
}
// 从最后一个分支往前构建 if-else 链(最后一个分支 = 最内层 else)
AstNode* result = NULL;
for (int i = arm_count - 1; i >= 0; i--) {
if (arm_is_wildcard[i]) {
// 通配符分支:if (true) { body } else { result }
AstNode* true_cond = ast_make_literal_bool(p->arena, true, tok_loc(match_tok));
result = ast_make_if(p->arena, true_cond, arm_body[i], result, tok_loc(match_tok));
} else {
// if (__match_val == pattern) { body } else { result }
AstNode* cond = ast_make_binary(p->arena, OP_EQ,
ast_make_ident(p->arena, varname, tok_loc(match_tok)),
arm_pattern[i], tok_loc(match_tok));
result = ast_make_if(p->arena, cond, arm_body[i], result, tok_loc(match_tok));
}
}
// 构建 let __match_val = <matched>;
AstNode* let_stmt = ast_make_let(p->arena, varname, TYPE_UNKNOWN,
false, false, matched, NULL, 0, NULL, 0, tok_loc(match_tok));
// 包装为代码块: { let __match_val = <expr>; <if-else 链> }
AstNode* stmts_arr[2] = { let_stmt, result };
AstNode** stmts = arena_alloc_impl(p->arena, 2 * sizeof(AstNode*));
memcpy(stmts, stmts_arr, 2 * sizeof(AstNode*));
return ast_make_block(p->arena, stmts, 2, tok_loc(match_tok));
}
// === 语句解析 ===
static AstNode* parse_block(Parser* p, ErrorInfo* error) {
if (++parse_depth > MAX_PARSE_DEPTH) {
error->message = "嵌套过深"; error->filename = p->filename;
error->line = peek(p)->line; error->col = peek(p)->col;
parse_depth--; return NULL;
}
const Token* open = peek(p);
if (!expect(p, TOK_LBRACE, error, "缺少 '{'")) { parse_depth--; return NULL; }
AstNode* stmts[256]; int count = 0;
while (peek(p)->kind != TOK_RBRACE && peek(p)->kind != TOK_EOF && !error->message) {
if (count >= 256) { error->message = "代码块语句过多 (最多256)"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; parse_depth--; return NULL; }
AstNode* s = parse_statement(p, error);
if (!s) { parse_depth--; return NULL; }
stmts[count++] = s;
}
if (!expect(p, TOK_RBRACE, error, "缺少 '}'")) { parse_depth--; return NULL; }
AstNode** arr = arena_alloc_impl(p->arena, count * sizeof(AstNode*));
memcpy(arr, stmts, count * sizeof(AstNode*));
parse_depth--;
return ast_make_block(p->arena, arr, count, tok_loc(open));
}
static AstNode* parse_statement(Parser* p, ErrorInfo* error) {
const Token* t = peek(p);
if (t->kind == TOK_LET || t->kind == TOK_VAR) {
bool is_mut = (advance(p)->kind == TOK_VAR);
const Token* name = expect(p, TOK_IDENT, error,
is_mut ? "var 后应为变量名" : "let 后应为变量名");
if (!name) return NULL;
// 可选的类型标注
TypeKind annot_type = TYPE_UNKNOWN;
bool has_type_annot = false;
const char* struct_type_name = NULL;
TypeKind annot_elem_type = 0;
const char* annot_elem_struct = NULL;
int64_t annot_arr_size = 0;
if (match(p, TOK_COLON)) {
TypeInfo ti = parse_type_expr(p, error);
if (ti.kind == TYPE_ERROR) return NULL;
annot_type = ti.kind;
struct_type_name = ti.struct_name;
annot_elem_type = ti.element_type;
annot_elem_struct = ti.element_struct_name;
annot_arr_size = ti.array_size;
has_type_annot = true;
}
if (!expect(p, TOK_ASSIGN, error, "缺少 '='")) return NULL;
AstNode* init = parse_expr(p, error);
if (!init) return NULL;
if (!expect(p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL;
return ast_make_let(p->arena,
arena_strdup_impl(p->arena, name->start, name->length),
annot_type, has_type_annot, is_mut, init, struct_type_name,
annot_elem_type, annot_elem_struct, annot_arr_size, tok_loc(t));
}
if (t->kind == TOK_IF) {
// 委托给表达式解析器(含 if let 去糖)
AstNode* if_expr = parse_expr_prec(p, PREC_NONE, error);
if (!if_expr) return NULL;
return if_expr; // AST_IF_STMT 或 AST_BLOCK(if-let去糖)
}
if (t->kind == TOK_WHILE) {
advance(p);
AstNode* cond = parse_expr(p, error);
if (!cond) return NULL;
AstNode* body = parse_block(p, error);
if (!body) return NULL;
return ast_make_while(p->arena, cond, body, tok_loc(t));
}
if (t->kind == TOK_FOR) {
advance(p); // 跳过 'for'
// 解析循环变量名
const Token* var_name = expect(p, TOK_IDENT, error, "for 后应为变量名");
if (!var_name) return NULL;
// 解析 'in'
if (!expect(p, TOK_IN, error, "缺少 'in'")) return NULL;
// 解析起始表达式
AstNode* start_expr = parse_expr(p, error);
if (!start_expr) return NULL;
// 解析 'to'
if (!expect(p, TOK_TO, error, "缺少 'to'")) return NULL;
// 解析结束表达式
AstNode* end_expr = parse_expr(p, error);
if (!end_expr) return NULL;
// 解析循环体
AstNode* body = parse_block(p, error);
if (!body) return NULL;
// 脱糖: for i in start to end { body; }
// → { var i = start; while i < end { body; i = i + 1; } }
const char* vname = arena_strdup_impl(p->arena, var_name->start, var_name->length);
// 构建: var i = start;
AstNode* let_stmt = ast_make_let(p->arena, vname, TYPE_UNKNOWN, false, true, start_expr, NULL, 0, NULL, 0, tok_loc(var_name));
// 构建: i < end (while 条件)
AstNode* cond = ast_make_binary(p->arena, OP_LT,
ast_make_ident(p->arena, vname, tok_loc(var_name)),
end_expr, tok_loc(var_name));
// 构建: i = i + 1 (循环增量)
AstNode* incr = ast_make_assign(p->arena, vname,
ast_make_binary(p->arena, OP_ADD,
ast_make_ident(p->arena, vname, tok_loc(var_name)),
ast_make_literal_i64(p->arena, 1, tok_loc(var_name)),
tok_loc(var_name)),
tok_loc(var_name));
// 将增量追加到循环体末尾
AstNode** new_stmts = arena_alloc_impl(p->arena,
(body->as.block.stmt_count + 1) * sizeof(AstNode*));
memcpy(new_stmts, body->as.block.stmts, body->as.block.stmt_count * sizeof(AstNode*));
new_stmts[body->as.block.stmt_count] = incr;
AstNode* new_body = ast_make_block(p->arena, new_stmts,
body->as.block.stmt_count + 1, body->loc);
// 构建: while i < end { ... body ... ; i = i + 1; }
AstNode* while_loop = ast_make_while(p->arena, cond, new_body, tok_loc(t));
// 包装: { var i = start; while i < end { ... } }
AstNode* stmts_arr[2] = { let_stmt, while_loop };
AstNode** stmts = arena_alloc_impl(p->arena, 2 * sizeof(AstNode*));
memcpy(stmts, stmts_arr, 2 * sizeof(AstNode*));
return ast_make_block(p->arena, stmts, 2, tok_loc(t));
}
if (t->kind == TOK_MATCH) {
return parse_match_stmt(p, error);
}
if (t->kind == TOK_GUARD) {
// guard expr else { ... } → if !(expr) { ... }
const Token* guard_tok = advance(p);
AstNode* cond = parse_expr(p, error);
if (!cond) return NULL;
if (!expect(p, TOK_ELSE, error, "guard 缺少 'else'")) return NULL;
AstNode* body = parse_block(p, error);
if (!body) return NULL;
// 去糖: if !cond { body }
AstNode* not_cond = ast_make_unary(p->arena, OP_NOT, cond, tok_loc(guard_tok));
return ast_make_if(p->arena, not_cond, body, NULL, tok_loc(guard_tok));
}
if (t->kind == TOK_RETURN) {
advance(p);
if (match(p, TOK_SEMICOLON)) {
return ast_make_return(p->arena, NULL, tok_loc(t));
}
AstNode* expr = parse_expr(p, error);
if (!expr) return NULL;
if (!expect(p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL;
return ast_make_return(p->arena, expr, tok_loc(t));
}
// 数组元素赋值: ident[expr] = expr ;
// 需要前瞻: 检查 ']' 后面是否是 '=' (而非 ';' 或其它)
if (t->kind == TOK_IDENT && (t + 1)->kind == TOK_LBRACKET) {
// 向前扫描找到对应的 ']'(不支持嵌套 '[' 在索引中)
int ahead_idx = 2;
int bracket_depth = 1;
while (bracket_depth > 0 && (t + ahead_idx)->kind != TOK_EOF) {
if ((t + ahead_idx)->kind == TOK_LBRACKET) bracket_depth++;
else if ((t + ahead_idx)->kind == TOK_RBRACKET) bracket_depth--;
if (bracket_depth > 0) ahead_idx++;
}
// 检查 ']' 后是否是 '='
if ((t + ahead_idx + 1)->kind == TOK_ASSIGN) {
const Token* name = advance(p); // 消费标识符
advance(p); // 消费 '['
AstNode* index = parse_expr(p, error);
if (!index) return NULL;
if (!expect(p, TOK_RBRACKET, error, "缺少 ']'")) return NULL;
if (!expect(p, TOK_ASSIGN, error, "缺少 '='")) return NULL;
AstNode* value = parse_expr(p, error);
if (!value) return NULL;
if (!expect(p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL;
return ast_make_array_assign(p->arena,
arena_strdup_impl(p->arena, name->start, name->length),
index, value, tok_loc(name));
}
// 否则: 不是数组赋值, 回退到下方表达式语句处理
}
// 赋值语句: ident = expr ;
if (t->kind == TOK_IDENT && (t + 1)->kind == TOK_ASSIGN) {
const Token* name = advance(p); // 消费标识符
advance(p); // 消费 '='
AstNode* value = parse_expr(p, error);
if (!value) return NULL;
if (!expect(p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL;
return ast_make_assign(p->arena,
arena_strdup_impl(p->arena, name->start, name->length),
value, tok_loc(name));
}
// 复合赋值: ident += expr → ident = ident + expr
if (t->kind == TOK_IDENT) {
TokenKind next_kind = (t + 1)->kind;
if (next_kind >= TOK_PLUS_EQ && next_kind <= TOK_SLASH_EQ) {
const Token* name = advance(p); // 消费标识符
TokenKind comp_op = advance(p)->kind;
BinaryOp binop;
switch (comp_op) {
case TOK_PLUS_EQ: binop = OP_ADD; break;
case TOK_MINUS_EQ: binop = OP_SUB; break;
case TOK_STAR_EQ: binop = OP_MUL; break;
case TOK_SLASH_EQ: binop = OP_DIV; break;
default: break;
}
AstNode* rhs = parse_expr(p, error);
if (!rhs) return NULL;
if (!expect(p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL;
AstNode* lhs_ident = ast_make_ident(p->arena,
arena_strdup_impl(p->arena, name->start, name->length),
tok_loc(name));
AstNode* bin_expr = ast_make_binary(p->arena, binop, lhs_ident, rhs,
tok_loc(name));
return ast_make_assign(p->arena,
arena_strdup_impl(p->arena, name->start, name->length),
bin_expr, tok_loc(name));
}
}
// 表达式语句
AstNode* expr = parse_expr(p, error);
if (!expr) return NULL;
if (!expect(p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL;
return ast_make_expr_stmt(p->arena, expr, tok_loc(t));
}
// === 函数解析 ===
static AstNode* parse_function(Parser* p, bool is_pub, ErrorInfo* error) {
const Token* fn_tok = advance(p); // fn
const Token* name = expect(p, TOK_IDENT, error, "fn 后应为函数名");
if (!name) return NULL;
// 泛型类型参数: <T, U, ...>
const char* type_params[8]; int tp_count = 0;
if (peek(p)->kind == TOK_LT) {
advance(p); // 跳过 '<'
while (peek(p)->kind != TOK_GT && !error->message) {
if (tp_count >= 8) { error->message = "类型参数过多 (最多8)"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; }
const Token* tp = expect(p, TOK_IDENT, error, "类型参数名");
if (!tp) return NULL;
type_params[tp_count++] = arena_strdup_impl(p->arena, tp->start, tp->length);
if (peek(p)->kind == TOK_COMMA) advance(p); else break;
}
if (!expect(p, TOK_GT, error, "缺少 '>'")) return NULL;
}
if (!expect(p, TOK_LPAREN, error, "缺少 '('")) return NULL;
// 参数列表(泛型参数可标注为类型参数名)
AstNode* params[64]; int pcount = 0;
while (peek(p)->kind != TOK_RPAREN && !error->message) {
if (pcount >= 64) { error->message = "函数参数过多 (最多64)"; error->filename = p->filename; error->line = peek(p)->line; error->col = peek(p)->col; return NULL; }
const Token* pname = expect(p, TOK_IDENT, error, "参数名");
if (!pname) return NULL;
if (!expect(p, TOK_COLON, error, "缺少 ':'")) return NULL;
TypeInfo pti = parse_type_expr(p, error);
if (pti.kind == TYPE_ERROR) return NULL;
params[pcount++] = ast_make_parameter(p->arena,
arena_strdup_impl(p->arena, pname->start, pname->length),
pti.kind, pti.struct_name, tok_loc(pname));
if (match(p, TOK_COMMA)) continue;
else break;
}
if (!expect(p, TOK_RPAREN, error, "缺少 ')'")) return NULL;
// 返回类型
TypeKind ret = TYPE_VOID;
const char* ret_struct_name = NULL;
if (match(p, TOK_ARROW)) {
TypeInfo rti = parse_type_expr(p, error);
if (rti.kind == TYPE_ERROR) return NULL;
ret = rti.kind;
ret_struct_name = rti.struct_name;
}
// trait 方法签名或普通函数体
AstNode* body = NULL;
if (match(p, TOK_SEMICOLON)) {
body = NULL; // trait 方法签名,无实现
} else {
body = parse_block(p, error);
if (!body) return NULL;
}
AstNode** parr = arena_alloc_impl(p->arena, pcount * sizeof(AstNode*));
memcpy(parr, params, pcount * sizeof(AstNode*));
const char** tparr = NULL;
if (tp_count > 0) {
tparr = arena_alloc_impl(p->arena, tp_count * sizeof(const char*));
memcpy(tparr, type_params, tp_count * sizeof(const char*));
}
return ast_make_function(p->arena,
arena_strdup_impl(p->arena, name->start, name->length),
parr, pcount, ret, ret_struct_name, body, is_pub, tparr, tp_count, tok_loc(fn_tok));
}
// === 模块文件加载辅助 ===
// parse 前向声明(定义在后面)
AstNode* parse(Arena* a, const Token* tokens, size_t count,
const char* filename, ErrorInfo* error);
static AstNode* load_module(Arena* a, const char* parent_file,
const char* mod_name, ErrorInfo* error) {
// 构造模块文件路径: 同目录下 mod_name.l
char mod_path[512];
const char* last_slash = strrchr(parent_file, '/');
const char* last_bs = strrchr(parent_file, '\\');
const char* dir_end = parent_file;
if (last_slash && last_slash > dir_end) dir_end = last_slash;
if (last_bs && last_bs > dir_end) dir_end = last_bs;
if (dir_end != parent_file) {
size_t dir_len = dir_end - parent_file + 1;
memcpy(mod_path, parent_file, dir_len);
snprintf(mod_path + dir_len, sizeof(mod_path) - dir_len, "%s.l", mod_name);
} else {
snprintf(mod_path, sizeof(mod_path), "%s.l", mod_name);
}
// 读取文件
FILE* f = fopen(mod_path, "rb");
if (!f) {
error->message = "无法打开模块文件"; error->filename = mod_path;
error->line = 0; error->col = 0;
return NULL;
}
fseek(f, 0, SEEK_END);
size_t sz = ftell(f); fseek(f, 0, SEEK_SET);
char* src = malloc(sz + 1);
if (!src) { fclose(f); return NULL; }
fread(src, 1, sz, f); src[sz] = '\0'; fclose(f);
size_t tc;
ErrorInfo lex_err = {0};
Token* toks = lex(a, src, mod_path, &tc, &lex_err);
free(src);
if (!toks) { *error = lex_err; return NULL; }
AstNode* ast = parse(a, toks, tc, mod_path, error);
return ast;
}
// === 程序入口 ===
AstNode* parse(Arena* a, const Token* tokens, size_t count,
const char* filename, ErrorInfo* error) {
Parser p = {.tokens = tokens, .count = count, .pos = 0,
.filename = filename, .arena = a};
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;
AstNode* impls[64]; int impl_count = 0;
AstNode* mods[64]; int mod_count = 0;
AstNode* uses[64]; int use_count = 0;
while (peek(&p)->kind != TOK_EOF && !error->message) {
// pub 前缀
bool is_pub = false;
if (peek(&p)->kind == TOK_PUB) {
is_pub = true; advance(&p);
}
if (peek(&p)->kind == TOK_TRAIT) {
const Token* tt = advance(&p);
const Token* tname = expect(&p, TOK_IDENT, error, "trait 后应为接口名");
if (!tname) return NULL;
if (!expect(&p, TOK_LBRACE, error, "缺少 '{'")) return NULL;
AstNode* methods[64]; int mcount = 0;
while (peek(&p)->kind != TOK_RBRACE && !error->message) {
if (mcount >= 64) { error->message = "trait 方法过多(最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
if (peek(&p)->kind != TOK_FN) { error->message = "trait 内只允许 fn"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
// trait 方法只解析签名(body 为空)
AstNode* m = parse_function(&p, false, error);
if (!m) return NULL;
m->as.function.body = NULL; // trait 方法无实现
methods[mcount++] = m;
if (peek(&p)->kind == TOK_COMMA) advance(&p);
}
if (!expect(&p, TOK_RBRACE, error, "缺少 '}'")) return NULL;
AstNode** marr = arena_alloc_impl(p.arena, mcount * sizeof(AstNode*));
memcpy(marr, methods, mcount * sizeof(AstNode*));
// 复用 impl_count 存储 trait(共用计数)
if (impl_count >= 64) { error->message = "trait 过多(最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
impls[impl_count++] = ast_make_trait_decl(p.arena,
arena_strdup_impl(p.arena, tname->start, tname->length),
marr, mcount, tok_loc(tt));
} else 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; }
structs[struct_count++] = parse_struct_decl(&p, error);
} else if (peek(&p)->kind == TOK_TYPE) {
if (alias_count >= 64) { error->message = "类型别名过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
const Token* type_tok = advance(&p); // 跳过 'type'
const Token* alias_name = expect(&p, TOK_IDENT, error, "type 后应为别名");
if (!alias_name) return NULL;
if (!expect(&p, TOK_ASSIGN, error, "缺少 '='")) return NULL;
TypeInfo rti = parse_type_expr(&p, error);
if (rti.kind == TYPE_ERROR) return NULL;
if (!expect(&p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL;
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];
TypeKind payload_types[64];
const char* payload_snames[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);
payload_types[vcount] = TYPE_VOID;
payload_snames[vcount] = NULL;
// 可选 payload: Variant(Type)
if (peek(&p)->kind == TOK_LPAREN) {
advance(&p);
TypeInfo pti = parse_type_expr(&p, error);
if (pti.kind == TYPE_ERROR) return NULL;
payload_types[vcount] = pti.kind;
payload_snames[vcount] = pti.struct_name;
if (!expect(&p, TOK_RPAREN, error, "缺少 ')'")) return NULL;
}
vcount++;
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*));
TypeKind* pt_arr = arena_alloc_impl(p.arena, vcount * sizeof(TypeKind));
memcpy(pt_arr, payload_types, vcount * sizeof(TypeKind));
const char** ps_arr = arena_alloc_impl(p.arena, vcount * sizeof(const char*));
memcpy(ps_arr, payload_snames, vcount * sizeof(const char*));
AstNode* enum_decl = ast_make_enum_decl(p.arena,
arena_strdup_impl(p.arena, name->start, name->length),
v_arr, pt_arr, ps_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_EXTEND) {
const Token* i_tok = advance(&p);
const Token* first = expect(&p, TOK_IDENT, error, "extend 后应为结构体名");
if (!first) return NULL;
const char* trait_name = NULL;
const char* struct_name;
// extend Trait Struct { ... }trait 实现:两个标识符)
if (peek(&p)->kind == TOK_IDENT) {
trait_name = arena_strdup_impl(p.arena, first->start, first->length);
struct_name = arena_strdup_impl(p.arena, peek(&p)->start, peek(&p)->length);
advance(&p);
} else {
struct_name = arena_strdup_impl(p.arena, first->start, first->length);
}
if (!expect(&p, TOK_LBRACE, error, "缺少 '{'")) return NULL;
AstNode* methods[64]; int mcount = 0;
while (peek(&p)->kind != TOK_RBRACE && !error->message) {
if (mcount >= 64) { error->message = "方法过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
if (peek(&p)->kind != TOK_FN) { error->message = "extend 块内只允许 fn"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
AstNode* m = parse_function(&p, false, error);
if (!m) return NULL;
// trait 实现: 方法名 mangled 为 TraitName$methodName
if (trait_name) {
char* mn = arena_alloc_impl(p.arena, strlen(trait_name) + strlen(m->as.function.name) + 4);
sprintf(mn, "%s$%s", trait_name, m->as.function.name);
m->as.function.name = mn;
}
methods[mcount++] = m;
}
if (!expect(&p, TOK_RBRACE, error, "缺少 '}'")) return NULL;
AstNode** m_arr = arena_alloc_impl(p.arena, mcount * sizeof(AstNode*));
memcpy(m_arr, methods, mcount * sizeof(AstNode*));
if (impl_count >= 64) { error->message = "extend 块过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
impls[impl_count++] = ast_make_impl_block(p.arena, struct_name, m_arr, mcount, tok_loc(i_tok));
} else if (peek(&p)->kind == TOK_MOD) {
advance(&p);
const Token* mn = expect(&p, TOK_IDENT, error, "mod 后应为模块名");
if (!mn) return NULL;
if (!expect(&p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL;
const char* mod_name = arena_strdup_impl(p.arena, mn->start, mn->length);
AstNode* sub = load_module(a, filename, mod_name, error);
if (!sub) return NULL;
// 合并子模块项到当前文件(以 mod_name:: 为前缀)
for (size_t i = 0; i < sub->as.program.fn_count; i++) {
AstNode* fn = sub->as.program.functions[i];
if (fn->as.function.is_pub) {
char* mangled = arena_alloc_impl(p.arena, strlen(mod_name) + strlen(fn->as.function.name) + 4);
sprintf(mangled, "%s::%s", mod_name, fn->as.function.name);
fn->as.function.name = mangled;
if (fn_count >= 256) { error->message = "函数过多"; error->filename = p.filename; return NULL; }
functions[fn_count++] = fn;
}
}
for (size_t i = 0; i < sub->as.program.struct_count; i++) {
if (struct_count >= 64) break;
structs[struct_count++] = sub->as.program.structs[i];
}
for (size_t i = 0; i < sub->as.program.enum_count; i++) {
if (enum_count >= 64) break;
enums[enum_count++] = sub->as.program.enums[i];
}
if (mod_count < 64) mods[mod_count++] = ast_make_mod_decl(a, mod_name, sub, tok_loc(mn));
} else if (peek(&p)->kind == TOK_USE) {
advance(&p);
const Token* path_tok = expect(&p, TOK_IDENT, error, "use 后应为模块名");
if (!path_tok) return NULL;
if (!expect(&p, TOK_COLON_COLON, error, "缺少 '::'")) return NULL;
const Token* item_tok = expect(&p, TOK_IDENT, error, "use 后应为项目名");
if (!item_tok) return NULL;
if (!expect(&p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL;
if (use_count >= 64) { error->message = "use 过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
uses[use_count++] = ast_make_use_decl(a,
arena_strdup_impl(p.arena, path_tok->start, path_tok->length),
arena_strdup_impl(p.arena, item_tok->start, item_tok->length),
tok_loc(path_tok));
} 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, is_pub, error);
} else {
error->message = "顶层只允许 fn、struct、type、enum、extend、mod 或 use";
error->filename = p.filename;
error->line = peek(&p)->line;
error->col = peek(&p)->col;
return NULL;
}
}
if (error->message) return NULL;
AstNode** fn_arr = arena_alloc_impl(a, fn_count * sizeof(AstNode*));
memcpy(fn_arr, functions, fn_count * sizeof(AstNode*));
AstNode** st_arr = arena_alloc_impl(a, struct_count * sizeof(AstNode*));
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*));
AstNode** im_arr = arena_alloc_impl(a, impl_count * sizeof(AstNode*));
memcpy(im_arr, impls, impl_count * sizeof(AstNode*));
return ast_make_program(a, fn_arr, fn_count, st_arr, struct_count,
al_arr, alias_count, en_arr, enum_count,
im_arr, impl_count, loc_at(0, 0));
}