Commit ddfcf0246e
2022-11-24 17:13:22
1 parent
c4cac21Changed files (1)
lib
std
zig
lib/std/zig/parse.zig
@@ -131,11 +131,23 @@ const Parser = struct {
return @intCast(Node.Index, i);
}
- fn reserveNode(p: *Parser) !usize {
+ fn reserveNode(p: *Parser, tag: Ast.Node.Tag) !usize {
try p.nodes.resize(p.gpa, p.nodes.len + 1);
+ p.nodes.items(.tag)[p.nodes.len - 1] = tag;
return p.nodes.len - 1;
}
+ fn unreserveNode(p: *Parser, node_index: usize) void {
+ if (p.nodes.len == node_index) {
+ p.nodes.resize(p.gpa, p.nodes.len - 1) catch unreachable;
+ } else {
+ // There is zombie node left in the tree, let's make it as inoffensive as possible
+ // (sadly there's no no-op node)
+ p.nodes.items(.tag)[node_index] = .unreachable_literal;
+ p.nodes.items(.main_token)[node_index] = p.tok_i;
+ }
+ }
+
fn addExtra(p: *Parser, extra: anytype) Allocator.Error!Node.Index {
const fields = std.meta.fields(@TypeOf(extra));
try p.extra_data.ensureUnusedCapacity(p.gpa, fields.len);
@@ -637,13 +649,15 @@ const Parser = struct {
return fn_proto;
},
.l_brace => {
- const fn_decl_index = try p.reserveNode();
- const body_block = try p.parseBlock();
- assert(body_block != 0);
if (is_extern) {
try p.warnMsg(.{ .tag = .extern_fn_body, .token = extern_export_inline_token });
return null_node;
}
+ const fn_decl_index = try p.reserveNode(.fn_decl);
+ errdefer p.unreserveNode(fn_decl_index);
+
+ const body_block = try p.parseBlock();
+ assert(body_block != 0);
return p.setNode(fn_decl_index, .{
.tag = .fn_decl,
.main_token = p.nodes.items(.main_token)[fn_proto],
@@ -724,7 +738,8 @@ const Parser = struct {
const fn_token = p.eatToken(.keyword_fn) orelse return null_node;
// We want the fn proto node to be before its children in the array.
- const fn_proto_index = try p.reserveNode();
+ const fn_proto_index = try p.reserveNode(.fn_proto);
+ errdefer p.unreserveNode(fn_proto_index);
_ = p.eatToken(.identifier);
const params = try p.parseParamDeclList();