| ... | ... | @@ -88,6 +88,7 @@ pub const Parser = struct { |
| 88 | 88 | InfixOp: &ast.NodeInfixOp, |
| 89 | 89 | PrefixOp: &ast.NodePrefixOp, |
| 90 | 90 | SuffixOp: &ast.Node, |
| 91 | SliceOrArrayAccess, |
| 91 | 92 | AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo, |
| 92 | 93 | TypeExpr: DestPtr, |
| 93 | 94 | VarDecl: &ast.NodeVarDecl, |
| ... | ... | @@ -590,6 +591,11 @@ pub const Parser = struct { |
| 590 | 591 | }); |
| 591 | 592 | continue; |
| 592 | 593 | |
| 594 | } else if (token.id == Token.Id.LBracket) { |
| 595 | try stack.append(State.SliceOrArrayAccess); |
| 596 | try stack.append(State.ExpectOperand); |
| 597 | continue; |
| 598 | |
| 593 | 599 | // TODO: Parse postfix operator |
| 594 | 600 | } else { |
| 595 | 601 | // no postfix/infix operator after this operand. |
| ... | ... | @@ -603,6 +609,53 @@ pub const Parser = struct { |
| 603 | 609 | try dest_ptr.store(expression); |
| 604 | 610 | break; |
| 605 | 611 | }, |
| 612 | State.SliceOrArrayAccess => { |
| 613 | var rbracket_or_ellipsis2_token = self.getNextToken(); |
| 614 | |
| 615 | switch (rbracket_or_ellipsis2_token.id) { |
| 616 | Token.Id.Ellipsis2 => { |
| 617 | const node = try arena.create(ast.NodeSliceExpression); |
| 618 | *node = ast.NodeSliceExpression { |
| 619 | .base = self.initNode(ast.Node.Id.SliceExpression), |
| 620 | .expr = undefined, |
| 621 | .start = expression, |
| 622 | .end = null, |
| 623 | .rbracket_token = undefined, |
| 624 | }; |
| 625 | |
| 626 | try stack.append(State { .SuffixOp = &node.base }); |
| 627 | try stack.append(State.AfterOperand); |
| 628 | |
| 629 | const rbracket_token = self.getNextToken(); |
| 630 | if (rbracket_token.id != Token.Id.RBracket) { |
| 631 | self.putBackToken(rbracket_token); |
| 632 | try stack.append(State { |
| 633 | .ExpectTokenSave = ExpectTokenSave { |
| 634 | .id = Token.Id.RBracket, |
| 635 | .ptr = &node.rbracket_token, |
| 636 | } |
| 637 | }); |
| 638 | try stack.append(State { .Expression = DestPtr { .NullableField = &node.end } }); |
| 639 | } else { |
| 640 | node.rbracket_token = rbracket_token; |
| 641 | } |
| 642 | break; |
| 643 | }, |
| 644 | Token.Id.RBracket => { |
| 645 | const node = try arena.create(ast.NodeArrayAccess); |
| 646 | *node = ast.NodeArrayAccess { |
| 647 | .base = self.initNode(ast.Node.Id.ArrayAccess), |
| 648 | .expr = undefined, |
| 649 | .index = expression, |
| 650 | .rbracket_token = token, |
| 651 | }; |
| 652 | try stack.append(State { .SuffixOp = &node.base }); |
| 653 | try stack.append(State.AfterOperand); |
| 654 | break; |
| 655 | }, |
| 656 | else => return self.parseError(token, "expected ']' or '..', found {}", @tagName(token.id)) |
| 657 | } |
| 658 | }, |
| 606 | 659 | State.InfixOp => |infix_op| { |
| 607 | 660 | infix_op.rhs = expression; |
| 608 | 661 | infix_op.lhs = popSuffixOp(&stack); |
| ... | ... | @@ -857,6 +910,7 @@ pub const Parser = struct { |
| 857 | 910 | State.PrefixOp => unreachable, |
| 858 | 911 | State.SuffixOp => unreachable, |
| 859 | 912 | State.Operand => unreachable, |
| 913 | State.SliceOrArrayAccess => unreachable, |
| 860 | 914 | } |
| 861 | 915 | } |
| 862 | 916 | } |
| ... | ... | @@ -874,6 +928,18 @@ pub const Parser = struct { |
| 874 | 928 | left_leaf_ptr = &call.callee; |
| 875 | 929 | continue; |
| 876 | 930 | }, |
| 931 | ast.Node.Id.ArrayAccess => { |
| 932 | const arr_access = @fieldParentPtr(ast.NodeArrayAccess, "base", suffix_op); |
| 933 | *left_leaf_ptr = &arr_access.base; |
| 934 | left_leaf_ptr = &arr_access.expr; |
| 935 | continue; |
| 936 | }, |
| 937 | ast.Node.Id.SliceExpression => { |
| 938 | const slice_expr = @fieldParentPtr(ast.NodeSliceExpression, "base", suffix_op); |
| 939 | *left_leaf_ptr = &slice_expr.base; |
| 940 | left_leaf_ptr = &slice_expr.expr; |
| 941 | continue; |
| 942 | }, |
| 877 | 943 | else => unreachable, |
| 878 | 944 | } |
| 879 | 945 | }, |
| ... | ... | @@ -1594,6 +1660,24 @@ pub const Parser = struct { |
| 1594 | 1660 | try stack.append(RenderState { .Text = "("}); |
| 1595 | 1661 | try stack.append(RenderState { .Expression = call.callee }); |
| 1596 | 1662 | }, |
| 1663 | ast.Node.Id.ArrayAccess => { |
| 1664 | const arr_access = @fieldParentPtr(ast.NodeArrayAccess, "base", base); |
| 1665 | try stack.append(RenderState { .Text = "]"}); |
| 1666 | try stack.append(RenderState { .Expression = arr_access.index}); |
| 1667 | try stack.append(RenderState { .Text = "["}); |
| 1668 | try stack.append(RenderState { .Expression = arr_access.expr }); |
| 1669 | }, |
| 1670 | ast.Node.Id.SliceExpression => { |
| 1671 | const slice_expr = @fieldParentPtr(ast.NodeSliceExpression, "base", base); |
| 1672 | try stack.append(RenderState { .Text = "]"}); |
| 1673 | if (slice_expr.end) |end| { |
| 1674 | try stack.append(RenderState { .Expression = end}); |
| 1675 | } |
| 1676 | try stack.append(RenderState { .Text = ".."}); |
| 1677 | try stack.append(RenderState { .Expression = slice_expr.start}); |
| 1678 | try stack.append(RenderState { .Text = "["}); |
| 1679 | try stack.append(RenderState { .Expression = slice_expr.expr}); |
| 1680 | }, |
| 1597 | 1681 | ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"), |
| 1598 | 1682 | ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"), |
| 1599 | 1683 | |
| ... | ... | @@ -1978,6 +2062,14 @@ test "zig fmt: indexing" { |
| 1978 | 2062 | \\ a[0 + 5]; |
| 1979 | 2063 | \\ a[0..]; |
| 1980 | 2064 | \\ a[0..5]; |
| 2065 | \\ a[a[0]]; |
| 2066 | \\ a[a[0..]]; |
| 2067 | \\ a[a[0..5]]; |
| 2068 | \\ a[a[0]..]; |
| 2069 | \\ a[a[0..5]..]; |
| 2070 | \\ a[a[0]..a[0]]; |
| 2071 | \\ a[a[0..5]..a[0]]; |
| 2072 | \\ a[a[0..5]..a[0..5]]; |
| 1981 | 2073 | \\} |
| 1982 | 2074 | \\ |
| 1983 | 2075 | ); |