authorgravatar for gbell12907@gmail.comCMDRZero <gbell12907@gmail.com> 2026-07-18 23:57:30-05:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-22 12:21:43+02:00
logc57dfa2f06e088b67ace125f84e2d97de5396c41
tree72ce9b61000c17cf3b74fd252aabd08959d22a75
parent1bae04f02026427d1754f704bd24fce3317f3e89

Add --upgrade for migrating precedence. Known bug: deletes comments from assignment lines. No clue why.


4 files changed, 105 insertions(+), 36 deletions(-)

lib/std/zig/Ast.zig+2-4
...@@ -139,10 +139,7 @@ pub fn deinit(tree: *Ast, gpa: Allocator) void {...@@ -139,10 +139,7 @@ pub fn deinit(tree: *Ast, gpa: Allocator) void {
139}139}
140140
141pub const Mode = enum { zig, zon };141pub const Mode = enum { zig, zon };
142pub const ParseOptions = struct {142pub const ParseOptions = struct { recover: bool = true, mode: Mode = .zig, use_old_precedence: bool = false };
143 recover: bool = true,
144 mode: Mode = .zig,
145};
146143
147/// Result should be freed with tree.deinit() when there are144/// Result should be freed with tree.deinit() when there are
148/// no more references to any of the tokens or nodes.145/// no more references to any of the tokens or nodes.
...@@ -185,6 +182,7 @@ pub fn parseTokens(...@@ -185,6 +182,7 @@ pub fn parseTokens(
185 .scratch = .empty,182 .scratch = .empty,
186 .tok_i = 0,183 .tok_i = 0,
187 .recover = options.recover,184 .recover = options.recover,
185 .use_old_precedence = options.use_old_precedence,
188 };186 };
189 defer parser.errors.deinit(gpa);187 defer parser.errors.deinit(gpa);
190 defer parser.nodes.deinit(gpa);188 defer parser.nodes.deinit(gpa);
lib/std/zig/Ast/Render.zig+34-3
...@@ -4,6 +4,7 @@ const mem = std.mem;...@@ -4,6 +4,7 @@ const mem = std.mem;
4const Allocator = std.mem.Allocator;4const Allocator = std.mem.Allocator;
5const meta = std.meta;5const meta = std.meta;
6const Ast = std.zig.Ast;6const Ast = std.zig.Ast;
7const Parse = @import("../../zig/Parse.zig");
7const Token = std.zig.Token;8const Token = std.zig.Token;
8const primitives = std.zig.primitives;9const primitives = std.zig.primitives;
9const Writer = std.Io.Writer;10const Writer = std.Io.Writer;
...@@ -539,13 +540,43 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -539,13 +540,43 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
539 .@"orelse",540 .@"orelse",
540 => {541 => {
541 const lhs, const rhs = tree.nodeData(node).node_and_node;542 const lhs, const rhs = tree.nodeData(node).node_and_node;
542 try renderExpression(r, lhs, .space);543
543 const op_token = tree.nodeMainToken(node);544 const lhs_tag = tree.nodeTag(lhs);
545 const center_tag = tree.nodeTag(node);
546 const rhs_tag = tree.nodeTag(rhs);
547
548 const lhs_prec = Parse.precedenceFromNodeTag(lhs_tag);
549 const center_prec = Parse.precedenceFromNodeTag(center_tag);
550 const rhs_prec = Parse.precedenceFromNodeTag(rhs_tag);
551
552 const left_rel = lhs_prec.cmp(center_prec);
553 const right_rel = rhs_prec.cmp(center_prec);
554
555 const paren_left = left_rel == null or left_rel == .lt or (left_rel == .eq and lhs_prec.group == center_prec.group and lhs_prec.assoc == .none);
556 const paren_right = right_rel == null or right_rel == .lt;
557
558
559 if (paren_left) try ais.writeByte('(');
560 try renderExpression(r, lhs, .none);
561 if (paren_left) try ais.writeByte(')');
562 // Multiline string literals will eat the space so we need to skip if we thats next.
563 if (tree.tokenTag(tree.lastToken(lhs)) != .multiline_string_literal_line) try renderOnlySpace(r, .space);
564
544 try ais.pushIndent(.binop);565 try ais.pushIndent(.binop);
566 const op_token = tree.nodeMainToken(node);
545 const rhs_seperate_line = !tree.tokensOnSameLine(op_token, op_token + 1) or567 const rhs_seperate_line = !tree.tokensOnSameLine(op_token, op_token + 1) or
546 tree.tokenTag(op_token + 1) == .multiline_string_literal_line;568 tree.tokenTag(op_token + 1) == .multiline_string_literal_line;
547 try renderToken(r, op_token, if (rhs_seperate_line) .newline else .space);569 try renderToken(r, op_token, if (rhs_seperate_line) .newline else .space);
548 try renderExpression(r, rhs, space);570
571 if (paren_right) try ais.writeByte('(');
572 try renderExpression(r, rhs, .none);
573 if (paren_right) try ais.writeByte(')');
574
575 const most_recent = tree.lastToken(rhs);
576 const lexeme = tokenSliceForRender(tree, most_recent);
577 // If our space is .none, then the above code functions as normal and putting this here will duplicate comments and such
578 if (space != .none) try renderSpace(r, most_recent, lexeme.len, space);
579
549 ais.popIndent();580 ais.popIndent();
550 },581 },
551582
lib/std/zig/Parse.zig+63-28
...@@ -24,6 +24,7 @@ nodes: Ast.NodeList,...@@ -24,6 +24,7 @@ nodes: Ast.NodeList,
24extra_data: std.ArrayList(u32),24extra_data: std.ArrayList(u32),
25scratch: std.ArrayList(Node.Index),25scratch: std.ArrayList(Node.Index),
26recover: bool,26recover: bool,
27use_old_precedence: bool = false,
2728
28fn tokenTag(p: *const Parse, token_index: TokenIndex) Token.Tag {29fn tokenTag(p: *const Parse, token_index: TokenIndex) Token.Tag {
29 return p.tokens.items(.tag)[token_index];30 return p.tokens.items(.tag)[token_index];
...@@ -1531,6 +1532,8 @@ const PrecClass = struct {...@@ -1531,6 +1532,8 @@ const PrecClass = struct {
1531 const Group = enum {1532 const Group = enum {
1532 const num_distinct = std.meta.fieldNames(Group).len;1533 const num_distinct = std.meta.fieldNames(Group).len;
15331534
1535 top,
1536
1534 arithmetic_product_chainable,1537 arithmetic_product_chainable,
1535 arithmetic_mod_nonchainable,1538 arithmetic_mod_nonchainable,
1536 arithmetic_sum,1539 arithmetic_sum,
...@@ -1588,7 +1591,7 @@ const PrecClass = struct {...@@ -1588,7 +1591,7 @@ const PrecClass = struct {
1588 gt = 1,1591 gt = 1,
15891592
1590 fn inverted(self: Rel) Rel {1593 fn inverted(self: Rel) Rel {
1591 return @enumFromInt(-@intFromEnum(self));1594 return @fromBackingInt(@intCast(-@backingInt(self)));
1592 }1595 }
1593 };1596 };
15941597
...@@ -1602,12 +1605,14 @@ const PrecClass = struct {...@@ -1602,12 +1605,14 @@ const PrecClass = struct {
1602 if (!std.mem.startsWith(u8, fieldname_j, @tagName(major_b))) continue;1605 if (!std.mem.startsWith(u8, fieldname_j, @tagName(major_b))) continue;
16031606
1604 prec_array.*[i][j] = rel;1607 prec_array.*[i][j] = rel;
1608 prec_array.*[j][i] = rel.inverted();
1605 }1609 }
1606 }1610 }
1607 }1611 }
16081612
1609 fn setMinorRelation(prec_array: *PrecedenceArray, minor_a: Group, rel: Rel, minor_b: Group) void {1613 fn setMinorRelation(prec_array: *PrecedenceArray, minor_a: Group, rel: Rel, minor_b: Group) void {
1610 prec_array.*[@intFromEnum(minor_a)][@intFromEnum(minor_b)] = rel;1614 prec_array.*[@backingInt(minor_a)][@backingInt(minor_b)] = rel;
1615 prec_array.*[@backingInt(minor_b)][@backingInt(minor_a)] = rel.inverted();
1611 }1616 }
16121617
1613 /// Arithmetic_* > Comparison1618 /// Arithmetic_* > Comparison
...@@ -1622,6 +1627,9 @@ const PrecClass = struct {...@@ -1622,6 +1627,9 @@ const PrecClass = struct {
1622 @setEvalBranchQuota(20_000);1627 @setEvalBranchQuota(20_000);
1623 const major_greater_than_relations = [_][2]Group.Major{1628 const major_greater_than_relations = [_][2]Group.Major{
1624 // zig fmt: off1629 // zig fmt: off
1630 .{ .top, .arithmetic },
1631 .{ .top, .bitwise },
1632 .{ .top, .recovery },
1625 .{ .arithmetic, .comparison },1633 .{ .arithmetic, .comparison },
1626 .{ .bitwise, .comparison },1634 .{ .bitwise, .comparison },
1627 .{ .comparison, .bool },1635 .{ .comparison, .bool },
...@@ -1656,30 +1664,21 @@ const PrecClass = struct {...@@ -1656,30 +1664,21 @@ const PrecClass = struct {
16561664
1657 var order: PrecedenceArray = @splat(@splat(null));1665 var order: PrecedenceArray = @splat(@splat(null));
16581666
1667 setMinorRelation(&order, .top, .gt, .arithmetic_product_chainable);
1668
1659 setMinorRelation(&order, .arithmetic_product_chainable, .eq, .arithmetic_mod_nonchainable);1669 setMinorRelation(&order, .arithmetic_product_chainable, .eq, .arithmetic_mod_nonchainable);
1660 setMinorRelation(&order, .arithmetic_mod_nonchainable, .gt, .arithmetic_sum);1670 setMinorRelation(&order, .arithmetic_mod_nonchainable, .gt, .arithmetic_sum);
1661 setMinorRelation(&order, .arithmetic_product_chainable, .gt, .arithmetic_sum);
16621671
1663 setMinorRelation(&order, .arithmetic_sum, .gt, .bitwise_shift);1672 setMinorRelation(&order, .arithmetic_sum, .gt, .bitwise_shift);
16641673
1665 // Here since the transative ordering computer cant leverage equals to derive a = b < c --> a < c, we have to manually list these
1666 setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_and);1674 setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_and);
1667 setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_xor);
1668 setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_or);
1669 setMinorRelation(&order, .bitwise_shift, .gt, .recovery_catch);
1670 setMinorRelation(&order, .bitwise_shift, .gt, .recovery_orelse);
16711675
1672 setMinorRelation(&order, .bitwise_and, .eq, .bitwise_xor);1676 setMinorRelation(&order, .bitwise_and, .eq, .bitwise_xor);
1673 setMinorRelation(&order, .bitwise_xor, .eq, .bitwise_or);1677 setMinorRelation(&order, .bitwise_and, .eq, .bitwise_or);
1674 setMinorRelation(&order, .bitwise_or, .eq, .recovery_catch);1678 setMinorRelation(&order, .bitwise_and, .eq, .recovery_catch);
1675 setMinorRelation(&order, .recovery_catch, .eq, .recovery_orelse);1679 setMinorRelation(&order, .bitwise_and, .eq, .recovery_orelse);
1676 setMinorRelation(&order, .recovery_orelse, .eq, .bitwise_and);
16771680
1678 setMinorRelation(&order, .bitwise_and, .gt, .comparison);1681 setMinorRelation(&order, .bitwise_and, .gt, .comparison);
1679 setMinorRelation(&order, .bitwise_xor, .gt, .comparison);
1680 setMinorRelation(&order, .bitwise_or, .gt, .comparison);
1681 setMinorRelation(&order, .recovery_catch, .gt, .comparison);
1682 setMinorRelation(&order, .recovery_orelse, .gt, .comparison);
16831682
1684 setMinorRelation(&order, .comparison, .gt, .bool_and);1683 setMinorRelation(&order, .comparison, .gt, .bool_and);
16851684
...@@ -1697,16 +1696,22 @@ const PrecClass = struct {...@@ -1697,16 +1696,22 @@ const PrecClass = struct {
1697 };1696 };
16981697
1699 pub fn cmp(lhs: PrecClass, rhs: PrecClass) ?Rel {1698 pub fn cmp(lhs: PrecClass, rhs: PrecClass) ?Rel {
1700 return PrecClass.precedence_ordering[@intFromEnum(lhs.group)][@intFromEnum(rhs.group)];1699 return PrecClass.precedence_ordering[@backingInt(lhs.group)][@backingInt(rhs.group)];
1701 }1700 }
17021701
1703 pub fn v16_cmp(lhs: PrecClass, rhs: PrecClass) Rel {1702 pub fn v16_cmp(lhs: PrecClass, rhs: PrecClass) Rel {
1704 return PrecClass.v16_precedence_ordering[@intFromEnum(lhs.group)][@intFromEnum(rhs.group)].?;1703 return PrecClass.v16_precedence_ordering[@backingInt(lhs.group)][@backingInt(rhs.group)].?;
1705 }1704 }
17061705
1707 fn computeTransativeOrdering(order: *PrecedenceArray) void {1706 fn computeTransativeOrdering(order: *PrecedenceArray) void {
1708 for (0..Group.num_distinct) |i| for (0..Group.num_distinct) |j| for (0..Group.num_distinct) |k| {1707 for (0..Group.num_distinct) |i| for (0..Group.num_distinct) |j| for (0..Group.num_distinct) |k| {
1709 if (order[i][k] == order[k][j] and order[i][k] != null) order[i][j] = order[i][k];1708 if (order[i][j] == null or order[j][k] == null) continue;
1709 // X < Y < Z ==> X < Z X > Y > Z ==> X > Z
1710 if (order[i][j] == order[j][k]) order[i][k] = order[i][j];
1711 // X = Y < Z ==> X < Z X = Y > Z ==> X > Z
1712 if (order[i][j] == .eq) order[i][k] = order[j][k];
1713 // X < Y = Z ==> X < Z X > Y = Z ==> X > Z
1714 if (order[j][k] == .eq) order[i][k] = order[i][j];
1710 };1715 };
1711 for (0..Group.num_distinct) |i| for (0..Group.num_distinct) |j| {1716 for (0..Group.num_distinct) |i| for (0..Group.num_distinct) |j| {
1712 if (i == j) order[i][j] = .eq;1717 if (i == j) order[i][j] = .eq;
...@@ -1762,6 +1767,23 @@ const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec...@@ -1762,6 +1767,23 @@ const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec
1762 // zig fmt: on1767 // zig fmt: on
1763});1768});
17641769
1770fn comptimePrecedenceFromNodeTag(comptime tag: Node.Tag) PrecClass {
1771 for (operTable) |data| {
1772 if (data.tag == tag) return data.prec;
1773 }
1774 return .{ .group = .top, .assoc = .left };
1775}
1776
1777pub fn precedenceFromNodeTag(tag: Node.Tag) PrecClass {
1778 return switch (tag) {
1779 inline else => |ct_tag| comptimePrecedenceFromNodeTag(ct_tag),
1780 };
1781}
1782
1783pub fn newPrecedenceBetween(left_tok: Node.Tag, right_tok: Node.Tag) ?PrecClass.Rel {
1784 return precedenceFromNodeTag(left_tok).cmp(precedenceFromNodeTag(right_tok));
1785}
1786
1765fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32) Error!?Node.Index {1787fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32) Error!?Node.Index {
1766 var node = try p.parsePrefixExpr() orelse return null;1788 var node = try p.parsePrefixExpr() orelse return null;
17671789
...@@ -1769,17 +1791,21 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32...@@ -1769,17 +1791,21 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32
17691791
1770 while (true) {1792 while (true) {
1771 const tok_tag = p.tokenTag(p.tok_i);1793 const tok_tag = p.tokenTag(p.tok_i);
1772 const info = operTable[@intFromEnum(tok_tag)];1794 const info = operTable[@backingInt(tok_tag)];
17731795
1774 const rel = info.prec.cmp(min_exc_prec) orelse b: {1796 const prec_relation = if (!p.use_old_precedence) info.prec.cmp(min_exc_prec) else info.prec.v16_cmp(min_exc_prec);
1797 const rel = prec_relation orelse b: {
1798 // This issues warnings if the relation is null, which it never is in 0.16.0
1775 const prev_op_tok_tag = p.tokenTag(prev_operator_token);1799 const prev_op_tok_tag = p.tokenTag(prev_operator_token);
1776 const prev_op_info = operTable[@intFromEnum(prev_op_tok_tag)];1800 const prev_op_info = operTable[@backingInt(prev_op_tok_tag)];
1777 const v16_rel = prev_op_info.prec.v16_cmp(info.prec);1801 const v16_rel = prev_op_info.prec.v16_cmp(info.prec);
1778 try p.warnMsg(.{1802 try p.warnMsg(.{
1779 .tag = .ambiguous_operator_precedence,1803 .tag = .ambiguous_operator_precedence,
1780 .is_note = false,1804 .is_note = false,
1781 .token = p.tok_i,1805 .token = p.tok_i,
1782 .extra = .{ .offset = p.tok_i - prev_operator_token },1806 .extra = .{
1807 .offset = p.tok_i - prev_operator_token,
1808 },
1783 });1809 });
1784 try p.warnMsg(.{1810 try p.warnMsg(.{
1785 .tag = .previous_ambiguous_operator,1811 .tag = .previous_ambiguous_operator,
...@@ -1791,14 +1817,18 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32...@@ -1791,14 +1817,18 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32
1791 .tag = .hint_operator_precedence_left,1817 .tag = .hint_operator_precedence_left,
1792 .is_note = true,1818 .is_note = true,
1793 .token = p.tok_i,1819 .token = p.tok_i,
1794 .extra = .{ .offset = p.tok_i - prev_operator_token },1820 .extra = .{
1821 .offset = p.tok_i - prev_operator_token,
1822 },
1795 });1823 });
1796 } else {1824 } else {
1797 try p.warnMsg(.{1825 try p.warnMsg(.{
1798 .tag = .hint_operator_precedence_right,1826 .tag = .hint_operator_precedence_right,
1799 .is_note = true,1827 .is_note = true,
1800 .token = p.tok_i,1828 .token = p.tok_i,
1801 .extra = .{ .offset = p.tok_i - prev_operator_token },1829 .extra = .{
1830 .offset = p.tok_i - prev_operator_token,
1831 },
1802 });1832 });
1803 }1833 }
1804 break :b .gt;1834 break :b .gt;
...@@ -1812,12 +1842,15 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32...@@ -1812,12 +1842,15 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32
1812 //Special cased check to maintain the old more helpful error for chained comparisons.1842 //Special cased check to maintain the old more helpful error for chained comparisons.
1813 if (info.prec.group == .comparison) {1843 if (info.prec.group == .comparison) {
1814 try p.warn(.chained_comparison_operators);1844 try p.warn(.chained_comparison_operators);
1815 } else {1845 // In 0.16.0 the only reptition prohibited was comparisons which we checked above
1846 } else if (!p.use_old_precedence) {
1816 try p.warnMsg(.{1847 try p.warnMsg(.{
1817 .tag = .illegal_chained_operators,1848 .tag = .illegal_chained_operators,
1818 .is_note = false,1849 .is_note = false,
1819 .token = p.tok_i,1850 .token = p.tok_i,
1820 .extra = .{ .offset = p.tok_i - prev_operator_token },1851 .extra = .{
1852 .offset = p.tok_i - prev_operator_token,
1853 },
1821 });1854 });
1822 try p.warnMsg(.{1855 try p.warnMsg(.{
1823 .tag = .previous_ambiguous_operator,1856 .tag = .previous_ambiguous_operator,
...@@ -1828,7 +1861,9 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32...@@ -1828,7 +1861,9 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32
1828 .tag = .hint_operator_precedence_left,1861 .tag = .hint_operator_precedence_left,
1829 .is_note = true,1862 .is_note = true,
1830 .token = p.tok_i,1863 .token = p.tok_i,
1831 .extra = .{ .offset = p.tok_i - prev_operator_token },1864 .extra = .{
1865 .offset = p.tok_i - prev_operator_token,
1866 },
1832 });1867 });
1833 }1868 }
1834 }1869 }
src/fmt.zig+6-1
...@@ -41,6 +41,7 @@ const Fmt = struct {...@@ -41,6 +41,7 @@ const Fmt = struct {
41 out_buffer: std.Io.Writer.Allocating,41 out_buffer: std.Io.Writer.Allocating,
42 stdout_writer: *Io.File.Writer,42 stdout_writer: *Io.File.Writer,
43 stats: ?*Stats,43 stats: ?*Stats,
44 fix_precedence: bool,
4445
45 const SeenMap = std.AutoHashMap(Io.File.INode, void);46 const SeenMap = std.AutoHashMap(Io.File.INode, void);
46};47};
...@@ -66,6 +67,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !...@@ -66,6 +67,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
66 var check_ast_flag = false;67 var check_ast_flag = false;
67 var force_zon = false;68 var force_zon = false;
68 var enable_stats = false;69 var enable_stats = false;
70 var fix_precedence = false;
6971
70 var input_files = std.array_list.Managed([]const u8).init(gpa);72 var input_files = std.array_list.Managed([]const u8).init(gpa);
71 defer input_files.deinit();73 defer input_files.deinit();
...@@ -107,6 +109,8 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !...@@ -107,6 +109,8 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
107 try excluded_files.append(next_arg);109 try excluded_files.append(next_arg);
108 } else if (mem.eql(u8, arg, "--zon")) {110 } else if (mem.eql(u8, arg, "--zon")) {
109 force_zon = true;111 force_zon = true;
112 } else if (mem.eql(u8, arg, "--upgrade")) {
113 fix_precedence = true;
110 } else {114 } else {
111 fatal("unrecognized parameter: {q}", .{arg});115 fatal("unrecognized parameter: {q}", .{arg});
112 }116 }
...@@ -198,6 +202,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !...@@ -198,6 +202,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
198 .out_buffer = .init(gpa),202 .out_buffer = .init(gpa),
199 .stdout_writer = &stdout_writer,203 .stdout_writer = &stdout_writer,
200 .stats = null,204 .stats = null,
205 .fix_precedence = fix_precedence,
201 };206 };
202 defer fmt.seen.deinit();207 defer fmt.seen.deinit();
203 defer fmt.out_buffer.deinit();208 defer fmt.out_buffer.deinit();
...@@ -382,7 +387,7 @@ fn fmtPathFile(...@@ -382,7 +387,7 @@ fn fmtPathFile(
382 break :mode .zig;387 break :mode .zig;
383 };388 };
384389
385 var tree = try std.zig.Ast.parse(gpa, source_code, .{ .mode = mode });390 var tree = try std.zig.Ast.parse(gpa, source_code, .{ .mode = mode, .use_old_precedence = fmt.fix_precedence });
386 defer tree.deinit(gpa);391 defer tree.deinit(gpa);
387392
388 if (tree.errors.len != 0) {393 if (tree.errors.len != 0) {