| ... | ... | @@ -104,6 +104,11 @@ pub const Parser = struct { |
| 104 | 104 | ptr: &Token, |
| 105 | 105 | }; |
| 106 | 106 | |
| 107 | const ElseCtx = struct { |
| 108 | payload: ?DestPtr, |
| 109 | body: DestPtr, |
| 110 | }; |
| 111 | |
| 107 | 112 | fn ListSave(comptime T: type) type { |
| 108 | 113 | return struct { |
| 109 | 114 | list: &ArrayList(T), |
| ... | ... | @@ -140,7 +145,7 @@ pub const Parser = struct { |
| 140 | 145 | FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer), |
| 141 | 146 | FieldListCommaOrEnd: &ast.NodeContainerDecl, |
| 142 | 147 | SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase), |
| 143 | | SwitchCaseCapture: &?ast.NodeSwitchCase.Capture, |
| 148 | Payload: DestPtr, |
| 144 | 149 | SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase), |
| 145 | 150 | SwitchCaseItem: &ArrayList(&ast.Node), |
| 146 | 151 | SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node), |
| ... | ... | @@ -635,9 +640,6 @@ pub const Parser = struct { |
| 635 | 640 | Token.Id.Keyword_await => { |
| 636 | 641 | @panic("TODO: await"); |
| 637 | 642 | }, |
| 638 | | Token.Id.Keyword_suspend => { |
| 639 | | @panic("TODO: suspend"); |
| 640 | | }, |
| 641 | 643 | else => { |
| 642 | 644 | self.putBackToken(token); |
| 643 | 645 | stack.append(State { .AssignmentExpressionBegin = dest_ptr }) catch unreachable; |
| ... | ... | @@ -705,21 +707,14 @@ pub const Parser = struct { |
| 705 | 707 | |
| 706 | 708 | stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable; |
| 707 | 709 | try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }); |
| 708 | | |
| 709 | | const next = self.getNextToken(); |
| 710 | | if (next.id != Token.Id.Pipe) { |
| 711 | | self.putBackToken(next); |
| 712 | | continue; |
| 713 | | } |
| 714 | | |
| 715 | | node.op.Catch = try self.createIdentifier(arena, Token(undefined)); |
| 716 | | try stack.append(State { .ExpectToken = Token.Id.Pipe }); |
| 717 | 710 | try stack.append(State { |
| 718 | | .ExpectTokenSave = ExpectTokenSave { |
| 719 | | .id = Token.Id.Identifier, |
| 720 | | .ptr = &(??node.op.Catch).name_token |
| 711 | .Optional = RevertState { |
| 712 | .tokenizer = *self.tokenizer, |
| 713 | .parser = *self, |
| 714 | .ptr = &node.op.Catch, |
| 721 | 715 | } |
| 722 | 716 | }); |
| 717 | try stack.append(State { .Payload = DestPtr { .NullableField = &node.op.Catch } }); |
| 723 | 718 | continue; |
| 724 | 719 | }, |
| 725 | 720 | Token.Id.QuestionMarkQuestionMark => { |
| ... | ... | @@ -1404,12 +1399,25 @@ pub const Parser = struct { |
| 1404 | 1399 | @panic("TODO: inline if"); |
| 1405 | 1400 | }, |
| 1406 | 1401 | Token.Id.Keyword_while => { |
| 1402 | const node = try arena.create(ast.NodeWhile); |
| 1403 | *node = ast.NodeWhile { |
| 1404 | .base = self.initNode(ast.Node.Id.While), |
| 1405 | .while_token = token, |
| 1406 | .condition = undefined, |
| 1407 | .payload = null, |
| 1408 | .continue_expr = null, |
| 1409 | .body = undefined, |
| 1410 | .@"else" = null, |
| 1411 | }; |
| 1412 | dest_ptr.store(&node.base); |
| 1413 | |
| 1407 | 1414 | @panic("TODO: inline while"); |
| 1408 | 1415 | }, |
| 1409 | 1416 | Token.Id.Keyword_for => { |
| 1410 | 1417 | @panic("TODO: inline for"); |
| 1411 | 1418 | }, |
| 1412 | 1419 | Token.Id.Keyword_switch => { |
| 1420 | @breakpoint(); |
| 1413 | 1421 | const node = try arena.create(ast.NodeSwitch); |
| 1414 | 1422 | *node = ast.NodeSwitch { |
| 1415 | 1423 | .base = self.initNode(ast.Node.Id.Switch), |
| ... | ... | @@ -1434,9 +1442,6 @@ pub const Parser = struct { |
| 1434 | 1442 | Token.Id.Keyword_comptime => { |
| 1435 | 1443 | @panic("TODO: inline comptime"); |
| 1436 | 1444 | }, |
| 1437 | | Token.Id.Keyword_suspend => { |
| 1438 | | @panic("TODO: inline suspend"); |
| 1439 | | }, |
| 1440 | 1445 | else => { |
| 1441 | 1446 | try self.parseError(&stack, token, "expected primary expression, found {}", @tagName(token.id)); |
| 1442 | 1447 | continue; |
| ... | ... | @@ -1547,13 +1552,21 @@ pub const Parser = struct { |
| 1547 | 1552 | *node = ast.NodeSwitchCase { |
| 1548 | 1553 | .base = self.initNode(ast.Node.Id.SwitchCase), |
| 1549 | 1554 | .items = ArrayList(&ast.Node).init(arena), |
| 1550 | | .capture = null, |
| 1555 | .payload = null, |
| 1551 | 1556 | .expr = undefined, |
| 1552 | 1557 | }; |
| 1553 | 1558 | try list_state.list.append(node); |
| 1554 | 1559 | stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable; |
| 1555 | 1560 | try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } }); |
| 1556 | | try stack.append(State { .SwitchCaseCapture = &node.capture }); |
| 1561 | try stack.append(State { |
| 1562 | .Optional = RevertState { |
| 1563 | .tokenizer = *self.tokenizer, |
| 1564 | .parser = *self, |
| 1565 | .ptr = &node.payload, |
| 1566 | } |
| 1567 | }); |
| 1568 | try stack.append(State { .Payload = DestPtr { .NullableField = &node.payload } }); |
| 1569 | try stack.append(State.Required); |
| 1557 | 1570 | |
| 1558 | 1571 | const maybe_else = self.getNextToken(); |
| 1559 | 1572 | if (maybe_else.id == Token.Id.Keyword_else) { |
| ... | ... | @@ -1572,12 +1585,8 @@ pub const Parser = struct { |
| 1572 | 1585 | } |
| 1573 | 1586 | }, |
| 1574 | 1587 | |
| 1575 | | State.SwitchCaseCapture => |capture| { |
| 1576 | | const token = self.getNextToken(); |
| 1577 | | if (token.id != Token.Id.Pipe) { |
| 1578 | | self.putBackToken(token); |
| 1579 | | continue; |
| 1580 | | } |
| 1588 | State.Payload => |dest_ptr| { |
| 1589 | const lpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; |
| 1581 | 1590 | |
| 1582 | 1591 | const is_ptr = blk: { |
| 1583 | 1592 | const asterik = self.getNextToken(); |
| ... | ... | @@ -1590,11 +1599,16 @@ pub const Parser = struct { |
| 1590 | 1599 | }; |
| 1591 | 1600 | |
| 1592 | 1601 | const ident = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; |
| 1593 | | _ = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; |
| 1594 | | *capture = ast.NodeSwitchCase.Capture { |
| 1602 | const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; |
| 1603 | const node = try arena.create(ast.NodePayload); |
| 1604 | *node = ast.NodePayload { |
| 1605 | .base = self.initNode(ast.Node.Id.Payload), |
| 1606 | .lpipe = lpipe, |
| 1607 | .is_ptr = is_ptr, |
| 1595 | 1608 | .symbol = try self.createIdentifier(arena, ident), |
| 1596 | | .is_ptr = is_ptr |
| 1609 | .rpipe = rpipe |
| 1597 | 1610 | }; |
| 1611 | dest_ptr.store(&node.base); |
| 1598 | 1612 | }, |
| 1599 | 1613 | |
| 1600 | 1614 | State.SwitchCaseItem => |case_items| { |
| ... | ... | @@ -1856,6 +1870,8 @@ pub const Parser = struct { |
| 1856 | 1870 | stack.append(State { .Block = inner_block }) catch unreachable; |
| 1857 | 1871 | continue; |
| 1858 | 1872 | }, |
| 1873 | Token.Id.Keyword_suspend, Token.Id.Keyword_if, |
| 1874 | Token.Id.Keyword_while, Token.Id.Keyword_for, |
| 1859 | 1875 | Token.Id.Keyword_switch => { |
| 1860 | 1876 | self.putBackToken(next); |
| 1861 | 1877 | stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } }) catch unreachable; |
| ... | ... | @@ -2572,9 +2588,8 @@ pub const Parser = struct { |
| 2572 | 2588 | |
| 2573 | 2589 | if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) { |
| 2574 | 2590 | if (prefix_op_node.op.Catch) |payload| { |
| 2575 | | try stack.append(RenderState { .Text = "| " }); |
| 2576 | | try stack.append(RenderState { .Expression = &payload.base }); |
| 2577 | | try stack.append(RenderState { .Text = "|" }); |
| 2591 | try stack.append(RenderState { .Text = " " }); |
| 2592 | try stack.append(RenderState { .Expression = payload }); |
| 2578 | 2593 | } |
| 2579 | 2594 | try stack.append(RenderState { .Text = " catch " }); |
| 2580 | 2595 | } else { |
| ... | ... | @@ -2764,6 +2779,17 @@ pub const Parser = struct { |
| 2764 | 2779 | try stack.append(RenderState { .Expression = rhs }); |
| 2765 | 2780 | } |
| 2766 | 2781 | }, |
| 2782 | ast.Node.Id.Payload => { |
| 2783 | const payload = @fieldParentPtr(ast.NodePayload, "base", base); |
| 2784 | try stack.append(RenderState { .Text = "|"}); |
| 2785 | try stack.append(RenderState { .Expression = &payload.symbol.base }); |
| 2786 | |
| 2787 | if (payload.is_ptr) { |
| 2788 | try stack.append(RenderState { .Text = "*"}); |
| 2789 | } |
| 2790 | |
| 2791 | try stack.append(RenderState { .Text = "|"}); |
| 2792 | }, |
| 2767 | 2793 | ast.Node.Id.GroupedExpression => { |
| 2768 | 2794 | const grouped_expr = @fieldParentPtr(ast.NodeGroupedExpression, "base", base); |
| 2769 | 2795 | try stack.append(RenderState { .Text = ")"}); |
| ... | ... | @@ -2985,14 +3011,9 @@ pub const Parser = struct { |
| 2985 | 3011 | const switch_case = @fieldParentPtr(ast.NodeSwitchCase, "base", base); |
| 2986 | 3012 | |
| 2987 | 3013 | try stack.append(RenderState { .Expression = switch_case.expr }); |
| 2988 | | if (switch_case.capture) |capture| { |
| 2989 | | try stack.append(RenderState { .Text = "| "}); |
| 2990 | | try stack.append(RenderState { .Expression = &capture.symbol.base }); |
| 2991 | | |
| 2992 | | if (capture.is_ptr) { |
| 2993 | | try stack.append(RenderState { .Text = "*"}); |
| 2994 | | } |
| 2995 | | try stack.append(RenderState { .Text = "|"}); |
| 3014 | if (switch_case.payload) |payload| { |
| 3015 | try stack.append(RenderState { .Text = " " }); |
| 3016 | try stack.append(RenderState { .Expression = payload }); |
| 2996 | 3017 | } |
| 2997 | 3018 | try stack.append(RenderState { .Text = " => "}); |
| 2998 | 3019 | |
| ... | ... | @@ -3011,6 +3032,7 @@ pub const Parser = struct { |
| 3011 | 3032 | const switch_else = @fieldParentPtr(ast.NodeSwitchElse, "base", base); |
| 3012 | 3033 | try stream.print("{}", self.tokenizer.getTokenSlice(switch_else.token)); |
| 3013 | 3034 | }, |
| 3035 | ast.Node.Id.While => @panic("TODO: Render while"), |
| 3014 | 3036 | |
| 3015 | 3037 | ast.Node.Id.StructField, |
| 3016 | 3038 | ast.Node.Id.UnionTag, |