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:
+72
-3
@@ -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); // 消费标识符
|
||||
|
||||
Reference in New Issue
Block a user