| author | |
| committer | |
| log | d4e6a6d5e27df845d47b254aab9d14f44d68d620 |
| tree | b133bdcf05533b2c43a7b726ff047c676e90a17f |
| parent | 725b6ee634f01355da4a6badc5675751b85f0bf0 |
| signature |
4 files changed, 108 insertions(+), 39 deletions(-)
lib/std/zig/ast.zig+17-4| ... | ... | @@ -1648,10 +1648,15 @@ pub const Node = struct { |
| 1648 | 1648 | |
| 1649 | 1649 | pub const SuffixOp = struct { |
| 1650 | 1650 | base: Node, |
| 1651 | lhs: *Node, | |
| 1651 | lhs: Lhs, | |
| 1652 | 1652 | op: Op, |
| 1653 | 1653 | rtoken: TokenIndex, |
| 1654 | 1654 | |
| 1655 | pub const Lhs = union(enum) { | |
| 1656 | node: *Node, | |
| 1657 | dot: TokenIndex, | |
| 1658 | }; | |
| 1659 | ||
| 1655 | 1660 | pub const Op = union(enum) { |
| 1656 | 1661 | Call: Call, |
| 1657 | 1662 | ArrayAccess: *Node, |
| ... | ... | @@ -1679,8 +1684,13 @@ pub const Node = struct { |
| 1679 | 1684 | pub fn iterate(self: *SuffixOp, index: usize) ?*Node { |
| 1680 | 1685 | var i = index; |
| 1681 | 1686 | |
| 1682 | if (i < 1) return self.lhs; | |
| 1683 | i -= 1; | |
| 1687 | switch (self.lhs) { | |
| 1688 | .node => |node| { | |
| 1689 | if (i == 0) return node; | |
| 1690 | i -= 1; | |
| 1691 | }, | |
| 1692 | .dot => {}, | |
| 1693 | } | |
| 1684 | 1694 | |
| 1685 | 1695 | switch (self.op) { |
| 1686 | 1696 | .Call => |*call_info| { |
| ... | ... | @@ -1721,7 +1731,10 @@ pub const Node = struct { |
| 1721 | 1731 | .Call => |*call_info| if (call_info.async_token) |async_token| return async_token, |
| 1722 | 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 | } |
| 1726 | 1739 | |
| 1727 | 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 | 1026 | /// CurlySuffixExpr <- TypeExpr InitList? |
| 1027 | 1027 | fn parseCurlySuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1028 | 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; | |
| 1030 | init_list.cast(Node.SuffixOp).?.lhs = type_expr; | |
| 1031 | return init_list; | |
| 1029 | const suffix_op = (try parseInitList(arena, it, tree)) orelse return type_expr; | |
| 1030 | suffix_op.lhs.node = type_expr; | |
| 1031 | return &suffix_op.base; | |
| 1032 | 1032 | } |
| 1033 | 1033 | |
| 1034 | 1034 | /// InitList |
| 1035 | 1035 | /// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE |
| 1036 | 1036 | /// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE |
| 1037 | 1037 | /// / LBRACE RBRACE |
| 1038 | fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | |
| 1038 | fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.SuffixOp { | |
| 1039 | 1039 | const lbrace = eatToken(it, .LBrace) orelse return null; |
| 1040 | 1040 | var init_list = Node.SuffixOp.Op.InitList.init(arena); |
| 1041 | 1041 | |
| ... | ... | @@ -1064,11 +1064,11 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1064 | 1064 | const node = try arena.create(Node.SuffixOp); |
| 1065 | 1065 | node.* = Node.SuffixOp{ |
| 1066 | 1066 | .base = Node{ .id = .SuffixOp }, |
| 1067 | .lhs = undefined, // set by caller | |
| 1067 | .lhs = .{.node = undefined}, // set by caller | |
| 1068 | 1068 | .op = op, |
| 1069 | 1069 | .rtoken = try expectToken(it, tree, .RBrace), |
| 1070 | 1070 | }; |
| 1071 | return &node.base; | |
| 1071 | return node; | |
| 1072 | 1072 | } |
| 1073 | 1073 | |
| 1074 | 1074 | /// TypeExpr <- PrefixTypeOp* ErrorUnionExpr |
| ... | ... | @@ -1117,7 +1117,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1117 | 1117 | |
| 1118 | 1118 | while (try parseSuffixOp(arena, it, tree)) |node| { |
| 1119 | 1119 | switch (node.id) { |
| 1120 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res, | |
| 1120 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res}, | |
| 1121 | 1121 | .InfixOp => node.cast(Node.InfixOp).?.lhs = res, |
| 1122 | 1122 | else => unreachable, |
| 1123 | 1123 | } |
| ... | ... | @@ -1133,7 +1133,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1133 | 1133 | const node = try arena.create(Node.SuffixOp); |
| 1134 | 1134 | node.* = Node.SuffixOp{ |
| 1135 | 1135 | .base = Node{ .id = .SuffixOp }, |
| 1136 | .lhs = res, | |
| 1136 | .lhs = .{.node = res}, | |
| 1137 | 1137 | .op = Node.SuffixOp.Op{ |
| 1138 | 1138 | .Call = Node.SuffixOp.Op.Call{ |
| 1139 | 1139 | .params = params.list, |
| ... | ... | @@ -1150,7 +1150,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1150 | 1150 | while (true) { |
| 1151 | 1151 | if (try parseSuffixOp(arena, it, tree)) |node| { |
| 1152 | 1152 | switch (node.id) { |
| 1153 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res, | |
| 1153 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res}, | |
| 1154 | 1154 | .InfixOp => node.cast(Node.InfixOp).?.lhs = res, |
| 1155 | 1155 | else => unreachable, |
| 1156 | 1156 | } |
| ... | ... | @@ -1161,7 +1161,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1161 | 1161 | const call = try arena.create(Node.SuffixOp); |
| 1162 | 1162 | call.* = Node.SuffixOp{ |
| 1163 | 1163 | .base = Node{ .id = .SuffixOp }, |
| 1164 | .lhs = res, | |
| 1164 | .lhs = .{.node = res}, | |
| 1165 | 1165 | .op = Node.SuffixOp.Op{ |
| 1166 | 1166 | .Call = Node.SuffixOp.Op.Call{ |
| 1167 | 1167 | .params = params.list, |
| ... | ... | @@ -1215,7 +1215,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N |
| 1215 | 1215 | return &node.base; |
| 1216 | 1216 | } |
| 1217 | 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 | 1219 | if (try parseErrorSetDecl(arena, it, tree)) |node| return node; |
| 1220 | 1220 | if (try parseFloatLiteral(arena, it, tree)) |node| return node; |
| 1221 | 1221 | if (try parseFnProto(arena, it, tree)) |node| return node; |
| ... | ... | @@ -1494,16 +1494,28 @@ fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1494 | 1494 | } |
| 1495 | 1495 | |
| 1496 | 1496 | /// DOT IDENTIFIER |
| 1497 | fn parseEnumLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | |
| 1497 | fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | |
| 1498 | 1498 | const dot = eatToken(it, .Period) orelse return null; |
| 1499 | const name = try expectToken(it, tree, .Identifier); | |
| 1500 | const node = try arena.create(Node.EnumLiteral); | |
| 1501 | node.* = Node.EnumLiteral{ | |
| 1502 | .base = Node{ .id = .EnumLiteral }, | |
| 1503 | .dot = dot, | |
| 1504 | .name = name, | |
| 1505 | }; | |
| 1506 | return &node.base; | |
| 1499 | ||
| 1500 | // anon enum literal | |
| 1501 | if (eatToken(it, .Identifier)) |name| { | |
| 1502 | const node = try arena.create(Node.EnumLiteral); | |
| 1503 | node.* = Node.EnumLiteral{ | |
| 1504 | .base = Node{ .id = .EnumLiteral }, | |
| 1505 | .dot = dot, | |
| 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 | } |
| 1508 | 1520 | |
| 1509 | 1521 | /// AsmOutput <- COLON AsmOutputList AsmInput? |
lib/std/zig/parser_test.zig+17| ... | ... | @@ -1,3 +1,20 @@ |
| 1 | test "zig fmt: anon struct literal syntax" { | |
| 2 | try testCanonical( | |
| 3 | \\const x = .{ | |
| 4 | \\ .a = b, | |
| 5 | \\ .c = d, | |
| 6 | \\}; | |
| 7 | \\ | |
| 8 | ); | |
| 9 | } | |
| 10 | ||
| 11 | test "zig fmt: anon list literal syntax" { | |
| 12 | try testCanonical( | |
| 13 | \\const x = .{ a, b, c }; | |
| 14 | \\ | |
| 15 | ); | |
| 16 | } | |
| 17 | ||
| 1 | 18 | test "zig fmt: async function" { |
| 2 | 19 | try testCanonical( |
| 3 | 20 | \\pub const Server = struct { |
lib/std/zig/render.zig+42-15| ... | ... | @@ -538,9 +538,9 @@ fn renderExpression( |
| 538 | 538 | try renderToken(tree, stream, async_token, indent, start_col, Space.Space); |
| 539 | 539 | } |
| 540 | 540 | |
| 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); | |
| 542 | 542 | |
| 543 | const lparen = tree.nextToken(suffix_op.lhs.lastToken()); | |
| 543 | const lparen = tree.nextToken(suffix_op.lhs.node.lastToken()); | |
| 544 | 544 | |
| 545 | 545 | if (call_info.params.len == 0) { |
| 546 | 546 | try renderToken(tree, stream, lparen, indent, start_col, Space.None); |
| ... | ... | @@ -598,7 +598,7 @@ fn renderExpression( |
| 598 | 598 | const lbracket = tree.prevToken(index_expr.firstToken()); |
| 599 | 599 | const rbracket = tree.nextToken(index_expr.lastToken()); |
| 600 | 600 | |
| 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 | 602 | try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ |
| 603 | 603 | |
| 604 | 604 | const starts_with_comment = tree.tokens.at(lbracket + 1).id == .LineComment; |
| ... | ... | @@ -616,18 +616,18 @@ fn renderExpression( |
| 616 | 616 | }, |
| 617 | 617 | |
| 618 | 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 | 620 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // .* |
| 621 | 621 | }, |
| 622 | 622 | |
| 623 | 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 | 625 | try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // . |
| 626 | 626 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ? |
| 627 | 627 | }, |
| 628 | 628 | |
| 629 | 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); | |
| 631 | 631 | |
| 632 | 632 | const lbracket = tree.prevToken(range.start.firstToken()); |
| 633 | 633 | const dotdot = tree.nextToken(range.start.lastToken()); |
| ... | ... | @@ -647,10 +647,16 @@ fn renderExpression( |
| 647 | 647 | }, |
| 648 | 648 | |
| 649 | 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 | }; | |
| 651 | 654 | |
| 652 | 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 | 660 | try renderToken(tree, stream, lbrace, indent + indent_delta, start_col, Space.None); |
| 655 | 661 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); |
| 656 | 662 | } |
| ... | ... | @@ -691,7 +697,10 @@ fn renderExpression( |
| 691 | 697 | break :blk; |
| 692 | 698 | } |
| 693 | 699 | |
| 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 | 704 | try renderToken(tree, stream, lbrace, indent, start_col, Space.Space); |
| 696 | 705 | try renderExpression(allocator, stream, tree, indent, start_col, &field_init.base, Space.Space); |
| 697 | 706 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); |
| ... | ... | @@ -699,7 +708,10 @@ fn renderExpression( |
| 699 | 708 | |
| 700 | 709 | if (!src_has_trailing_comma and src_same_line and expr_outputs_one_line) { |
| 701 | 710 | // 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 | 715 | try renderToken(tree, stream, lbrace, indent, start_col, Space.Space); |
| 704 | 716 | |
| 705 | 717 | var it = field_inits.iterator(0); |
| ... | ... | @@ -719,7 +731,10 @@ fn renderExpression( |
| 719 | 731 | |
| 720 | 732 | const new_indent = indent + indent_delta; |
| 721 | 733 | |
| 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 | 738 | try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline); |
| 724 | 739 | |
| 725 | 740 | var it = field_inits.iterator(0); |
| ... | ... | @@ -743,23 +758,35 @@ fn renderExpression( |
| 743 | 758 | }, |
| 744 | 759 | |
| 745 | 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 | }; | |
| 747 | 765 | |
| 748 | 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 | 771 | try renderToken(tree, stream, lbrace, indent, start_col, Space.None); |
| 751 | 772 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); |
| 752 | 773 | } |
| 753 | 774 | if (exprs.len == 1 and tree.tokens.at(exprs.at(0).*.lastToken() + 1).id == .RBrace) { |
| 754 | 775 | const expr = exprs.at(0).*; |
| 755 | 776 | |
| 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 | 781 | try renderToken(tree, stream, lbrace, indent, start_col, Space.None); |
| 758 | 782 | try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None); |
| 759 | 783 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); |
| 760 | 784 | } |
| 761 | 785 | |
| 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 | } | |
| 763 | 790 | |
| 764 | 791 | // scan to find row size |
| 765 | 792 | const maybe_row_size: ?usize = blk: { |