Commit 928f6f48a6
Changed files (4)
lib
lib/std/zig/ast.zig
@@ -255,6 +255,7 @@ pub const Tree = struct {
=> return main_tokens[n] - end_offset,
.ArrayInitDot,
+ .ArrayInitDotComma,
.ArrayInitDotTwo,
.ArrayInitDotTwoComma,
.StructInitDot,
@@ -311,7 +312,9 @@ pub const Tree = struct {
.Deref,
.ArrayAccess,
.ArrayInitOne,
+ .ArrayInitOneComma,
.ArrayInit,
+ .ArrayInitComma,
.StructInitOne,
.StructInit,
.CallOne,
@@ -604,6 +607,13 @@ pub const Tree = struct {
const extra = tree.extraData(datas[n].rhs, Node.Asm);
return extra.rparen + end_offset;
},
+ .ArrayInit => {
+ const elements = tree.extraData(datas[n].rhs, Node.SubRange);
+ assert(elements.end - elements.start > 0);
+ end_offset += 1; // for the rbrace
+ n = tree.extra_data[elements.end - 1]; // last element
+ },
+ .ArrayInitComma,
.ContainerDeclArgComma,
.SwitchComma,
=> {
@@ -612,6 +622,7 @@ pub const Tree = struct {
end_offset += 2; // for the comma + rbrace
n = tree.extra_data[members.end - 1]; // last parameter
},
+ .ArrayInitDot,
.Block,
.ContainerDecl,
.TaggedUnion,
@@ -621,6 +632,7 @@ pub const Tree = struct {
end_offset += 1; // for the rbrace
n = tree.extra_data[datas[n].rhs - 1]; // last statement
},
+ .ArrayInitDotComma,
.BlockSemicolon,
.ContainerDeclComma,
.TaggedUnionComma,
@@ -772,7 +784,16 @@ pub const Tree = struct {
}
},
- .SliceOpen, .CallOneComma, .AsyncCallOneComma => {
+ .ArrayInitOne => {
+ end_offset += 1; // rbrace
+ n = datas[n].rhs;
+ assert(n != 0);
+ },
+ .SliceOpen,
+ .CallOneComma,
+ .AsyncCallOneComma,
+ .ArrayInitOneComma,
+ => {
end_offset += 2; // ellipsis2 + rbracket, or comma + rparen
n = datas[n].rhs;
assert(n != 0);
@@ -912,9 +933,6 @@ pub const Tree = struct {
// require recursion due to the optional comma followed by rbrace.
// TODO follow the pattern set by StructInitDotTwoComma which will allow
// lastToken to work for all of these.
- .ArrayInit => unreachable, // TODO
- .ArrayInitOne => unreachable, // TODO
- .ArrayInitDot => unreachable, // TODO
.StructInit => unreachable, // TODO
.StructInitOne => unreachable, // TODO
.StructInitDot => unreachable, // TODO
@@ -1151,7 +1169,8 @@ pub const Tree = struct {
}
pub fn arrayInitOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full.ArrayInit {
- assert(tree.nodes.items(.tag)[node] == .ArrayInitOne);
+ assert(tree.nodes.items(.tag)[node] == .ArrayInitOne or
+ tree.nodes.items(.tag)[node] == .ArrayInitOneComma);
const data = tree.nodes.items(.data)[node];
buffer[0] = data.rhs;
const elements = if (data.rhs == 0) buffer[0..0] else buffer[0..1];
@@ -1185,7 +1204,8 @@ pub const Tree = struct {
}
pub fn arrayInitDot(tree: Tree, node: Node.Index) full.ArrayInit {
- assert(tree.nodes.items(.tag)[node] == .ArrayInitDot);
+ assert(tree.nodes.items(.tag)[node] == .ArrayInitDot or
+ tree.nodes.items(.tag)[node] == .ArrayInitDotComma);
const data = tree.nodes.items(.data)[node];
return .{
.ast = .{
@@ -1197,7 +1217,8 @@ pub const Tree = struct {
}
pub fn arrayInit(tree: Tree, node: Node.Index) full.ArrayInit {
- assert(tree.nodes.items(.tag)[node] == .ArrayInit);
+ assert(tree.nodes.items(.tag)[node] == .ArrayInit or
+ tree.nodes.items(.tag)[node] == .ArrayInitComma);
const data = tree.nodes.items(.data)[node];
const elem_range = tree.extraData(data.rhs, Node.SubRange);
return .{
@@ -2436,6 +2457,8 @@ pub const Node = struct {
ArrayAccess,
/// `lhs{rhs}`. rhs can be omitted.
ArrayInitOne,
+ /// `lhs{rhs,}`. rhs can *not* be omitted
+ ArrayInitOneComma,
/// `.{lhs, rhs}`. lhs and rhs can be omitted.
ArrayInitDotTwo,
/// Same as `ArrayInitDotTwo` except there is known to be a trailing comma
@@ -2443,8 +2466,14 @@ pub const Node = struct {
ArrayInitDotTwoComma,
/// `.{a, b}`. `sub_list[lhs..rhs]`.
ArrayInitDot,
+ /// Same as `ArrayInitDot` except there is known to be a trailing comma
+ /// before the final rbrace.
+ ArrayInitDotComma,
/// `lhs{a, b}`. `sub_range_list[rhs]`. lhs can be omitted which means `.{a, b}`.
ArrayInit,
+ /// Same as `ArrayInit` except there is known to be a trailing comma
+ /// before the final rbrace.
+ ArrayInitComma,
/// `lhs{.a = rhs}`. rhs can be omitted making it empty.
/// main_token is the lbrace.
StructInitOne,
lib/std/zig/parse.zig
@@ -2205,9 +2205,10 @@ const Parser = struct {
}
const elem_init = try p.expectExpr();
+ const comma_one = p.eatToken(.Comma);
if (p.eatToken(.RBrace)) |_| {
return p.addNode(.{
- .tag = .ArrayInitOne,
+ .tag = if (comma_one != null) .ArrayInitOneComma else .ArrayInitOne,
.main_token = lbrace,
.data = .{
.lhs = lhs,
@@ -2215,21 +2216,30 @@ const Parser = struct {
},
});
}
+ if (comma_one == null) {
+ try p.warn(.{
+ .ExpectedToken = .{ .token = p.tok_i, .expected_id = .Comma },
+ });
+ }
var init_list = std.ArrayList(Node.Index).init(p.gpa);
defer init_list.deinit();
try init_list.append(elem_init);
- while (p.eatToken(.Comma)) |_| {
- const next = try p.parseExpr();
- if (next == 0) break;
+ var trailing_comma = true;
+ var next = try p.parseExpr();
+ while (next != 0) : (next = try p.parseExpr()) {
try init_list.append(next);
+ if (p.eatToken(.Comma) == null) {
+ trailing_comma = false;
+ break;
+ }
}
_ = try p.expectToken(.RBrace);
const span = try p.listToSpan(init_list.items);
return p.addNode(.{
- .tag = .ArrayInit,
+ .tag = if (trailing_comma) .ArrayInitComma else .ArrayInit,
.main_token = lbrace,
.data = .{
.lhs = lhs,
@@ -2805,7 +2815,7 @@ const Parser = struct {
const comma_two = p.eatToken(.Comma);
if (p.eatToken(.RBrace)) |_| {
return p.addNode(.{
- .tag = if (comma_one != null) .ArrayInitDotTwoComma else .ArrayInitDotTwo,
+ .tag = if (comma_two != null) .ArrayInitDotTwoComma else .ArrayInitDotTwo,
.main_token = lbrace,
.data = .{
.lhs = elem_init_one,
@@ -2855,7 +2865,7 @@ const Parser = struct {
}
const span = try p.listToSpan(init_list.items);
return p.addNode(.{
- .tag = .ArrayInitDot,
+ .tag = if (p.token_tags[p.tok_i - 2] == .Comma) .ArrayInitDotComma else .ArrayInitDot,
.main_token = lbrace,
.data = .{
.lhs = span.start,
lib/std/zig/parser_test.zig
@@ -568,109 +568,135 @@ test "zig fmt: struct literal 3 element comma" {
test "zig fmt: anon list literal 1 element" {
try testCanonical(
- \\const x = .{a};
+ \\test {
+ \\ const x = .{a};
+ \\}
\\
);
}
test "zig fmt: anon list literal 1 element comma" {
try testCanonical(
- \\const x = .{
- \\ a,
- \\};
+ \\test {
+ \\ const x = .{
+ \\ a,
+ \\ };
+ \\}
\\
);
}
test "zig fmt: anon list literal 2 element" {
try testCanonical(
- \\const x = .{ a, b };
+ \\test {
+ \\ const x = .{ a, b };
+ \\}
\\
);
}
test "zig fmt: anon list literal 2 element comma" {
try testCanonical(
- \\const x = .{
- \\ a,
- \\ b,
- \\};
+ \\test {
+ \\ const x = .{
+ \\ a,
+ \\ b,
+ \\ };
+ \\}
\\
);
}
test "zig fmt: anon list literal 3 element" {
try testCanonical(
- \\const x = .{ a, b, c };
+ \\test {
+ \\ const x = .{ a, b, c };
+ \\}
\\
);
}
test "zig fmt: anon list literal 3 element comma" {
try testCanonical(
- \\const x = .{
- \\ a,
- \\ b,
- \\ c,
- \\};
+ \\test {
+ \\ const x = .{
+ \\ a,
+ \\ b,
+ \\ c,
+ \\ };
+ \\}
\\
);
}
test "zig fmt: array literal 1 element" {
try testCanonical(
- \\const x = [_]u32{a};
+ \\test {
+ \\ const x = [_]u32{a};
+ \\}
\\
);
}
test "zig fmt: array literal 1 element comma" {
try testCanonical(
- \\const x = [1]u32{
- \\ a,
- \\};
+ \\test {
+ \\ const x = [1]u32{
+ \\ a,
+ \\ };
+ \\}
\\
);
}
test "zig fmt: array literal 2 element" {
try testCanonical(
- \\const x = [_]u32{ a, b };
+ \\test {
+ \\ const x = [_]u32{ a, b };
+ \\}
\\
);
}
test "zig fmt: array literal 2 element comma" {
try testCanonical(
- \\const x = [2]u32{
- \\ a,
- \\ b,
- \\};
+ \\test {
+ \\ const x = [2]u32{
+ \\ a,
+ \\ b,
+ \\ };
+ \\}
\\
);
}
test "zig fmt: array literal 3 element" {
try testCanonical(
- \\const x = [_]u32{ a, b, c };
+ \\test {
+ \\ const x = [_]u32{ a, b, c };
+ \\}
\\
);
}
test "zig fmt: array literal 3 element comma" {
try testCanonical(
- \\const x = [3]u32{
- \\ a,
- \\ b,
- \\ c,
- \\};
+ \\test {
+ \\ const x = [3]u32{
+ \\ a,
+ \\ b,
+ \\ c,
+ \\ };
+ \\}
\\
);
}
test "zig fmt: sentinel array literal 1 element" {
try testCanonical(
- \\const x = [_:9000]u32{a};
+ \\test {
+ \\ const x = [_:9000]u32{a};
+ \\}
\\
);
}
lib/std/zig/render.zig
@@ -390,7 +390,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
.PtrType => return renderPtrType(ais, tree, tree.ptrType(node), space),
.PtrTypeBitRange => return renderPtrType(ais, tree, tree.ptrTypeBitRange(node), space),
- .ArrayInitOne => {
+ .ArrayInitOne, .ArrayInitOneComma => {
var elements: [1]ast.Node.Index = undefined;
return renderArrayInit(ais, tree, tree.arrayInitOne(&elements, node), space);
},
@@ -398,8 +398,12 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
var elements: [2]ast.Node.Index = undefined;
return renderArrayInit(ais, tree, tree.arrayInitDotTwo(&elements, node), space);
},
- .ArrayInitDot => return renderArrayInit(ais, tree, tree.arrayInitDot(node), space),
- .ArrayInit => return renderArrayInit(ais, tree, tree.arrayInit(node), space),
+ .ArrayInitDot,
+ .ArrayInitDotComma,
+ => return renderArrayInit(ais, tree, tree.arrayInitDot(node), space),
+ .ArrayInit,
+ .ArrayInitComma,
+ => return renderArrayInit(ais, tree, tree.arrayInit(node), space),
.StructInitOne => {
var fields: [1]ast.Node.Index = undefined;