feat: 数组+索引 [T;N], arr[i] (P1 #6)

- lexer: TOK_LBRACKET, TOK_RBRACKET
- type: TYPE_ARRAY + TypeInfo扩展(element_type/array_size)
- ast: AST_INDEX_EXPR, AST_ARRAY_ASSIGN_STMT
- parser: parse_type_expr()支持[T;N], Pratt加[索引], 数组元素赋值
- sema: 数组类型检查, 索引必须i64, 元素赋值类型匹配
- codegen: type_info_to_llvm(TYPE_ARRAY), GEP+load/store
- 新增集成测试: 18_array.l

测试: 136 通过 (41+15+59+21)
This commit is contained in:
2026-06-05 14:19:01 +08:00
parent 5237398245
commit 2923e7574d
14 changed files with 512 additions and 58 deletions
+72 -3
View File
@@ -231,6 +231,16 @@ static AstNode* parse_expr_prec(Parser* p, Precedence min_prec, ErrorInfo* error
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;
@@ -255,9 +265,32 @@ static TypeKind token_to_type(TokenKind k) {
default: return TYPE_VOID; }
}
// === 类型表达式解析(内置类型/结构体名)===
// === 类型表达式解析(内置类型/结构体名/数组类型===
static TypeInfo parse_type_expr(Parser* p, ErrorInfo* error) {
const Token* t = peek(p);
// 数组类型: [element_type; size]
if (t->kind == TOK_LBRACKET) {
advance(p); // 跳过 '['
TypeInfo elem = parse_type_expr(p, error);
if (elem.kind == TYPE_ERROR) return elem;
if (!expect(p, TOK_SEMICOLON, error, "数组类型中缺少 ';'")) {
TypeInfo ti = {0}; ti.kind = TYPE_ERROR; return ti;
}
const Token* size_tok = expect(p, TOK_INT_LIT, error, "数组大小必须是整数常量");
if (!size_tok) { TypeInfo ti = {0}; ti.kind = TYPE_ERROR; return ti; }
int64_t size = tok_int_value(size_tok);
if (!expect(p, TOK_RBRACKET, error, "缺少 ']'")) {
TypeInfo ti = {0}; ti.kind = TYPE_ERROR; return ti;
}
TypeInfo ti = {0};
ti.kind = TYPE_ARRAY;
ti.element_type = elem.kind;
ti.element_struct_name = elem.struct_name;
ti.array_size = size;
return ti;
}
TypeInfo ti = {0};
if (tok_is_type(t->kind)) {
advance(p);
@@ -344,11 +377,17 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) {
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;
@@ -357,7 +396,8 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) {
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, tok_loc(t));
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) {
@@ -418,7 +458,7 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) {
const char* vname = arena_strdup_impl(p->arena, var_name->start, var_name->length);
// 构建: let mut i = start;
AstNode* let_stmt = ast_make_let(p->arena, vname, TYPE_UNKNOWN, false, true, start_expr, NULL, tok_loc(var_name));
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,
@@ -462,6 +502,35 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) {
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); // 消费标识符