| ... | ... | @@ -89,6 +89,15 @@ pub const Parser = struct { |
| 89 | 89 | ptr: &Token, |
| 90 | 90 | }; |
| 91 | 91 | |
| 92 | const RevertState = struct { |
| 93 | parser: Parser, |
| 94 | tokenizer: Tokenizer, |
| 95 | |
| 96 | // We expect, that if something is optional, then there is a field, |
| 97 | // that needs to be set to null, when we revert. |
| 98 | ptr: &?&ast.Node, |
| 99 | }; |
| 100 | |
| 92 | 101 | fn ListState(comptime T: type) type { |
| 93 | 102 | return struct { |
| 94 | 103 | list: &ArrayList(T), |
| ... | ... | @@ -131,7 +140,7 @@ pub const Parser = struct { |
| 131 | 140 | /// optional state is found, the parser will revert to the state it was in |
| 132 | 141 | /// when the optional was added. This will polute the arena allocator with |
| 133 | 142 | /// "leaked" nodes. TODO: Figure out if it's nessesary to handle leaked nodes. |
| 134 | | Optional: Parser, |
| 143 | Optional: RevertState, |
| 135 | 144 | |
| 136 | 145 | /// Optional can be reverted by adding the Required state to the stack. |
| 137 | 146 | Required, |
| ... | ... | @@ -598,7 +607,13 @@ pub const Parser = struct { |
| 598 | 607 | const node = try self.createControlFlowExpr(arena, token, ast.NodeControlFlowExpression.Kind.Return); |
| 599 | 608 | dest_ptr.store(&node.base); |
| 600 | 609 | |
| 601 | | stack.append(State { .Optional = *self }) catch unreachable; |
| 610 | stack.append(State { |
| 611 | .Optional = RevertState { |
| 612 | .parser = *self, |
| 613 | .tokenizer = *self.tokenizer, |
| 614 | .ptr = &node.rhs, |
| 615 | } |
| 616 | }) catch unreachable; |
| 602 | 617 | try stack.append(State { .Expression = DestPtr { .NullableField = &node.rhs } }); |
| 603 | 618 | continue; |
| 604 | 619 | }, |
| ... | ... | @@ -673,7 +688,7 @@ pub const Parser = struct { |
| 673 | 688 | continue; |
| 674 | 689 | } |
| 675 | 690 | |
| 676 | | node.op.Catch = try self.createIdentifier(arena, undefined); |
| 691 | node.op.Catch = try self.createIdentifier(arena, Token(undefined)); |
| 677 | 692 | try stack.append(State { .ExpectToken = Token.Id.Pipe }); |
| 678 | 693 | try stack.append(State { |
| 679 | 694 | .ExpectTokenSave = ExpectTokenSave { |
| ... | ... | @@ -1910,7 +1925,7 @@ pub const Parser = struct { |
| 1910 | 1925 | .base = self.initNode(ast.Node.Id.ControlFlowExpression), |
| 1911 | 1926 | .ltoken = *ltoken, |
| 1912 | 1927 | .kind = *kind, |
| 1913 | | .rhs = undefined, |
| 1928 | .rhs = null, |
| 1914 | 1929 | }; |
| 1915 | 1930 | return node; |
| 1916 | 1931 | } |
| ... | ... | @@ -2067,7 +2082,9 @@ pub const Parser = struct { |
| 2067 | 2082 | while (stack.popOrNull()) |state| { |
| 2068 | 2083 | switch (state) { |
| 2069 | 2084 | State.Optional => |revert| { |
| 2070 | | *self = state.Optional; |
| 2085 | *self = revert.parser; |
| 2086 | *self.tokenizer = revert.tokenizer; |
| 2087 | *revert.ptr = null; |
| 2071 | 2088 | return; |
| 2072 | 2089 | }, |
| 2073 | 2090 | State.Required => { |
| ... | ... | @@ -2359,7 +2376,7 @@ pub const Parser = struct { |
| 2359 | 2376 | |
| 2360 | 2377 | if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) { |
| 2361 | 2378 | if (prefix_op_node.op.Catch) |payload| { |
| 2362 | | try stack.append(RenderState { .Text = "|" }); |
| 2379 | try stack.append(RenderState { .Text = "| " }); |
| 2363 | 2380 | try stack.append(RenderState { .Expression = &payload.base }); |
| 2364 | 2381 | try stack.append(RenderState { .Text = "|" }); |
| 2365 | 2382 | } |
| ... | ... | @@ -2956,6 +2973,10 @@ test "zig fmt: return" { |
| 2956 | 2973 | \\ return 0; |
| 2957 | 2974 | \\} |
| 2958 | 2975 | \\ |
| 2976 | \\fn bar() void { |
| 2977 | \\ return; |
| 2978 | \\} |
| 2979 | \\ |
| 2959 | 2980 | ); |
| 2960 | 2981 | } |
| 2961 | 2982 | |