| ... | @@ -116,6 +116,24 @@ pub const Parser = struct { | ... | @@ -116,6 +116,24 @@ pub const Parser = struct { |
| 116 | }; | 116 | }; |
| 117 | } | 117 | } |
| 118 | | 118 | |
| | 119 | const LabelCtx = struct { |
| | 120 | label: ?Token, |
| | 121 | dest_ptr: DestPtr, |
| | 122 | }; |
| | 123 | |
| | 124 | const InlineCtx = struct { |
| | 125 | label: ?Token, |
| | 126 | inline_token: ?Token, |
| | 127 | dest_ptr: DestPtr, |
| | 128 | }; |
| | 129 | |
| | 130 | const LoopCtx = struct { |
| | 131 | label: ?Token, |
| | 132 | inline_token: ?Token, |
| | 133 | loop_token: Token, |
| | 134 | dest_ptr: DestPtr, |
| | 135 | }; |
| | 136 | |
| 119 | const State = union(enum) { | 137 | const State = union(enum) { |
| 120 | TopLevel, | 138 | TopLevel, |
| 121 | TopLevelExtern: TopLevelDeclCtx, | 139 | TopLevelExtern: TopLevelDeclCtx, |
| ... | @@ -137,15 +155,22 @@ pub const Parser = struct { | ... | @@ -137,15 +155,22 @@ pub const Parser = struct { |
| 137 | ParamDecl: &ast.NodeFnProto, | 155 | ParamDecl: &ast.NodeFnProto, |
| 138 | ParamDeclComma, | 156 | ParamDeclComma, |
| 139 | FnDef: &ast.NodeFnProto, | 157 | FnDef: &ast.NodeFnProto, |
| | 158 | LabeledExpression: LabelCtx, |
| | 159 | Inline: InlineCtx, |
| | 160 | While: LoopCtx, |
| | 161 | For: LoopCtx, |
| 140 | Block: &ast.NodeBlock, | 162 | Block: &ast.NodeBlock, |
| | 163 | Else: &?&ast.NodeElse, |
| | 164 | WhileContinueExpr: &?&ast.Node, |
| 141 | Statement: &ast.NodeBlock, | 165 | Statement: &ast.NodeBlock, |
| | 166 | Semicolon: &const &const ast.Node, |
| 142 | ExprListItemOrEnd: ExprListCtx, | 167 | ExprListItemOrEnd: ExprListCtx, |
| 143 | ExprListCommaOrEnd: ExprListCtx, | 168 | ExprListCommaOrEnd: ExprListCtx, |
| 144 | FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer), | 169 | FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer), |
| 145 | FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer), | 170 | FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer), |
| 146 | FieldListCommaOrEnd: &ast.NodeContainerDecl, | 171 | FieldListCommaOrEnd: &ast.NodeContainerDecl, |
| 147 | SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase), | 172 | SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase), |
| 148 | Payload: DestPtr, | 173 | Payload: &?&ast.NodePayload, |
| 149 | SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase), | 174 | SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase), |
| 150 | SwitchCaseItem: &ArrayList(&ast.Node), | 175 | SwitchCaseItem: &ArrayList(&ast.Node), |
| 151 | SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node), | 176 | SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node), |
| ... | @@ -157,9 +182,6 @@ pub const Parser = struct { | ... | @@ -157,9 +182,6 @@ pub const Parser = struct { |
| 157 | /// "leaked" nodes. TODO: Figure out if it's nessesary to handle leaked nodes. | 182 | /// "leaked" nodes. TODO: Figure out if it's nessesary to handle leaked nodes. |
| 158 | Optional: RevertState, | 183 | Optional: RevertState, |
| 159 | | 184 | |
| 160 | /// Optional can be reverted by adding the Required state to the stack. | | |
| 161 | Required, | | |
| 162 | | | |
| 163 | Expression: DestPtr, | 185 | Expression: DestPtr, |
| 164 | RangeExpressionBegin: DestPtr, | 186 | RangeExpressionBegin: DestPtr, |
| 165 | RangeExpressionEnd: DestPtr, | 187 | RangeExpressionEnd: DestPtr, |
| ... | @@ -598,8 +620,7 @@ pub const Parser = struct { | ... | @@ -598,8 +620,7 @@ pub const Parser = struct { |
| 598 | continue; | 620 | continue; |
| 599 | }, | 621 | }, |
| 600 | | 622 | |
| 601 | State.Optional, | 623 | State.Optional => { }, |
| 602 | State.Required => { }, | | |
| 603 | | 624 | |
| 604 | State.Expression => |dest_ptr| { | 625 | State.Expression => |dest_ptr| { |
| 605 | const token = self.getNextToken(); | 626 | const token = self.getNextToken(); |
| ... | @@ -626,10 +647,51 @@ pub const Parser = struct { | ... | @@ -626,10 +647,51 @@ pub const Parser = struct { |
| 626 | continue; | 647 | continue; |
| 627 | }, | 648 | }, |
| 628 | Token.Id.Keyword_break => { | 649 | Token.Id.Keyword_break => { |
| 629 | @panic("TODO: break"); | 650 | const label = blk: { |
| | 651 | const colon = self.getNextToken(); |
| | 652 | if (colon.id != Token.Id.Colon) { |
| | 653 | self.putBackToken(colon); |
| | 654 | break :blk null; |
| | 655 | } |
| | 656 | |
| | 657 | break :blk (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; |
| | 658 | }; |
| | 659 | |
| | 660 | const node = try self.createControlFlowExpr(arena, token, |
| | 661 | ast.NodeControlFlowExpression.Kind { |
| | 662 | .Break = label, |
| | 663 | } |
| | 664 | ); |
| | 665 | dest_ptr.store(&node.base); |
| | 666 | |
| | 667 | stack.append(State { |
| | 668 | .Optional = RevertState { |
| | 669 | .parser = *self, |
| | 670 | .tokenizer = *self.tokenizer, |
| | 671 | .ptr = &node.rhs, |
| | 672 | } |
| | 673 | }) catch unreachable; |
| | 674 | try stack.append(State { .Expression = DestPtr { .NullableField = &node.rhs } }); |
| | 675 | continue; |
| 630 | }, | 676 | }, |
| 631 | Token.Id.Keyword_continue => { | 677 | Token.Id.Keyword_continue => { |
| 632 | @panic("TODO: break"); | 678 | const label = blk: { |
| | 679 | const colon = self.getNextToken(); |
| | 680 | if (colon.id != Token.Id.Colon) { |
| | 681 | self.putBackToken(colon); |
| | 682 | break :blk null; |
| | 683 | } |
| | 684 | |
| | 685 | break :blk (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; |
| | 686 | }; |
| | 687 | |
| | 688 | const node = try self.createControlFlowExpr(arena, token, |
| | 689 | ast.NodeControlFlowExpression.Kind { |
| | 690 | .Continue = label, |
| | 691 | } |
| | 692 | ); |
| | 693 | dest_ptr.store(&node.base); |
| | 694 | continue; |
| 633 | }, | 695 | }, |
| 634 | Token.Id.Keyword_cancel => { | 696 | Token.Id.Keyword_cancel => { |
| 635 | @panic("TODO: cancel"); | 697 | @panic("TODO: cancel"); |
| ... | @@ -707,14 +769,7 @@ pub const Parser = struct { | ... | @@ -707,14 +769,7 @@ pub const Parser = struct { |
| 707 | | 769 | |
| 708 | stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable; | 770 | stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable; |
| 709 | try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }); | 771 | try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }); |
| 710 | try stack.append(State { | 772 | try stack.append(State { .Payload = &node.op.Catch }); |
| 711 | .Optional = RevertState { | | |
| 712 | .tokenizer = *self.tokenizer, | | |
| 713 | .parser = *self, | | |
| 714 | .ptr = &node.op.Catch, | | |
| 715 | } | | |
| 716 | }); | | |
| 717 | try stack.append(State { .Payload = DestPtr { .NullableField = &node.op.Catch } }); | | |
| 718 | continue; | 773 | continue; |
| 719 | }, | 774 | }, |
| 720 | Token.Id.QuestionMarkQuestionMark => { | 775 | Token.Id.QuestionMarkQuestionMark => { |
| ... | @@ -1370,16 +1425,12 @@ pub const Parser = struct { | ... | @@ -1370,16 +1425,12 @@ pub const Parser = struct { |
| 1370 | continue; | 1425 | continue; |
| 1371 | } | 1426 | } |
| 1372 | | 1427 | |
| 1373 | const block = try self.createBlock(arena, (?Token)(token), Token(undefined)); | 1428 | stack.append(State { |
| 1374 | dest_ptr.store(&block.base); | 1429 | .LabeledExpression = LabelCtx { |
| 1375 | | 1430 | .label = token, |
| 1376 | stack.append(State { .Block = block }) catch unreachable; | 1431 | .dest_ptr = dest_ptr |
| 1377 | try stack.append(State { | | |
| 1378 | .ExpectTokenSave = ExpectTokenSave { | | |
| 1379 | .id = Token.Id.LBrace, | | |
| 1380 | .ptr = &block.lbrace, | | |
| 1381 | } | 1432 | } |
| 1382 | }); | 1433 | }) catch unreachable; |
| 1383 | continue; | 1434 | continue; |
| 1384 | }, | 1435 | }, |
| 1385 | Token.Id.LBrace => { | 1436 | Token.Id.LBrace => { |
| ... | @@ -1398,26 +1449,31 @@ pub const Parser = struct { | ... | @@ -1398,26 +1449,31 @@ pub const Parser = struct { |
| 1398 | Token.Id.Keyword_if => { | 1449 | Token.Id.Keyword_if => { |
| 1399 | @panic("TODO: inline if"); | 1450 | @panic("TODO: inline if"); |
| 1400 | }, | 1451 | }, |
| | 1452 | Token.Id.Keyword_inline => { |
| | 1453 | stack.append(State { |
| | 1454 | .Inline = InlineCtx { |
| | 1455 | .label = null, |
| | 1456 | .inline_token = token, |
| | 1457 | .dest_ptr = dest_ptr, |
| | 1458 | } |
| | 1459 | }) catch unreachable; |
| | 1460 | continue; |
| | 1461 | }, |
| 1401 | Token.Id.Keyword_while => { | 1462 | Token.Id.Keyword_while => { |
| 1402 | const node = try arena.create(ast.NodeWhile); | 1463 | stack.append(State { |
| 1403 | *node = ast.NodeWhile { | 1464 | .While = LoopCtx { |
| 1404 | .base = self.initNode(ast.Node.Id.While), | 1465 | .label = null, |
| 1405 | .while_token = token, | 1466 | .inline_token = null, |
| 1406 | .condition = undefined, | 1467 | .loop_token = token, |
| 1407 | .payload = null, | 1468 | .dest_ptr = dest_ptr, |
| 1408 | .continue_expr = null, | 1469 | } |
| 1409 | .body = undefined, | 1470 | }) catch unreachable; |
| 1410 | .@"else" = null, | 1471 | continue; |
| 1411 | }; | | |
| 1412 | dest_ptr.store(&node.base); | | |
| 1413 | | | |
| 1414 | @panic("TODO: inline while"); | | |
| 1415 | }, | 1472 | }, |
| 1416 | Token.Id.Keyword_for => { | 1473 | Token.Id.Keyword_for => { |
| 1417 | @panic("TODO: inline for"); | 1474 | @panic("TODO: inline for"); |
| 1418 | }, | 1475 | }, |
| 1419 | Token.Id.Keyword_switch => { | 1476 | Token.Id.Keyword_switch => { |
| 1420 | @breakpoint(); | | |
| 1421 | const node = try arena.create(ast.NodeSwitch); | 1477 | const node = try arena.create(ast.NodeSwitch); |
| 1422 | *node = ast.NodeSwitch { | 1478 | *node = ast.NodeSwitch { |
| 1423 | .base = self.initNode(ast.Node.Id.Switch), | 1479 | .base = self.initNode(ast.Node.Id.Switch), |
| ... | @@ -1558,15 +1614,7 @@ pub const Parser = struct { | ... | @@ -1558,15 +1614,7 @@ pub const Parser = struct { |
| 1558 | try list_state.list.append(node); | 1614 | try list_state.list.append(node); |
| 1559 | stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable; | 1615 | stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable; |
| 1560 | try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } }); | 1616 | try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } }); |
| 1561 | try stack.append(State { | 1617 | try stack.append(State { .Payload = &node.payload }); |
| 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); | | |
| 1570 | | 1618 | |
| 1571 | const maybe_else = self.getNextToken(); | 1619 | const maybe_else = self.getNextToken(); |
| 1572 | if (maybe_else.id == Token.Id.Keyword_else) { | 1620 | if (maybe_else.id == Token.Id.Keyword_else) { |
| ... | @@ -1585,32 +1633,6 @@ pub const Parser = struct { | ... | @@ -1585,32 +1633,6 @@ pub const Parser = struct { |
| 1585 | } | 1633 | } |
| 1586 | }, | 1634 | }, |
| 1587 | | 1635 | |
| 1588 | State.Payload => |dest_ptr| { | | |
| 1589 | const lpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; | | |
| 1590 | | | |
| 1591 | const is_ptr = blk: { | | |
| 1592 | const asterik = self.getNextToken(); | | |
| 1593 | if (asterik.id == Token.Id.Asterisk) { | | |
| 1594 | break :blk true; | | |
| 1595 | } else { | | |
| 1596 | self.putBackToken(asterik); | | |
| 1597 | break :blk false; | | |
| 1598 | } | | |
| 1599 | }; | | |
| 1600 | | | |
| 1601 | const ident = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; | | |
| 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, | | |
| 1608 | .symbol = try self.createIdentifier(arena, ident), | | |
| 1609 | .rpipe = rpipe | | |
| 1610 | }; | | |
| 1611 | dest_ptr.store(&node.base); | | |
| 1612 | }, | | |
| 1613 | | | |
| 1614 | State.SwitchCaseItem => |case_items| { | 1636 | State.SwitchCaseItem => |case_items| { |
| 1615 | stack.append(State { .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable; | 1637 | stack.append(State { .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable; |
| 1616 | try stack.append(State { .RangeExpressionBegin = DestPtr{ .Field = try case_items.addOne() } }); | 1638 | try stack.append(State { .RangeExpressionBegin = DestPtr{ .Field = try case_items.addOne() } }); |
| ... | @@ -1642,6 +1664,68 @@ pub const Parser = struct { | ... | @@ -1642,6 +1664,68 @@ pub const Parser = struct { |
| 1642 | continue; | 1664 | continue; |
| 1643 | }, | 1665 | }, |
| 1644 | | 1666 | |
| | 1667 | State.Else => |dest| { |
| | 1668 | const else_token = self.getNextToken(); |
| | 1669 | if (else_token.id != Token.Id.Keyword_else) { |
| | 1670 | self.putBackToken(else_token); |
| | 1671 | continue; |
| | 1672 | } |
| | 1673 | |
| | 1674 | const node = try arena.create(ast.NodeElse); |
| | 1675 | *node = ast.NodeElse { |
| | 1676 | .base = self.initNode(ast.Node.Id.Else), |
| | 1677 | .else_token = else_token, |
| | 1678 | .payload = null, |
| | 1679 | .body = undefined, |
| | 1680 | }; |
| | 1681 | *dest = node; |
| | 1682 | |
| | 1683 | stack.append(State { .Expression = DestPtr { .Field = &node.body } }) catch unreachable; |
| | 1684 | try stack.append(State { .Payload = &node.payload }); |
| | 1685 | }, |
| | 1686 | |
| | 1687 | State.WhileContinueExpr => |dest| { |
| | 1688 | const colon = self.getNextToken(); |
| | 1689 | if (colon.id != Token.Id.Colon) { |
| | 1690 | self.putBackToken(colon); |
| | 1691 | continue; |
| | 1692 | } |
| | 1693 | |
| | 1694 | _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue; |
| | 1695 | stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable; |
| | 1696 | try stack.append(State { .Expression = DestPtr { .NullableField = dest } }); |
| | 1697 | }, |
| | 1698 | |
| | 1699 | State.Payload => |dest| { |
| | 1700 | const lpipe = self.getNextToken(); |
| | 1701 | if (lpipe.id != Token.Id.Pipe) { |
| | 1702 | self.putBackToken(lpipe); |
| | 1703 | continue; |
| | 1704 | } |
| | 1705 | |
| | 1706 | const is_ptr = blk: { |
| | 1707 | const asterik = self.getNextToken(); |
| | 1708 | if (asterik.id == Token.Id.Asterisk) { |
| | 1709 | break :blk true; |
| | 1710 | } else { |
| | 1711 | self.putBackToken(asterik); |
| | 1712 | break :blk false; |
| | 1713 | } |
| | 1714 | }; |
| | 1715 | |
| | 1716 | const ident = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; |
| | 1717 | const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; |
| | 1718 | const node = try arena.create(ast.NodePayload); |
| | 1719 | *node = ast.NodePayload { |
| | 1720 | .base = self.initNode(ast.Node.Id.Payload), |
| | 1721 | .lpipe = lpipe, |
| | 1722 | .is_ptr = is_ptr, |
| | 1723 | .symbol = try self.createIdentifier(arena, ident), |
| | 1724 | .rpipe = rpipe |
| | 1725 | }; |
| | 1726 | *dest = node; |
| | 1727 | }, |
| | 1728 | |
| 1645 | State.AddrOfModifiers => |addr_of_info| { | 1729 | State.AddrOfModifiers => |addr_of_info| { |
| 1646 | var token = self.getNextToken(); | 1730 | var token = self.getNextToken(); |
| 1647 | switch (token.id) { | 1731 | switch (token.id) { |
| ... | @@ -1803,6 +1887,114 @@ pub const Parser = struct { | ... | @@ -1803,6 +1887,114 @@ pub const Parser = struct { |
| 1803 | } | 1887 | } |
| 1804 | }, | 1888 | }, |
| 1805 | | 1889 | |
| | 1890 | State.LabeledExpression => |ctx| { |
| | 1891 | const token = self.getNextToken(); |
| | 1892 | switch (token.id) { |
| | 1893 | Token.Id.LBrace => { |
| | 1894 | const block = try self.createBlock(arena, (?Token)(ctx.label), token); |
| | 1895 | ctx.dest_ptr.store(&block.base); |
| | 1896 | |
| | 1897 | stack.append(State { .Block = block }) catch unreachable; |
| | 1898 | continue; |
| | 1899 | }, |
| | 1900 | Token.Id.Keyword_while => { |
| | 1901 | stack.append(State { |
| | 1902 | .While = LoopCtx { |
| | 1903 | .label = ctx.label, |
| | 1904 | .inline_token = null, |
| | 1905 | .loop_token = token, |
| | 1906 | .dest_ptr = ctx.dest_ptr, |
| | 1907 | } |
| | 1908 | }) catch unreachable; |
| | 1909 | continue; |
| | 1910 | }, |
| | 1911 | Token.Id.Keyword_for => { |
| | 1912 | stack.append(State { |
| | 1913 | .For = LoopCtx { |
| | 1914 | .label = ctx.label, |
| | 1915 | .inline_token = null, |
| | 1916 | .loop_token = token, |
| | 1917 | .dest_ptr = ctx.dest_ptr, |
| | 1918 | } |
| | 1919 | }) catch unreachable; |
| | 1920 | continue; |
| | 1921 | }, |
| | 1922 | Token.Id.Keyword_inline => { |
| | 1923 | stack.append(State { |
| | 1924 | .Inline = InlineCtx { |
| | 1925 | .label = ctx.label, |
| | 1926 | .inline_token = token, |
| | 1927 | .dest_ptr = ctx.dest_ptr, |
| | 1928 | } |
| | 1929 | }) catch unreachable; |
| | 1930 | continue; |
| | 1931 | }, |
| | 1932 | else => { |
| | 1933 | try self.parseError(&stack, token, "expected 'while', 'for', 'inline' or '{{', found {}", @tagName(token.id)); |
| | 1934 | continue; |
| | 1935 | }, |
| | 1936 | } |
| | 1937 | }, |
| | 1938 | |
| | 1939 | State.Inline => |ctx| { |
| | 1940 | const token = self.getNextToken(); |
| | 1941 | switch (token.id) { |
| | 1942 | Token.Id.Keyword_while => { |
| | 1943 | stack.append(State { |
| | 1944 | .While = LoopCtx { |
| | 1945 | .inline_token = ctx.inline_token, |
| | 1946 | .label = ctx.label, |
| | 1947 | .loop_token = token, |
| | 1948 | .dest_ptr = ctx.dest_ptr, |
| | 1949 | } |
| | 1950 | }) catch unreachable; |
| | 1951 | continue; |
| | 1952 | }, |
| | 1953 | Token.Id.Keyword_for => { |
| | 1954 | stack.append(State { |
| | 1955 | .For = LoopCtx { |
| | 1956 | .inline_token = ctx.inline_token, |
| | 1957 | .label = ctx.label, |
| | 1958 | .loop_token = token, |
| | 1959 | .dest_ptr = ctx.dest_ptr, |
| | 1960 | } |
| | 1961 | }) catch unreachable; |
| | 1962 | continue; |
| | 1963 | }, |
| | 1964 | else => { |
| | 1965 | try self.parseError(&stack, token, "expected 'while' or 'for', found {}", @tagName(token.id)); |
| | 1966 | continue; |
| | 1967 | }, |
| | 1968 | } |
| | 1969 | }, |
| | 1970 | |
| | 1971 | State.While => |ctx| { |
| | 1972 | const node = try arena.create(ast.NodeWhile); |
| | 1973 | *node = ast.NodeWhile { |
| | 1974 | .base = self.initNode(ast.Node.Id.While), |
| | 1975 | .label = ctx.label, |
| | 1976 | .inline_token = ctx.inline_token, |
| | 1977 | .while_token = ctx.loop_token, |
| | 1978 | .condition = undefined, |
| | 1979 | .payload = null, |
| | 1980 | .continue_expr = null, |
| | 1981 | .body = undefined, |
| | 1982 | .@"else" = null, |
| | 1983 | }; |
| | 1984 | ctx.dest_ptr.store(&node.base); |
| | 1985 | |
| | 1986 | stack.append(State { .Else = &node.@"else" }) catch unreachable; |
| | 1987 | try stack.append(State { .Expression = DestPtr { .Field = &node.body } }); |
| | 1988 | try stack.append(State { .WhileContinueExpr = &node.continue_expr }); |
| | 1989 | try stack.append(State { .Payload = &node.payload }); |
| | 1990 | try stack.append(State { .ExpectToken = Token.Id.RParen }); |
| | 1991 | try stack.append(State { .Expression = DestPtr { .Field = &node.condition } }); |
| | 1992 | try stack.append(State { .ExpectToken = Token.Id.LParen }); |
| | 1993 | }, |
| | 1994 | |
| | 1995 | State.For => |ctx| { |
| | 1996 | }, |
| | 1997 | |
| 1806 | State.Block => |block| { | 1998 | State.Block => |block| { |
| 1807 | const token = self.getNextToken(); | 1999 | const token = self.getNextToken(); |
| 1808 | switch (token.id) { | 2000 | switch (token.id) { |
| ... | @@ -1841,28 +2033,6 @@ pub const Parser = struct { | ... | @@ -1841,28 +2033,6 @@ pub const Parser = struct { |
| 1841 | stack.append(State { .VarDecl = var_decl }) catch unreachable; | 2033 | stack.append(State { .VarDecl = var_decl }) catch unreachable; |
| 1842 | continue; | 2034 | continue; |
| 1843 | }, | 2035 | }, |
| 1844 | Token.Id.Identifier => { | | |
| 1845 | const maybe_colon = self.getNextToken(); | | |
| 1846 | if (maybe_colon.id != Token.Id.Colon) { | | |
| 1847 | self.putBackToken(maybe_colon); | | |
| 1848 | self.putBackToken(next); | | |
| 1849 | stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable; | | |
| 1850 | try stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } }); | | |
| 1851 | continue; | | |
| 1852 | } | | |
| 1853 | | | |
| 1854 | const inner_block = try self.createBlock(arena, (?Token)(next), Token(undefined)); | | |
| 1855 | try block.statements.append(&inner_block.base); | | |
| 1856 | | | |
| 1857 | stack.append(State { .Block = inner_block }) catch unreachable; | | |
| 1858 | try stack.append(State { | | |
| 1859 | .ExpectTokenSave = ExpectTokenSave { | | |
| 1860 | .id = Token.Id.LBrace, | | |
| 1861 | .ptr = &inner_block.lbrace, | | |
| 1862 | } | | |
| 1863 | }); | | |
| 1864 | continue; | | |
| 1865 | }, | | |
| 1866 | Token.Id.LBrace => { | 2036 | Token.Id.LBrace => { |
| 1867 | const inner_block = try self.createBlock(arena, (?Token)(null), next); | 2037 | const inner_block = try self.createBlock(arena, (?Token)(null), next); |
| 1868 | try block.statements.append(&inner_block.base); | 2038 | try block.statements.append(&inner_block.base); |
| ... | @@ -1870,22 +2040,53 @@ pub const Parser = struct { | ... | @@ -1870,22 +2040,53 @@ pub const Parser = struct { |
| 1870 | stack.append(State { .Block = inner_block }) catch unreachable; | 2040 | stack.append(State { .Block = inner_block }) catch unreachable; |
| 1871 | continue; | 2041 | continue; |
| 1872 | }, | 2042 | }, |
| 1873 | Token.Id.Keyword_suspend, Token.Id.Keyword_if, | | |
| 1874 | Token.Id.Keyword_while, Token.Id.Keyword_for, | | |
| 1875 | Token.Id.Keyword_switch => { | | |
| 1876 | self.putBackToken(next); | | |
| 1877 | stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } }) catch unreachable; | | |
| 1878 | continue; | | |
| 1879 | }, | | |
| 1880 | else => { | 2043 | else => { |
| 1881 | self.putBackToken(next); | 2044 | self.putBackToken(next); |
| 1882 | stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable; | 2045 | const statememt = try block.statements.addOne(); |
| 1883 | try stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } }); | 2046 | stack.append(State { .Semicolon = statememt }) catch unreachable; |
| | 2047 | try stack.append(State { .Expression = DestPtr{.Field = statememt } }); |
| 1884 | continue; | 2048 | continue; |
| 1885 | } | 2049 | } |
| 1886 | } | 2050 | } |
| 1887 | | 2051 | |
| 1888 | }, | 2052 | }, |
| | 2053 | |
| | 2054 | State.Semicolon => |node_ptr| { |
| | 2055 | const node = *node_ptr; |
| | 2056 | switch (node.id) { |
| | 2057 | ast.Node.Id.Root, |
| | 2058 | ast.Node.Id.StructField, |
| | 2059 | ast.Node.Id.UnionTag, |
| | 2060 | ast.Node.Id.EnumTag, |
| | 2061 | ast.Node.Id.ParamDecl, |
| | 2062 | ast.Node.Id.Block, |
| | 2063 | ast.Node.Id.Payload, |
| | 2064 | ast.Node.Id.Switch, |
| | 2065 | ast.Node.Id.SwitchCase, |
| | 2066 | ast.Node.Id.SwitchElse, |
| | 2067 | ast.Node.Id.FieldInitializer, |
| | 2068 | ast.Node.Id.LineComment, |
| | 2069 | ast.Node.Id.TestDecl => continue, |
| | 2070 | ast.Node.Id.While => { |
| | 2071 | const while_node = @fieldParentPtr(ast.NodeWhile, "base", node); |
| | 2072 | if (while_node.@"else") |@"else"| { |
| | 2073 | stack.append(State { .Semicolon = &@"else".base }) catch unreachable; |
| | 2074 | continue; |
| | 2075 | } |
| | 2076 | |
| | 2077 | stack.append(State { .Semicolon = &while_node.body }) catch unreachable; |
| | 2078 | continue; |
| | 2079 | }, |
| | 2080 | ast.Node.Id.Else => { |
| | 2081 | const else_node = @fieldParentPtr(ast.NodeElse, "base", node); |
| | 2082 | stack.append(State { .Semicolon = &else_node.body }) catch unreachable; |
| | 2083 | continue; |
| | 2084 | }, |
| | 2085 | else => { |
| | 2086 | _ = (try self.eatToken(&stack, Token.Id.Semicolon)) ?? continue; |
| | 2087 | } |
| | 2088 | } |
| | 2089 | } |
| 1889 | } | 2090 | } |
| 1890 | } | 2091 | } |
| 1891 | } | 2092 | } |
| ... | @@ -2295,9 +2496,6 @@ pub const Parser = struct { | ... | @@ -2295,9 +2496,6 @@ pub const Parser = struct { |
| 2295 | *revert.ptr = null; | 2496 | *revert.ptr = null; |
| 2296 | return; | 2497 | return; |
| 2297 | }, | 2498 | }, |
| 2298 | State.Required => { | | |
| 2299 | return error.StateRequired; | | |
| 2300 | }, | | |
| 2301 | else => { } | 2499 | else => { } |
| 2302 | } | 2500 | } |
| 2303 | } | 2501 | } |
| ... | @@ -2361,6 +2559,7 @@ pub const Parser = struct { | ... | @@ -2361,6 +2559,7 @@ pub const Parser = struct { |
| 2361 | Expression: &ast.Node, | 2559 | Expression: &ast.Node, |
| 2362 | VarDecl: &ast.NodeVarDecl, | 2560 | VarDecl: &ast.NodeVarDecl, |
| 2363 | Statement: &ast.Node, | 2561 | Statement: &ast.Node, |
| | 2562 | Semicolon: &ast.Node, |
| 2364 | FieldInitializer: &ast.NodeFieldInitializer, | 2563 | FieldInitializer: &ast.NodeFieldInitializer, |
| 2365 | PrintIndent, | 2564 | PrintIndent, |
| 2366 | Indent: usize, | 2565 | Indent: usize, |
| ... | @@ -2589,7 +2788,7 @@ pub const Parser = struct { | ... | @@ -2589,7 +2788,7 @@ pub const Parser = struct { |
| 2589 | if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) { | 2788 | if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) { |
| 2590 | if (prefix_op_node.op.Catch) |payload| { | 2789 | if (prefix_op_node.op.Catch) |payload| { |
| 2591 | try stack.append(RenderState { .Text = " " }); | 2790 | try stack.append(RenderState { .Text = " " }); |
| 2592 | try stack.append(RenderState { .Expression = payload }); | 2791 | try stack.append(RenderState { .Expression = &payload.base }); |
| 2593 | } | 2792 | } |
| 2594 | try stack.append(RenderState { .Text = " catch " }); | 2793 | try stack.append(RenderState { .Text = " catch " }); |
| 2595 | } else { | 2794 | } else { |
| ... | @@ -3013,7 +3212,7 @@ pub const Parser = struct { | ... | @@ -3013,7 +3212,7 @@ pub const Parser = struct { |
| 3013 | try stack.append(RenderState { .Expression = switch_case.expr }); | 3212 | try stack.append(RenderState { .Expression = switch_case.expr }); |
| 3014 | if (switch_case.payload) |payload| { | 3213 | if (switch_case.payload) |payload| { |
| 3015 | try stack.append(RenderState { .Text = " " }); | 3214 | try stack.append(RenderState { .Text = " " }); |
| 3016 | try stack.append(RenderState { .Expression = payload }); | 3215 | try stack.append(RenderState { .Expression = &payload.base }); |
| 3017 | } | 3216 | } |
| 3018 | try stack.append(RenderState { .Text = " => "}); | 3217 | try stack.append(RenderState { .Text = " => "}); |
| 3019 | | 3218 | |
| ... | @@ -3032,7 +3231,74 @@ pub const Parser = struct { | ... | @@ -3032,7 +3231,74 @@ pub const Parser = struct { |
| 3032 | const switch_else = @fieldParentPtr(ast.NodeSwitchElse, "base", base); | 3231 | const switch_else = @fieldParentPtr(ast.NodeSwitchElse, "base", base); |
| 3033 | try stream.print("{}", self.tokenizer.getTokenSlice(switch_else.token)); | 3232 | try stream.print("{}", self.tokenizer.getTokenSlice(switch_else.token)); |
| 3034 | }, | 3233 | }, |
| 3035 | ast.Node.Id.While => @panic("TODO: Render while"), | 3234 | ast.Node.Id.Else => { |
| | 3235 | const else_node = @fieldParentPtr(ast.NodeElse, "base", base); |
| | 3236 | try stream.print("{} ", self.tokenizer.getTokenSlice(else_node.else_token)); |
| | 3237 | |
| | 3238 | if (else_node.body.id == ast.Node.Id.Block) { |
| | 3239 | try stack.append(RenderState { .Expression = else_node.body }); |
| | 3240 | } else { |
| | 3241 | try stack.append(RenderState { .Indent = indent }); |
| | 3242 | try stack.append(RenderState { .Expression = else_node.body }); |
| | 3243 | try stack.append(RenderState.PrintIndent); |
| | 3244 | try stack.append(RenderState { .Indent = indent + indent_delta }); |
| | 3245 | try stack.append(RenderState { .Text = "\n" }); |
| | 3246 | } |
| | 3247 | |
| | 3248 | if (else_node.payload) |payload| { |
| | 3249 | try stack.append(RenderState { .Text = " " }); |
| | 3250 | try stack.append(RenderState { .Expression = &payload.base }); |
| | 3251 | } |
| | 3252 | }, |
| | 3253 | ast.Node.Id.While => { |
| | 3254 | const while_node = @fieldParentPtr(ast.NodeWhile, "base", base); |
| | 3255 | if (while_node.label) |label| { |
| | 3256 | try stream.print("{}: ", self.tokenizer.getTokenSlice(label)); |
| | 3257 | } |
| | 3258 | |
| | 3259 | if (while_node.inline_token) |inline_token| { |
| | 3260 | try stream.print("{} ", self.tokenizer.getTokenSlice(inline_token)); |
| | 3261 | } |
| | 3262 | |
| | 3263 | try stream.print("{} ", self.tokenizer.getTokenSlice(while_node.while_token)); |
| | 3264 | |
| | 3265 | if (while_node.@"else") |@"else"| { |
| | 3266 | try stack.append(RenderState { .Expression = &@"else".base }); |
| | 3267 | |
| | 3268 | if (while_node.body.id == ast.Node.Id.Block) { |
| | 3269 | try stack.append(RenderState { .Text = " " }); |
| | 3270 | } else { |
| | 3271 | try stack.append(RenderState { .Text = "\n" }); |
| | 3272 | } |
| | 3273 | } |
| | 3274 | |
| | 3275 | if (while_node.body.id == ast.Node.Id.Block) { |
| | 3276 | try stack.append(RenderState { .Expression = while_node.body }); |
| | 3277 | try stack.append(RenderState { .Text = " " }); |
| | 3278 | } else { |
| | 3279 | try stack.append(RenderState { .Indent = indent }); |
| | 3280 | try stack.append(RenderState { .Expression = while_node.body }); |
| | 3281 | try stack.append(RenderState.PrintIndent); |
| | 3282 | try stack.append(RenderState { .Indent = indent + indent_delta }); |
| | 3283 | try stack.append(RenderState { .Text = "\n" }); |
| | 3284 | } |
| | 3285 | |
| | 3286 | if (while_node.continue_expr) |continue_expr| { |
| | 3287 | try stack.append(RenderState { .Text = ")" }); |
| | 3288 | try stack.append(RenderState { .Expression = continue_expr }); |
| | 3289 | try stack.append(RenderState { .Text = ": (" }); |
| | 3290 | try stack.append(RenderState { .Text = " " }); |
| | 3291 | } |
| | 3292 | |
| | 3293 | if (while_node.payload) |payload| { |
| | 3294 | try stack.append(RenderState { .Expression = &payload.base }); |
| | 3295 | try stack.append(RenderState { .Text = " " }); |
| | 3296 | } |
| | 3297 | |
| | 3298 | try stack.append(RenderState { .Text = ")" }); |
| | 3299 | try stack.append(RenderState { .Expression = while_node.condition }); |
| | 3300 | try stack.append(RenderState { .Text = "(" }); |
| | 3301 | }, |
| 3036 | | 3302 | |
| 3037 | ast.Node.Id.StructField, | 3303 | ast.Node.Id.StructField, |
| 3038 | ast.Node.Id.UnionTag, | 3304 | ast.Node.Id.UnionTag, |
| ... | @@ -3077,13 +3343,45 @@ pub const Parser = struct { | ... | @@ -3077,13 +3343,45 @@ pub const Parser = struct { |
| 3077 | const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base); | 3343 | const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base); |
| 3078 | try stack.append(RenderState { .VarDecl = var_decl}); | 3344 | try stack.append(RenderState { .VarDecl = var_decl}); |
| 3079 | }, | 3345 | }, |
| 3080 | ast.Node.Id.Block, ast.Node.Id.Switch => { | | |
| 3081 | try stack.append(RenderState { .Expression = base}); | | |
| 3082 | }, | | |
| 3083 | else => { | 3346 | else => { |
| 3084 | try stack.append(RenderState { .Text = ";"}); | 3347 | try stack.append(RenderState { .Semicolon = base }); |
| 3085 | try stack.append(RenderState { .Expression = base}); | 3348 | try stack.append(RenderState { .Expression = base }); |
| | 3349 | }, |
| | 3350 | } |
| | 3351 | }, |
| | 3352 | RenderState.Semicolon => |base| { |
| | 3353 | switch (base.id) { |
| | 3354 | ast.Node.Id.Root, |
| | 3355 | ast.Node.Id.StructField, |
| | 3356 | ast.Node.Id.UnionTag, |
| | 3357 | ast.Node.Id.EnumTag, |
| | 3358 | ast.Node.Id.ParamDecl, |
| | 3359 | ast.Node.Id.Block, |
| | 3360 | ast.Node.Id.Payload, |
| | 3361 | ast.Node.Id.Switch, |
| | 3362 | ast.Node.Id.SwitchCase, |
| | 3363 | ast.Node.Id.SwitchElse, |
| | 3364 | ast.Node.Id.FieldInitializer, |
| | 3365 | ast.Node.Id.LineComment, |
| | 3366 | ast.Node.Id.TestDecl => {}, |
| | 3367 | ast.Node.Id.While => { |
| | 3368 | const while_node = @fieldParentPtr(ast.NodeWhile, "base", base); |
| | 3369 | if (while_node.@"else") |@"else"| { |
| | 3370 | stack.append(RenderState { .Semicolon = &@"else".base }) catch unreachable; |
| | 3371 | continue; |
| | 3372 | } |
| | 3373 | |
| | 3374 | stack.append(RenderState { .Semicolon = while_node.body }) catch unreachable; |
| | 3375 | continue; |
| | 3376 | }, |
| | 3377 | ast.Node.Id.Else => { |
| | 3378 | const else_node = @fieldParentPtr(ast.NodeElse, "base", base); |
| | 3379 | stack.append(RenderState { .Semicolon = else_node.body }) catch unreachable; |
| | 3380 | continue; |
| 3086 | }, | 3381 | }, |
| | 3382 | else => { |
| | 3383 | try stack.append(RenderState { .Text = ";" }); |
| | 3384 | } |
| 3087 | } | 3385 | } |
| 3088 | }, | 3386 | }, |
| 3089 | RenderState.Indent => |new_indent| indent = new_indent, | 3387 | RenderState.Indent => |new_indent| indent = new_indent, |
| ... | @@ -3690,8 +3988,11 @@ test "zig fmt: while" { | ... | @@ -3690,8 +3988,11 @@ test "zig fmt: while" { |
| 3690 | \\ continue; | 3988 | \\ continue; |
| 3691 | \\ | 3989 | \\ |
| 3692 | \\ i = 0; | 3990 | \\ i = 0; |
| 3693 | \\ var j usize = 0; | 3991 | \\ var j: usize = 0; |
| 3694 | \\ while (i < 10) : ({ i += 1; j += 1; }) { | 3992 | \\ while (i < 10) : ({ |
| | 3993 | \\ i += 1; |
| | 3994 | \\ j += 1; |
| | 3995 | \\ }) { |
| 3695 | \\ continue; | 3996 | \\ continue; |
| 3696 | \\ } | 3997 | \\ } |
| 3697 | \\ | 3998 | \\ |
| ... | @@ -3711,7 +4012,7 @@ test "zig fmt: while" { | ... | @@ -3711,7 +4012,7 @@ test "zig fmt: while" { |
| 3711 | \\ break 7; | 4012 | \\ break 7; |
| 3712 | \\ } else { | 4013 | \\ } else { |
| 3713 | \\ unreachable; | 4014 | \\ unreachable; |
| 3714 | \\ } | 4015 | \\ }; |
| 3715 | \\ | 4016 | \\ |
| 3716 | \\ var a: error!u8 = 0; | 4017 | \\ var a: error!u8 = 0; |
| 3717 | \\ while (a) |v| { | 4018 | \\ while (a) |v| { |
| ... | @@ -3721,7 +4022,7 @@ test "zig fmt: while" { | ... | @@ -3721,7 +4022,7 @@ test "zig fmt: while" { |
| 3721 | \\ } | 4022 | \\ } |
| 3722 | \\ | 4023 | \\ |
| 3723 | \\ comptime var k: usize = 0; | 4024 | \\ comptime var k: usize = 0; |
| 3724 | \\ inline while (i < 10) (i += 1) | 4025 | \\ inline while (i < 10) : (i += 1) |
| 3725 | \\ j += 2; | 4026 | \\ j += 2; |
| 3726 | \\} | 4027 | \\} |
| 3727 | \\ | 4028 | \\ |