feat: 字符串类型 + 字面量 + print_str

- 新增 TYPE_STR 类型 (i8* 指针)
- lexer: 双引号字符串字面量 + str 关键字
- parser: TOK_STR_LIT → AST_LITERAL_EXPR(str_val)
- sema: print_str 内置函数注册 + 字符串拼接类型检查
- codegen: GlobalStringPtr 生成字符串常量,print_str → printf("%s")
- 新增集成测试 07_hello_str.l

基于 Codex 分析报告 P0 建议。
This commit is contained in:
2026-06-05 00:47:53 +08:00
parent bd02a4989e
commit 9a53d97274
10 changed files with 84 additions and 11 deletions
+11 -3
View File
@@ -89,6 +89,12 @@ static AstNode* parse_literal(Parser* p) {
case TOK_FLOAT_LIT: return ast_make_literal_f64(p->arena, tok_float_value(t), t->line, t->col);
case TOK_TRUE: return ast_make_literal_bool(p->arena, true, t->line, t->col);
case TOK_FALSE: return ast_make_literal_bool(p->arena, false, t->line, t->col);
case TOK_STR_LIT: {
char* str = arena_alloc_impl(p->arena, t->length + 1);
memcpy(str, t->start, t->length);
str[t->length] = '\0';
return ast_make_literal_str(p->arena, str, t->line, t->col);
}
default: return NULL;
}
}
@@ -131,7 +137,8 @@ static AstNode* parse_expr_prec(Parser* p, Precedence min_prec, ErrorInfo* 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_TRUE || tok->kind == TOK_FALSE) {
tok->kind == TOK_TRUE || tok->kind == TOK_FALSE ||
tok->kind == TOK_STR_LIT) {
left = parse_literal(p);
} else if (tok->kind == TOK_IDENT) {
left = parse_ident_or_call(p, error);
@@ -163,12 +170,13 @@ static AstNode* parse_expr(Parser* p, ErrorInfo* error) {
// === 类型工具 ===
static bool is_type_token(TokenKind k) {
return k == TOK_I64 || k == TOK_F64 || k == TOK_BOOL || k == TOK_VOID;
return k == TOK_I64 || k == TOK_F64 || k == TOK_BOOL || k == TOK_STR || k == TOK_VOID;
}
static TypeKind token_to_type(TokenKind k) {
switch (k) { case TOK_I64: return TYPE_I64; case TOK_F64: return TYPE_F64;
case TOK_BOOL: return TYPE_BOOL; default: return TYPE_VOID; }
case TOK_BOOL: return TYPE_BOOL; case TOK_STR: return TYPE_STR;
default: return TYPE_VOID; }
}
// === 语句解析 ===