stage2 修复大量AI生成的风格问题 stage1 修复对于vm abi的错误生成

This commit is contained in:
zzy committed 2026-10-03 15:05:55 +08:00
1 parent 0e38858785
commit 76f980654c
40 files changed
+619 -938

No files matched your search

+177 -213
View File
@@ -1,7 +1,6 @@
// Expect retcode = 0
// Parser:token 流 -> Ast(ADT 节点)。C 版只作控制流参考,节点分配顺序需与 stage1
// 一致,以保证 dump 的 #ref 可对比。pos 在 token 向量上移动,自动跳过 trivia。
// token 流 -> Ast。节点分配顺序必须与 splc0 一致,否则 dump 的 #ref 无法逐字节对比。
type .{ .Vec } = @import("utils/vec.spl");
type .{ .ByteView } = @import("utils/byte_view.spl");
@@ -41,7 +40,6 @@ fn new(ast: *Ast, toks: Vec, diag: *Diag): Parser {
};
}
// ---- token 访问 ----
fn token_ptr(self: *Parser, index: usize): *Token {
if index >= self.toks.len { ret null; }
@@ -138,7 +136,6 @@ fn at_eof(self: *Parser): bool {
ret false;
}
// ---- 错误 ----
fn span_of(self: *Parser, tok: *Token): Span {
if tok == null { ret span_none(); }
@@ -151,7 +148,7 @@ fn parse_error(self: *Parser, tok: *Token, what: []u8) {
Diag.err(self.diag, span_of(self, tok), .ParseExpected, what);
}
// 转义解码(镜像 stage1 spl_decode_escape):去掉引号,处理 \n \t \r \0 \\ \' \" \xHH。
// 转义解码:去掉引号,处理 \n \t \r \0 \\ \' \" \xHH。
fn hex_digit(c: u8): u8 {
if c >= '0' && c <= '9' { ret c - '0'; }
if c >= 'a' && c <= 'f' { ret (c - 'a') + 10; }
@@ -172,9 +169,7 @@ fn decode_str(t: ByteView): ByteBuffer {
if e == 'x' && i + 3 < end {
var hi = hex_digit(t.ptr[i + 2]);
var lo = hex_digit(t.ptr[i + 3]);
match ByteBuffer.append_byte(&out, (hi * 16 + lo) as u8) {
.Ok => {}, .Err(error) => {},
}
ByteBuffer.append_byte(&out, (hi * 16 + lo) as u8);
i = i + 4;
} else {
var d: u8 = e;
@@ -182,11 +177,11 @@ fn decode_str(t: ByteView): ByteBuffer {
else if e == 't' { d = '\t'; }
else if e == 'r' { d = '\r'; }
else if e == '0' { d = 0; }
match ByteBuffer.append_byte(&out, d) { .Ok => {}, .Err(error) => {} }
ByteBuffer.append_byte(&out, d);
i = i + 2;
}
} else {
match ByteBuffer.append_byte(&out, c) { .Ok => {}, .Err(error) => {} }
ByteBuffer.append_byte(&out, c);
i = i + 1;
}
}
@@ -203,7 +198,6 @@ fn expect_punct(self: *Parser, punct: Punct, what: []u8): bool {
ret true;
}
// ---- 节点 ----
fn new_node(self: *Parser, body: Body, tok: *Token): usize {
ret Ast.alloc(self.ast, body, span_of(self, tok));
@@ -262,7 +256,6 @@ fn int_token_u64(self: *Parser, tok: *Token, radix: Radix): u64 {
ret v;
}
// ---- 判定(stage1 can_start_*)----
fn can_start_expr(kind: TokenKind): bool {
match kind {
@@ -335,11 +328,10 @@ fn can_start_statement(kind: TokenKind): bool {
ret false;
}
// ---- 模式(M3.2 子集:ident / _ / .variant / tuple / .{ } )----
fn parse_pattern_aggregate(self: *Parser, start: *Token): usize {
if !expect_punct(self, .LBrace, "'{' after '.'") { ret 0; }
// stage1 先分配 PATTERN_AGGREGATE,再解析字段。
// 先分配 PATTERN_AGGREGATE,再解析字段。
var ref = new_node(self, .PatternAggregate(.{ .items = ref_vec() }), start);
var fields = ref_vec();
while !self.failed {
@@ -354,7 +346,7 @@ fn parse_pattern_aggregate(self: *Parser, start: *Token): usize {
if name == null { break; }
match name.kind { .Ident => {}, _ => { break; } }
advance(self);
// stage1 先分配 PATTERN_FIELD,再解析可选子模式。
// 先分配 PATTERN_FIELD,再解析可选子模式。
var fre = new_node(self, .PatternField(.{
.name = name.text,
.pattern = 0,
@@ -449,7 +441,7 @@ fn parse_pattern_atom(self: *Parser): usize {
if nx == null { ret 0; }
match nx.kind { .Ident => {}, _ => { ret 0; } }
advance(self);
// stage1 先分配 PATTERN_DOT,再解析子模式。
// 先分配 PATTERN_DOT,再解析子模式。
var ref = new_node(self, .PatternDot(.{
.name = nx.text,
.sub_pattern = 0,
@@ -472,7 +464,7 @@ fn parse_pattern_atom(self: *Parser): usize {
},
.LParen => {
advance(self);
// stage1 先分配 PATTERN_TUPLE,再解析内部模式。
// 先分配 PATTERN_TUPLE,再解析内部模式。
var ref = new_node(self, .PatternTuple(.{ .items = ref_vec() }), t);
if at_punct(self, .RParen) {
advance(self);
@@ -562,7 +554,6 @@ fn parse_pattern(self: *Parser): usize {
ret new_node(self, .PatternList(.{ .items = atoms }), peek(self));
}
// ---- 声明 ----
fn parse_tag_list(self: *Parser, out: *Vec, is_external: bool, allow_at: bool, bang_only: bool) {
while !self.failed {
@@ -593,7 +584,7 @@ fn parse_tag_list(self: *Parser, out: *Vec, is_external: bool, allow_at: bool, b
if t == null { ret; }
match t.kind { .Ident => {}, _ => { parse_error(self, t, "expected tag name"); ret; } }
advance(self);
// stage1 先分配 tag 节点,再解析参数。
// 先分配 tag 节点,再解析参数。
var body: Body = .TagItem(.{
.is_at = is_at,
.is_external = ext_here,
@@ -724,20 +715,16 @@ fn token_starts_type(t: *Token): bool {
match t.kind {
.Ident => { ret true; },
.Keyword(k) => {
if @enum2int(k) == @enum2int(Keyword.Type) { ret true; }
if @enum2int(k) == @enum2int(Keyword.Bool) { ret true; }
if @enum2int(k) == @enum2int(Keyword.Any) { ret true; }
if @enum2int(k) == @enum2int(Keyword.Fn) { ret true; }
if @enum2int(k) == @enum2int(Keyword.Struct) { ret true; }
if @enum2int(k) == @enum2int(Keyword.Union) { ret true; }
if @enum2int(k) == @enum2int(Keyword.Enum) { ret true; }
if @enum2int(k) == @enum2int(Keyword.Shape) { ret true; }
match k {
.Type, .Bool, .Any, .Fn, .Struct, .Union, .Enum, .Shape => { ret true; },
_ => {},
}
},
.Punct(p) => {
if @enum2int(p) == @enum2int(Punct.Mul) { ret true; }
if @enum2int(p) == @enum2int(Punct.LBracket) { ret true; }
if @enum2int(p) == @enum2int(Punct.At) { ret true; }
if @enum2int(p) == @enum2int(Punct.Sharp) { ret true; }
match p {
.Mul, .LBracket, .At, .Sharp => { ret true; },
_ => {},
}
},
_ => {},
}
@@ -795,7 +782,7 @@ fn parse_type_decl(self: *Parser, tags: Vec): usize {
var pattern = parse_pattern(self);
if pattern == 0 { ret 0; }
if !expect_punct(self, .Assign, "'=' in type declaration") { ret 0; }
// stage1 先分配 TYPE_DECL 再解析 type_expr(影响 #ref 顺序)。
// 先分配 TYPE_DECL 再解析 type_expr(影响 #ref 顺序)。
var ref = new_node(self, .TypeDecl(.{
.attr_list = tags,
.pattern = pattern,
@@ -913,32 +900,33 @@ fn parse_container_declaration(self: *Parser): usize {
match t.kind {
.Eof => { ret 0; },
.Keyword(k) => {
if @enum2int(k) == @enum2int(Keyword.Fn) { ret parse_fn_decl(self, tags, false); }
if @enum2int(k) == @enum2int(Keyword.Type) { ret parse_type_decl(self, tags); }
if @enum2int(k) == @enum2int(Keyword.Var) {
ret parse_var_const_decl(self, tags, false);
}
if @enum2int(k) == @enum2int(Keyword.Const) {
ret parse_var_const_decl(self, tags, true);
}
if @enum2int(k) == @enum2int(Keyword.Comptime) {
// `comptime fn ...` -> 标记为编译期函数;否则 `comptime { }` 声明。
var nxt = peek_next(self);
if nxt != null && kind_is_keyword(nxt.kind, .Fn) {
advance(self);
ret parse_fn_decl(self, tags, true);
}
ret parse_comptime_decl(self);
match k {
.Fn => { ret parse_fn_decl(self, tags, false); },
.Type => { ret parse_type_decl(self, tags); },
.Var => { ret parse_var_const_decl(self, tags, false); },
.Const => { ret parse_var_const_decl(self, tags, true); },
.Comptime => {
var nxt = peek_next(self);
if nxt != null && kind_is_keyword(nxt.kind, .Fn) {
advance(self);
ret parse_fn_decl(self, tags, true);
}
ret parse_comptime_decl(self);
},
_ => {},
}
},
.Ident => { ret parse_member_decl(self, tags); },
.Punct(p) => {
if @enum2int(p) == @enum2int(Punct.LBrace) {
var block = parse_block(self);
ret new_node(self, .TopLevelBlock(.{
.tag_list = tags,
.block = block,
}), t);
match p {
.LBrace => {
var block = parse_block(self);
ret new_node(self, .TopLevelBlock(.{
.tag_list = tags,
.block = block,
}), t);
},
_ => {},
}
},
_ => {},
@@ -948,7 +936,6 @@ fn parse_container_declaration(self: *Parser): usize {
ret 0;
}
// ---- 类型 ----
fn parse_type_comptime_call(self: *Parser): usize {
var start = peek(self);
@@ -977,7 +964,7 @@ fn parse_type_base(self: *Parser): usize {
if kind_is_keyword(bt.kind, .Fn) {
advance(self);
if !expect_punct(self, .LParen, "'(' in function type") { ret 0; }
// stage1 先分配 TYPE_FN,再解析参数与返回类型。
// 先分配 TYPE_FN,再解析参数与返回类型。
var ref = new_node(self, .TypeFn(.{
.is_comptime = false,
.params = ref_vec(),
@@ -1011,10 +998,13 @@ fn parse_type_base(self: *Parser): usize {
match bt.kind {
.Keyword(k) => {
var kind_name: []u8 = "";
if @enum2int(k) == @enum2int(Keyword.Struct) { kind_name = "struct"; }
else if @enum2int(k) == @enum2int(Keyword.Union) { kind_name = "union"; }
else if @enum2int(k) == @enum2int(Keyword.Enum) { kind_name = "enum"; }
else if @enum2int(k) == @enum2int(Keyword.Shape) { kind_name = "shape"; }
match k {
.Struct => { kind_name = "struct"; },
.Union => { kind_name = "union"; },
.Enum => { kind_name = "enum"; },
.Shape => { kind_name = "shape"; },
_ => {},
}
if kind_name.len != 0 {
advance(self);
if !expect_punct(self, .LBrace, "'{' in aggregate type") { ret 0; }
@@ -1088,20 +1078,21 @@ fn parse_type_base(self: *Parser): usize {
}), bt);
},
.Keyword(k) => {
// stage1 is_builtin_type_kw:bool / any 作为类型路径;stage3 增加 `type`。
if @enum2int(k) == @enum2int(Keyword.Bool) ||
@enum2int(k) == @enum2int(Keyword.Any) ||
@enum2int(k) == @enum2int(Keyword.Type) {
advance(self);
ret new_node(self, .TypePath(.{
.name = bt.text,
.generic_args = ref_vec(),
}), bt);
match k {
.Bool, .Any, .Type => {
advance(self);
ret new_node(self, .TypePath(.{
.name = bt.text,
.generic_args = ref_vec(),
}), bt);
},
_ => {},
}
},
.Punct(p) => {
if @enum2int(p) == @enum2int(Punct.At) || @enum2int(p) == @enum2int(Punct.Sharp) {
ret parse_type_comptime_call(self);
match p {
.At, .Sharp => { ret parse_type_comptime_call(self); },
_ => {},
}
},
_ => {},
@@ -1116,7 +1107,7 @@ fn parse_type_expr(self: *Parser): usize {
if kind_is_punct(t.kind, .Mul) {
advance(self);
// stage1 先分配 POINTER,再解析 pointee。
// 先分配 POINTER,再解析 pointee。
var ref = new_node(self, .TypePointer(.{ .pointee = 0 }), t);
var pointee = parse_type_expr(self);
var pn = Ast.node(self.ast, ref);
@@ -1200,7 +1191,6 @@ fn parse_type_expr(self: *Parser): usize {
ret base;
}
// ---- 表达式 ----
type BinInfo = struct { op: Punct, prec: i32, right: bool }
type BinResult = enum { No, Yes: BinInfo }
@@ -1367,7 +1357,7 @@ fn parse_postfix(self: *Parser): usize {
if kind_is_punct(t.kind, .LParen) {
advance(self);
// stage1 先分配 CALL,再解析实参(影响 #ref 顺序)。
// 先分配 CALL,再解析实参(影响 #ref 顺序)。
var ref = new_node(self, .ExprCall(.{ .callee = expr, .args = ref_vec() }), t);
var args = parse_expr_list(self);
var cn = Ast.node(self.ast, ref);
@@ -1480,47 +1470,31 @@ fn parse_primary(self: *Parser): usize {
ret new_node(self, .ExprStringLit(.{ .data = Ast.push_string(self.ast, decode_str(t.text)) }), t);
},
.Keyword(k) => {
if @enum2int(k) == @enum2int(Keyword.True) {
advance(self);
ret new_node(self, .ExprBoolLit(.{ .value = true }), t);
}
if @enum2int(k) == @enum2int(Keyword.False) {
advance(self);
ret new_node(self, .ExprBoolLit(.{ .value = false }), t);
}
if @enum2int(k) == @enum2int(Keyword.Null) {
advance(self);
ret new_node(self, .ExprNullLit, t);
}
if @enum2int(k) == @enum2int(Keyword.Undefined) {
advance(self);
ret new_node(self, .ExprUndefinedLit, t);
}
if @enum2int(k) == @enum2int(Keyword.If) { ret parse_if_expr(self); }
if @enum2int(k) == @enum2int(Keyword.While) { ret parse_while_expr(self); }
if @enum2int(k) == @enum2int(Keyword.Loop) { ret parse_loop_expr(self); }
if @enum2int(k) == @enum2int(Keyword.For) { ret parse_for_expr(self); }
if @enum2int(k) == @enum2int(Keyword.Match) { ret parse_match_expr(self); }
// `try <expr>`:错误上抛前缀。
if @enum2int(k) == @enum2int(Keyword.Try) {
advance(self);
var tv = parse_expr(self);
ret new_node(self, .ExprTry(.{ .value = tv }), t);
}
// `comptime <expr>`:编译期表达式(可调用普通函数、返回类型等)。
if @enum2int(k) == @enum2int(Keyword.Comptime) {
advance(self);
var cbody = parse_expr(self);
ret new_node(self, .ExprComptime(.{ .body = cbody }), t);
}
// 类型即表达式:仅在 comptime 上下文内允许 `struct { ... }` 等聚合类型。
if self.comptime_depth > 0 {
if @enum2int(k) == @enum2int(Keyword.Struct) ||
@enum2int(k) == @enum2int(Keyword.Union) ||
@enum2int(k) == @enum2int(Keyword.Enum) ||
@enum2int(k) == @enum2int(Keyword.Shape) {
ret parse_type_base(self);
}
match k {
.True => { advance(self); ret new_node(self, .ExprBoolLit(.{ .value = true }), t); },
.False => { advance(self); ret new_node(self, .ExprBoolLit(.{ .value = false }), t); },
.Null => { advance(self); ret new_node(self, .ExprNullLit, t); },
.Undefined => { advance(self); ret new_node(self, .ExprUndefinedLit, t); },
.If => { ret parse_if_expr(self); },
.While => { ret parse_while_expr(self); },
.Loop => { ret parse_loop_expr(self); },
.For => { ret parse_for_expr(self); },
.Match => { ret parse_match_expr(self); },
.Try => {
advance(self);
var tv = parse_expr(self);
ret new_node(self, .ExprTry(.{ .value = tv }), t);
},
.Comptime => {
advance(self);
var cbody = parse_expr(self);
ret new_node(self, .ExprComptime(.{ .body = cbody }), t);
},
.Struct, .Union, .Enum, .Shape => {
// 类型即表达式仅限 comptime 上下文。
if self.comptime_depth > 0 { ret parse_type_base(self); }
},
_ => {},
}
parse_error(self, t, "unrecognized expression");
ret 0;
@@ -1528,7 +1502,7 @@ fn parse_primary(self: *Parser): usize {
.Ident => {
advance(self);
if at_punct(self, .LBrace) && self.stop_agg == 0 {
// stage1 先分配 AGGREGATE_LIT,再解析字段。
// 先分配 AGGREGATE_LIT,再解析字段。
var ref = new_node(self, .ExprAggregateLit(.{
.name = t.text,
.fields = ref_vec(),
@@ -1536,10 +1510,7 @@ fn parse_primary(self: *Parser): usize {
var fields = parse_aggregate_fields(self);
var an = Ast.node(self.ast, ref);
match an.body {
.ExprAggregateLit(a) => {
a.fields = fields;
an.body = .ExprAggregateLit(a);
},
.ExprAggregateLit(&a) => { a.fields = fields; },
_ => {},
}
ret ref;
@@ -1547,71 +1518,69 @@ fn parse_primary(self: *Parser): usize {
ret new_node(self, .ExprIdent(.{ .name = t.text }), t);
},
.Punct(p) => {
if @enum2int(p) == @enum2int(Punct.Dot) {
advance(self);
var nx = peek(self);
if nx == null { parse_error(self, t, "unexpected '.'"); ret 0; }
if kind_is_punct(nx.kind, .LBrace) && self.stop_agg == 0 {
var ref = new_node(self, .ExprAggregateLit(.{
.name = ByteView.empty(),
.fields = ref_vec(),
}), t);
var fields = parse_aggregate_fields(self);
var an = Ast.node(self.ast, ref);
match an.body {
.ExprAggregateLit(a) => {
a.fields = fields;
an.body = .ExprAggregateLit(a);
},
_ => {},
match p {
.Dot => {
advance(self);
var nx = peek(self);
if nx == null { parse_error(self, t, "unexpected '.'"); ret 0; }
if kind_is_punct(nx.kind, .LBrace) && self.stop_agg == 0 {
var ref = new_node(self, .ExprAggregateLit(.{
.name = ByteView.empty(),
.fields = ref_vec(),
}), t);
var fields = parse_aggregate_fields(self);
var an = Ast.node(self.ast, ref);
match an.body {
.ExprAggregateLit(&a) => { a.fields = fields; },
_ => {},
}
ret ref;
}
ret ref;
}
if kind_is_punct(nx.kind, .LBracket) {
advance(self);
var elems = parse_expr_list(self);
if !expect_punct(self, .RBracket, "']' in array literal") { ret 0; }
ret new_node(self, .ExprArrayLit(.{
.has_len = false,
.len = 0,
.is_underscore_len = false,
.elem_type = 0,
.elems = elems,
}), t);
}
var is_ident = false;
match nx.kind { .Ident => { is_ident = true; }, _ => {} }
if is_ident { ret parse_variant_construct(self, t); }
parse_error(self, nx, "expected '{', '[' or identifier after '.'");
ret 0;
}
if @enum2int(p) == @enum2int(Punct.LBracket) { ret parse_array_literal(self); }
if @enum2int(p) == @enum2int(Punct.LBrace) { ret parse_block(self); }
if @enum2int(p) == @enum2int(Punct.At) || @enum2int(p) == @enum2int(Punct.Sharp) {
ret parse_comptime_call(self);
}
if @enum2int(p) == @enum2int(Punct.LParen) {
advance(self);
var elems = ref_vec();
if at_punct(self, .RParen) {
advance(self);
ret new_node(self, .ExprTuple(.{ .items = elems }), t);
}
var first = parse_expr(self);
if at_punct(self, .Comma) {
match Vec.push(&elems, &first as *u8) { .Ok => {}, .Err(e) => { ret 0; } }
while at_punct(self, .Comma) {
if kind_is_punct(nx.kind, .LBracket) {
advance(self);
if at_punct(self, .RParen) { break; }
var nx = parse_expr(self);
match Vec.push(&elems, &nx as *u8) { .Ok => {}, .Err(e) => { ret 0; } }
var elems = parse_expr_list(self);
if !expect_punct(self, .RBracket, "']' in array literal") { ret 0; }
ret new_node(self, .ExprArrayLit(.{
.has_len = false,
.len = 0,
.is_underscore_len = false,
.elem_type = 0,
.elems = elems,
}), t);
}
expect_punct(self, .RParen, "')' in tuple literal");
ret new_node(self, .ExprTuple(.{ .items = elems }), t);
}
expect_punct(self, .RParen, "')' in paren expression");
Vec.drop(&elems);
ret first;
var is_ident = false;
match nx.kind { .Ident => { is_ident = true; }, _ => {} }
if is_ident { ret parse_variant_construct(self, t); }
parse_error(self, nx, "expected '{', '[' or identifier after '.'");
ret 0;
},
.LBracket => { ret parse_array_literal(self); },
.LBrace => { ret parse_block(self); },
.At, .Sharp => { ret parse_comptime_call(self); },
.LParen => {
advance(self);
var elems = ref_vec();
if at_punct(self, .RParen) {
advance(self);
ret new_node(self, .ExprTuple(.{ .items = elems }), t);
}
var first = parse_expr(self);
if at_punct(self, .Comma) {
Vec.push(&elems, &first as *u8);
while at_punct(self, .Comma) {
advance(self);
if at_punct(self, .RParen) { break; }
var nx = parse_expr(self);
Vec.push(&elems, &nx as *u8);
}
expect_punct(self, .RParen, "')' in tuple literal");
ret new_node(self, .ExprTuple(.{ .items = elems }), t);
}
expect_punct(self, .RParen, "')' in paren expression");
Vec.drop(&elems);
ret first;
},
_ => {},
}
},
_ => {},
@@ -1761,7 +1730,6 @@ fn parse_expr_list(self: *Parser): Vec {
ret vec;
}
// ---- if / while / loop / for / match ----
fn parse_if_expr(self: *Parser): usize {
var kw = peek(self);
@@ -1928,7 +1896,7 @@ fn parse_match_expr(self: *Parser): usize {
if at_punct(self, .Comma) { advance(self); }
}
if !expect_punct(self, .RBrace, "'}' in match") { ret 0; }
// stage1 先分配 MATCH_EXPR,再逐个分配 MATCH_ARM。
// 先分配 MATCH_EXPR,再逐个分配 MATCH_ARM。
var ref = new_node(self, .ExprMatch(.{
.matched_expr = matched,
.arms = ref_vec(),
@@ -1957,7 +1925,6 @@ fn parse_match_expr(self: *Parser): usize {
ret ref;
}
// ---- 语句 ----
fn parse_ret_stmt(self: *Parser): usize {
var kw = peek(self);
@@ -2054,27 +2021,26 @@ fn parse_statement(self: *Parser): usize {
match t.kind {
.Keyword(k) => {
if @enum2int(k) == @enum2int(Keyword.Ret) { ret parse_ret_stmt(self); }
if @enum2int(k) == @enum2int(Keyword.Break) { ret parse_break_stmt(self); }
if @enum2int(k) == @enum2int(Keyword.Continue) { ret parse_continue_stmt(self); }
if @enum2int(k) == @enum2int(Keyword.Defer) { ret parse_defer_stmt(self); }
if @enum2int(k) == @enum2int(Keyword.Errdefer) { ret parse_errdefer_stmt(self); }
if @enum2int(k) == @enum2int(Keyword.Comptime) { ret parse_comptime_stmt(self); }
if @enum2int(k) == @enum2int(Keyword.Var) ||
@enum2int(k) == @enum2int(Keyword.Const) ||
@enum2int(k) == @enum2int(Keyword.Type) {
var tags = ref_vec();
parse_tag_list(self, &tags, false, false, false);
var decl: usize = 0;
if @enum2int(k) == @enum2int(Keyword.Var) {
decl = parse_var_const_decl(self, tags, false);
} else if @enum2int(k) == @enum2int(Keyword.Const) {
decl = parse_var_const_decl(self, tags, true);
} else {
decl = parse_type_decl(self, tags);
}
if decl == 0 { ret 0; }
ret new_node(self, .StatementDecl(.{ .decl = decl }), t);
match k {
.Ret => { ret parse_ret_stmt(self); },
.Break => { ret parse_break_stmt(self); },
.Continue => { ret parse_continue_stmt(self); },
.Defer => { ret parse_defer_stmt(self); },
.Errdefer => { ret parse_errdefer_stmt(self); },
.Comptime => { ret parse_comptime_stmt(self); },
.Var, .Const, .Type => {
var tags = ref_vec();
parse_tag_list(self, &tags, false, false, false);
var decl: usize = 0;
match k {
.Var => { decl = parse_var_const_decl(self, tags, false); },
.Const => { decl = parse_var_const_decl(self, tags, true); },
_ => { decl = parse_type_decl(self, tags); },
}
if decl == 0 { ret 0; }
ret new_node(self, .StatementDecl(.{ .decl = decl }), t);
},
_ => {},
}
},
_ => {},
@@ -2179,7 +2145,7 @@ fn block_push_stmt(self: *Parser, ref: usize, stmt: usize) {
var n = Ast.node(self.ast, ref);
match n.body {
.ExprBlock(b) => {
match Vec.push(&b.stmts, &stmt as *u8) { .Ok => {}, .Err(e) => {} }
Vec.push(&b.stmts, &stmt as *u8);
n.body = .ExprBlock(b);
},
_ => {},
@@ -2200,7 +2166,6 @@ fn block_set_tail(self: *Parser, ref: usize, expr: usize) {
}
}
// ---- 入口 ----
fn skip_to_sync(self: *Parser) {
while !self.failed {
@@ -2215,7 +2180,7 @@ fn skip_to_sync(self: *Parser) {
}
}
// 解析整个文件;Root/ContainerMembers 最后分配(与 stage1 一致)。
// 解析整个文件;Root/ContainerMembers 最后分配(#ref 顺序须与 splc0 一致)。
fn parse(self: *Parser) {
var external_tags = ref_vec();
var declarations = ref_vec();
@@ -2258,7 +2223,6 @@ fn parse(self: *Parser) {
self.ast.root = root;
}
// ---- 测试 ----
fn lex_tokens(src: []u8): Vec {
var out = Vec.blank(@sizeof(Token), @alignof(Token));
@@ -2322,7 +2286,7 @@ fn expect_text(buf: *ByteBuffer, expected: []u8) {
}
}
// 与 stage1 `splc0 --dump ast` 输出逐字节一致(含 #ref 与 [line:col])。
// 与 splc0 --dump ast 逐字节一致(含 #ref 与 [line:col])。
fn test_parse_decls() {
var src: []u8 = "type Point = struct { x: i32, y: i32 };\nfn f(a: i32): i32;\n";
var toks = lex_tokens(src);
@@ -2354,7 +2318,7 @@ fn test_parse_decls() {
"AST:\n`-root #13\n `-container_members #12\n |-type_decl #2 [1:1]\n | |-pattern_ident #1 [1:6]\n | `-type_aggregate #3 [1:14]\n | |-member_decl #5 [1:23]\n | | |-type_path #4 [1:26]\n | `-member_decl #7 [1:31]\n | |-type_path #6 [1:34]\n `-fn_decl #11 [2:1]\n `-param_decl #9 [2:6]\n `-type_path #8 [2:9]\n |-type_path #10 [2:15]\n");
}
// 表达式/语句/块:与 001_main.spl 的 stage1 dump 逐字节一致。
// 表达式/语句/块:与 splc0 dump 逐字节一致。
fn test_parse_main() {
var src: []u8 = "// Expect retcode = 0\n\nfn main(): i32 {\n ret 0;\n}\n";
var toks = lex_tokens(src);
@@ -2386,7 +2350,7 @@ fn test_parse_main() {
"AST:\n`-root #7\n `-container_members #6\n `-fn_decl #5 [3:1]\n |-type_path #1 [3:12]\n `-block #2 [3:16]\n `-statement_ret #4 [4:5]\n `-int_lit #3 [4:9]\n");
}
// 任意宽度整数:2^64 也能正确解析(stage1 u64 之外);含分隔符与多进制。
// 任意宽度整数:2^64 也能正确解析;含分隔符与多进制。
fn check_int(src: []u8, expected: []u8) {
var toks = lex_tokens(src);
defer { Vec.drop(&toks); }