authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-11 13:10:06-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-11 13:12:45-05:00
logd4e6a6d5e27df845d47b254aab9d14f44d68d620
treeb133bdcf05533b2c43a7b726ff047c676e90a17f
parent725b6ee634f01355da4a6badc5675751b85f0bf0
signaturelock-open Commit is signed but in an unrecognized format.

zig fmt: support anon struct and anon list init syntax


4 files changed, 108 insertions(+), 39 deletions(-)

lib/std/zig/ast.zig+17-4
...@@ -1648,10 +1648,15 @@ pub const Node = struct {...@@ -1648,10 +1648,15 @@ pub const Node = struct {
16481648
1649 pub const SuffixOp = struct {1649 pub const SuffixOp = struct {
1650 base: Node,1650 base: Node,
1651 lhs: *Node,1651 lhs: Lhs,
1652 op: Op,1652 op: Op,
1653 rtoken: TokenIndex,1653 rtoken: TokenIndex,
16541654
1655 pub const Lhs = union(enum) {
1656 node: *Node,
1657 dot: TokenIndex,
1658 };
1659
1655 pub const Op = union(enum) {1660 pub const Op = union(enum) {
1656 Call: Call,1661 Call: Call,
1657 ArrayAccess: *Node,1662 ArrayAccess: *Node,
...@@ -1679,8 +1684,13 @@ pub const Node = struct {...@@ -1679,8 +1684,13 @@ pub const Node = struct {
1679 pub fn iterate(self: *SuffixOp, index: usize) ?*Node {1684 pub fn iterate(self: *SuffixOp, index: usize) ?*Node {
1680 var i = index;1685 var i = index;
16811686
1682 if (i < 1) return self.lhs;1687 switch (self.lhs) {
1683 i -= 1;1688 .node => |node| {
1689 if (i == 0) return node;
1690 i -= 1;
1691 },
1692 .dot => {},
1693 }
16841694
1685 switch (self.op) {1695 switch (self.op) {
1686 .Call => |*call_info| {1696 .Call => |*call_info| {
...@@ -1721,7 +1731,10 @@ pub const Node = struct {...@@ -1721,7 +1731,10 @@ pub const Node = struct {
1721 .Call => |*call_info| if (call_info.async_token) |async_token| return async_token,1731 .Call => |*call_info| if (call_info.async_token) |async_token| return async_token,
1722 else => {},1732 else => {},
1723 }1733 }
1724 return self.lhs.firstToken();1734 switch (self.lhs) {
1735 .node => |node| return node.firstToken(),
1736 .dot => |dot| return dot,
1737 }
1725 }1738 }
17261739
1727 pub fn lastToken(self: *const SuffixOp) TokenIndex {1740 pub fn lastToken(self: *const SuffixOp) TokenIndex {
lib/std/zig/parse.zig+32-20
...@@ -1026,16 +1026,16 @@ fn parseWhileExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1026,16 +1026,16 @@ fn parseWhileExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1026/// CurlySuffixExpr <- TypeExpr InitList?1026/// CurlySuffixExpr <- TypeExpr InitList?
1027fn parseCurlySuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1027fn parseCurlySuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1028 const type_expr = (try parseTypeExpr(arena, it, tree)) orelse return null;1028 const type_expr = (try parseTypeExpr(arena, it, tree)) orelse return null;
1029 const init_list = (try parseInitList(arena, it, tree)) orelse return type_expr;1029 const suffix_op = (try parseInitList(arena, it, tree)) orelse return type_expr;
1030 init_list.cast(Node.SuffixOp).?.lhs = type_expr;1030 suffix_op.lhs.node = type_expr;
1031 return init_list;1031 return &suffix_op.base;
1032}1032}
10331033
1034/// InitList1034/// InitList
1035/// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE1035/// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
1036/// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE1036/// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
1037/// / LBRACE RBRACE1037/// / LBRACE RBRACE
1038fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1038fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.SuffixOp {
1039 const lbrace = eatToken(it, .LBrace) orelse return null;1039 const lbrace = eatToken(it, .LBrace) orelse return null;
1040 var init_list = Node.SuffixOp.Op.InitList.init(arena);1040 var init_list = Node.SuffixOp.Op.InitList.init(arena);
10411041
...@@ -1064,11 +1064,11 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1064,11 +1064,11 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1064 const node = try arena.create(Node.SuffixOp);1064 const node = try arena.create(Node.SuffixOp);
1065 node.* = Node.SuffixOp{1065 node.* = Node.SuffixOp{
1066 .base = Node{ .id = .SuffixOp },1066 .base = Node{ .id = .SuffixOp },
1067 .lhs = undefined, // set by caller1067 .lhs = .{.node = undefined}, // set by caller
1068 .op = op,1068 .op = op,
1069 .rtoken = try expectToken(it, tree, .RBrace),1069 .rtoken = try expectToken(it, tree, .RBrace),
1070 };1070 };
1071 return &node.base;1071 return node;
1072}1072}
10731073
1074/// TypeExpr <- PrefixTypeOp* ErrorUnionExpr1074/// TypeExpr <- PrefixTypeOp* ErrorUnionExpr
...@@ -1117,7 +1117,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1117,7 +1117,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11171117
1118 while (try parseSuffixOp(arena, it, tree)) |node| {1118 while (try parseSuffixOp(arena, it, tree)) |node| {
1119 switch (node.id) {1119 switch (node.id) {
1120 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res,1120 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},
1121 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,1121 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
1122 else => unreachable,1122 else => unreachable,
1123 }1123 }
...@@ -1133,7 +1133,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1133,7 +1133,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1133 const node = try arena.create(Node.SuffixOp);1133 const node = try arena.create(Node.SuffixOp);
1134 node.* = Node.SuffixOp{1134 node.* = Node.SuffixOp{
1135 .base = Node{ .id = .SuffixOp },1135 .base = Node{ .id = .SuffixOp },
1136 .lhs = res,1136 .lhs = .{.node = res},
1137 .op = Node.SuffixOp.Op{1137 .op = Node.SuffixOp.Op{
1138 .Call = Node.SuffixOp.Op.Call{1138 .Call = Node.SuffixOp.Op.Call{
1139 .params = params.list,1139 .params = params.list,
...@@ -1150,7 +1150,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1150,7 +1150,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1150 while (true) {1150 while (true) {
1151 if (try parseSuffixOp(arena, it, tree)) |node| {1151 if (try parseSuffixOp(arena, it, tree)) |node| {
1152 switch (node.id) {1152 switch (node.id) {
1153 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res,1153 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},
1154 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,1154 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
1155 else => unreachable,1155 else => unreachable,
1156 }1156 }
...@@ -1161,7 +1161,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1161,7 +1161,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1161 const call = try arena.create(Node.SuffixOp);1161 const call = try arena.create(Node.SuffixOp);
1162 call.* = Node.SuffixOp{1162 call.* = Node.SuffixOp{
1163 .base = Node{ .id = .SuffixOp },1163 .base = Node{ .id = .SuffixOp },
1164 .lhs = res,1164 .lhs = .{.node = res},
1165 .op = Node.SuffixOp.Op{1165 .op = Node.SuffixOp.Op{
1166 .Call = Node.SuffixOp.Op.Call{1166 .Call = Node.SuffixOp.Op.Call{
1167 .params = params.list,1167 .params = params.list,
...@@ -1215,7 +1215,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N...@@ -1215,7 +1215,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
1215 return &node.base;1215 return &node.base;
1216 }1216 }
1217 if (try parseContainerDecl(arena, it, tree)) |node| return node;1217 if (try parseContainerDecl(arena, it, tree)) |node| return node;
1218 if (try parseEnumLiteral(arena, it, tree)) |node| return node;1218 if (try parseAnonLiteral(arena, it, tree)) |node| return node;
1219 if (try parseErrorSetDecl(arena, it, tree)) |node| return node;1219 if (try parseErrorSetDecl(arena, it, tree)) |node| return node;
1220 if (try parseFloatLiteral(arena, it, tree)) |node| return node;1220 if (try parseFloatLiteral(arena, it, tree)) |node| return node;
1221 if (try parseFnProto(arena, it, tree)) |node| return node;1221 if (try parseFnProto(arena, it, tree)) |node| return node;
...@@ -1494,16 +1494,28 @@ fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1494,16 +1494,28 @@ fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1494}1494}
14951495
1496/// DOT IDENTIFIER1496/// DOT IDENTIFIER
1497fn parseEnumLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1497fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1498 const dot = eatToken(it, .Period) orelse return null;1498 const dot = eatToken(it, .Period) orelse return null;
1499 const name = try expectToken(it, tree, .Identifier);1499
1500 const node = try arena.create(Node.EnumLiteral);1500 // anon enum literal
1501 node.* = Node.EnumLiteral{1501 if (eatToken(it, .Identifier)) |name| {
1502 .base = Node{ .id = .EnumLiteral },1502 const node = try arena.create(Node.EnumLiteral);
1503 .dot = dot,1503 node.* = Node.EnumLiteral{
1504 .name = name,1504 .base = Node{ .id = .EnumLiteral },
1505 };1505 .dot = dot,
1506 return &node.base;1506 .name = name,
1507 };
1508 return &node.base;
1509 }
1510
1511 // anon container literal
1512 if (try parseInitList(arena, it, tree)) |node| {
1513 node.lhs = .{.dot = dot};
1514 return &node.base;
1515 }
1516
1517 putBackToken(it, dot);
1518 return null;
1507}1519}
15081520
1509/// AsmOutput <- COLON AsmOutputList AsmInput?1521/// AsmOutput <- COLON AsmOutputList AsmInput?
lib/std/zig/parser_test.zig+17
...@@ -1,3 +1,20 @@...@@ -1,3 +1,20 @@
1test "zig fmt: anon struct literal syntax" {
2 try testCanonical(
3 \\const x = .{
4 \\ .a = b,
5 \\ .c = d,
6 \\};
7 \\
8 );
9}
10
11test "zig fmt: anon list literal syntax" {
12 try testCanonical(
13 \\const x = .{ a, b, c };
14 \\
15 );
16}
17
1test "zig fmt: async function" {18test "zig fmt: async function" {
2 try testCanonical(19 try testCanonical(
3 \\pub const Server = struct {20 \\pub const Server = struct {
lib/std/zig/render.zig+42-15
...@@ -538,9 +538,9 @@ fn renderExpression(...@@ -538,9 +538,9 @@ fn renderExpression(
538 try renderToken(tree, stream, async_token, indent, start_col, Space.Space);538 try renderToken(tree, stream, async_token, indent, start_col, Space.Space);
539 }539 }
540540
541 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);541 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
542542
543 const lparen = tree.nextToken(suffix_op.lhs.lastToken());543 const lparen = tree.nextToken(suffix_op.lhs.node.lastToken());
544544
545 if (call_info.params.len == 0) {545 if (call_info.params.len == 0) {
546 try renderToken(tree, stream, lparen, indent, start_col, Space.None);546 try renderToken(tree, stream, lparen, indent, start_col, Space.None);
...@@ -598,7 +598,7 @@ fn renderExpression(...@@ -598,7 +598,7 @@ fn renderExpression(
598 const lbracket = tree.prevToken(index_expr.firstToken());598 const lbracket = tree.prevToken(index_expr.firstToken());
599 const rbracket = tree.nextToken(index_expr.lastToken());599 const rbracket = tree.nextToken(index_expr.lastToken());
600600
601 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);601 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
602 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [602 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
603603
604 const starts_with_comment = tree.tokens.at(lbracket + 1).id == .LineComment;604 const starts_with_comment = tree.tokens.at(lbracket + 1).id == .LineComment;
...@@ -616,18 +616,18 @@ fn renderExpression(...@@ -616,18 +616,18 @@ fn renderExpression(
616 },616 },
617617
618 ast.Node.SuffixOp.Op.Deref => {618 ast.Node.SuffixOp.Op.Deref => {
619 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);619 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
620 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // .*620 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // .*
621 },621 },
622622
623 ast.Node.SuffixOp.Op.UnwrapOptional => {623 ast.Node.SuffixOp.Op.UnwrapOptional => {
624 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);624 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
625 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // .625 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // .
626 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ?626 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ?
627 },627 },
628628
629 @TagType(ast.Node.SuffixOp.Op).Slice => |range| {629 @TagType(ast.Node.SuffixOp.Op).Slice => |range| {
630 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);630 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
631631
632 const lbracket = tree.prevToken(range.start.firstToken());632 const lbracket = tree.prevToken(range.start.firstToken());
633 const dotdot = tree.nextToken(range.start.lastToken());633 const dotdot = tree.nextToken(range.start.lastToken());
...@@ -647,10 +647,16 @@ fn renderExpression(...@@ -647,10 +647,16 @@ fn renderExpression(
647 },647 },
648648
649 ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| {649 ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| {
650 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());650 const lbrace = switch (suffix_op.lhs) {
651 .dot => |dot| tree.nextToken(dot),
652 .node => |node| tree.nextToken(node.lastToken()),
653 };
651654
652 if (field_inits.len == 0) {655 if (field_inits.len == 0) {
653 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);656 switch (suffix_op.lhs) {
657 .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
658 .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
659 }
654 try renderToken(tree, stream, lbrace, indent + indent_delta, start_col, Space.None);660 try renderToken(tree, stream, lbrace, indent + indent_delta, start_col, Space.None);
655 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);661 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
656 }662 }
...@@ -691,7 +697,10 @@ fn renderExpression(...@@ -691,7 +697,10 @@ fn renderExpression(
691 break :blk;697 break :blk;
692 }698 }
693699
694 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);700 switch (suffix_op.lhs) {
701 .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
702 .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
703 }
695 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);704 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
696 try renderExpression(allocator, stream, tree, indent, start_col, &field_init.base, Space.Space);705 try renderExpression(allocator, stream, tree, indent, start_col, &field_init.base, Space.Space);
697 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);706 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
...@@ -699,7 +708,10 @@ fn renderExpression(...@@ -699,7 +708,10 @@ fn renderExpression(
699708
700 if (!src_has_trailing_comma and src_same_line and expr_outputs_one_line) {709 if (!src_has_trailing_comma and src_same_line and expr_outputs_one_line) {
701 // render all on one line, no trailing comma710 // render all on one line, no trailing comma
702 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);711 switch (suffix_op.lhs) {
712 .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
713 .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
714 }
703 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);715 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
704716
705 var it = field_inits.iterator(0);717 var it = field_inits.iterator(0);
...@@ -719,7 +731,10 @@ fn renderExpression(...@@ -719,7 +731,10 @@ fn renderExpression(
719731
720 const new_indent = indent + indent_delta;732 const new_indent = indent + indent_delta;
721733
722 try renderExpression(allocator, stream, tree, new_indent, start_col, suffix_op.lhs, Space.None);734 switch (suffix_op.lhs) {
735 .dot => |dot| try renderToken(tree, stream, dot, new_indent, start_col, Space.None),
736 .node => |node| try renderExpression(allocator, stream, tree, new_indent, start_col, node, Space.None),
737 }
723 try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline);738 try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline);
724739
725 var it = field_inits.iterator(0);740 var it = field_inits.iterator(0);
...@@ -743,23 +758,35 @@ fn renderExpression(...@@ -743,23 +758,35 @@ fn renderExpression(
743 },758 },
744759
745 ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| {760 ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| {
746 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());761 const lbrace = switch (suffix_op.lhs) {
762 .dot => |dot| tree.nextToken(dot),
763 .node => |node| tree.nextToken(node.lastToken()),
764 };
747765
748 if (exprs.len == 0) {766 if (exprs.len == 0) {
749 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);767 switch (suffix_op.lhs) {
768 .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
769 .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
770 }
750 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);771 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
751 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);772 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
752 }773 }
753 if (exprs.len == 1 and tree.tokens.at(exprs.at(0).*.lastToken() + 1).id == .RBrace) {774 if (exprs.len == 1 and tree.tokens.at(exprs.at(0).*.lastToken() + 1).id == .RBrace) {
754 const expr = exprs.at(0).*;775 const expr = exprs.at(0).*;
755776
756 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);777 switch (suffix_op.lhs) {
778 .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
779 .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
780 }
757 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);781 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
758 try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);782 try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);
759 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);783 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
760 }784 }
761785
762 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);786 switch (suffix_op.lhs) {
787 .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
788 .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
789 }
763790
764 // scan to find row size791 // scan to find row size
765 const maybe_row_size: ?usize = blk: {792 const maybe_row_size: ?usize = blk: {