feature. See also
. The project being documented here (as the example) is the Zig library itself.
Parse.expectVarAssignStatement
fn expectVarAssignStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Index
File
Code
fn expectVarAssignStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Index {
const scratch_top = p.scratch.items.len;
defer p.scratch.shrinkRetainingCapacity(scratch_top);
while (true) {
const opt_var_decl_proto = try p.parseVarDeclProto();
if (opt_var_decl_proto) |var_decl| {
try p.scratch.append(p.gpa, var_decl);
} else {
const expr = try p.parseExpr() orelse {
if (p.scratch.items.len == scratch_top) {
return p.fail(.expected_statement);
} else {
return p.fail(.expected_expr_or_var_decl);
}
};
try p.scratch.append(p.gpa, expr);
}
_ = p.eatToken(.comma) orelse break;
}
const lhs_count = p.scratch.items.len - scratch_top;
assert(lhs_count > 0);
const equal_token = p.eatToken(.equal) orelse eql: {
if (lhs_count > 1) {
if (p.eatToken(.equal_equal)) |tok| {
try p.warnMsg(.{ .tag = .wrong_equal_var_decl, .token = tok });
break :eql tok;
}
return p.failExpected(.equal);
}
const lhs = p.scratch.items[scratch_top];
switch (p.nodeTag(lhs)) {
.global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => {
if (p.eatToken(.equal_equal)) |tok| {
try p.warnMsg(.{ .tag = .wrong_equal_var_decl, .token = tok });
break :eql tok;
}
return p.failExpected(.equal);
},
else => {},
}
const expr = try p.finishAssignExpr(lhs);
try p.expectSemicolon(.expected_semi_after_stmt, true);
if (comptime_token) |t| {
return p.addNode(.{
.tag = .@"comptime",
.main_token = t,
.data = .{ .node = expr },
});
} else {
return expr;
}
};
const rhs = try p.expectExpr();
try p.expectSemicolon(.expected_semi_after_stmt, true);
if (lhs_count == 1) {
const lhs = p.scratch.items[scratch_top];
switch (p.nodeTag(lhs)) {
.simple_var_decl, .aligned_var_decl, .local_var_decl, .global_var_decl => {
p.setVarDeclInitExpr(lhs, rhs.toOptional());
return lhs;
},
else => {},
}
const expr = try p.addNode(.{
.tag = .assign,
.main_token = equal_token,
.data = .{ .node_and_node = .{
lhs,
rhs,
} },
});
if (comptime_token) |t| {
return p.addNode(.{
.tag = .@"comptime",
.main_token = t,
.data = .{ .node = expr },
});
} else {
return expr;
}
}
const extra_start: ExtraIndex = @fromBackingInt(@intCast(p.extra_data.items.len));
try p.extra_data.ensureUnusedCapacity(p.gpa, lhs_count + 1);
p.extra_data.appendAssumeCapacity(@intCast(lhs_count));
p.extra_data.appendSliceAssumeCapacity(@ptrCast(p.scratch.items[scratch_top..]));
return p.addNode(.{
.tag = .assign_destructure,
.main_token = equal_token,
.data = .{ .extra_and_node = .{
extra_start,
rhs,
} },
});
}