authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-09 11:11:18+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-09 11:11:18+02:00
loge260c8ca632fb2569f99d182dd6d1daea2b6df63
tree2879e9f2b319ad3321ddf911356bfe0e3b8cabfd
parente4d0b46c0c07f3151b4959c5e2e0d4c304981ead

std.zig.parser now parses while loops and labeled break and continue


2 files changed, 468 insertions(+), 135 deletions(-)

std/zig/ast.zig+47-15
......@@ -21,6 +21,7 @@ pub const Node = struct {
2121 ParamDecl,
2222 Block,
2323 Payload,
24 Else,
2425 Switch,
2526 SwitchCase,
2627 SwitchElse,
......@@ -61,6 +62,7 @@ pub const Node = struct {
6162 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),
6263 Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
6364 Id.Payload => @fieldParentPtr(NodePayload, "base", base).iterate(index),
65 Id.Else => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
6466 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
6567 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index),
6668 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).iterate(index),
......@@ -102,6 +104,7 @@ pub const Node = struct {
102104 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),
103105 Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
104106 Id.Payload => @fieldParentPtr(NodePayload, "base", base).firstToken(),
107 Id.Else => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
105108 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
106109 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),
107110 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(),
......@@ -143,6 +146,7 @@ pub const Node = struct {
143146 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),
144147 Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
145148 Id.Payload => @fieldParentPtr(NodePayload, "base", base).lastToken(),
149 Id.Else => @fieldParentPtr(NodeElse, "base", base).lastToken(),
146150 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),
147151 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),
148152 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).lastToken(),
......@@ -578,6 +582,35 @@ pub const NodePayload = struct {
578582 }
579583};
580584
585pub const NodeElse = struct {
586 base: Node,
587 else_token: Token,
588 payload: ?&NodePayload,
589 body: &Node,
590
591 pub fn iterate(self: &NodeElse, index: usize) ?&Node {
592 var i = index;
593
594 if (self.payload) |payload| {
595 if (i < 1) return &payload.base;
596 i -= 1;
597 }
598
599 if (i < 1) return self.body;
600 i -= 1;
601
602 return null;
603 }
604
605 pub fn firstToken(self: &NodeElse) Token {
606 return self.else_token;
607 }
608
609 pub fn lastToken(self: &NodeElse) Token {
610 return self.body.lastToken();
611 }
612};
613
581614pub const NodeSwitch = struct {
582615 base: Node,
583616 switch_token: Token,
......@@ -609,7 +642,7 @@ pub const NodeSwitch = struct {
609642pub const NodeSwitchCase = struct {
610643 base: Node,
611644 items: ArrayList(&Node),
612 payload: ?&Node,
645 payload: ?&NodePayload,
613646 expr: &Node,
614647
615648 pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node {
......@@ -657,18 +690,14 @@ pub const NodeSwitchElse = struct {
657690
658691pub const NodeWhile = struct {
659692 base: Node,
693 label: ?Token,
694 inline_token: ?Token,
660695 while_token: Token,
661696 condition: &Node,
662697 payload: ?&NodePayload,
663698 continue_expr: ?&Node,
664699 body: &Node,
665 @"else": ?Else,
666
667 const Else = struct {
668 capture: ?&NodeIdentifier,
669 body: &Node,
670 };
671
700 @"else": ?&NodeElse,
672701
673702 pub fn iterate(self: &NodeWhile, index: usize) ?&Node {
674703 var i = index;
......@@ -690,12 +719,7 @@ pub const NodeWhile = struct {
690719 i -= 1;
691720
692721 if (self.@"else") |@"else"| {
693 if (@"else".capture) |capture| {
694 if (i < 1) return &capture.base;
695 i -= 1;
696 }
697
698 if (i < 1) return @"else".body;
722 if (i < 1) return &@"else".base;
699723 i -= 1;
700724 }
701725
......@@ -703,6 +727,14 @@ pub const NodeWhile = struct {
703727 }
704728
705729 pub fn firstToken(self: &NodeWhile) Token {
730 if (self.label) |label| {
731 return label;
732 }
733
734 if (self.inline_token) |inline_token| {
735 return inline_token;
736 }
737
706738 return self.while_token;
707739 }
708740
......@@ -749,7 +781,7 @@ pub const NodeInfixOp = struct {
749781 BitXor,
750782 BoolAnd,
751783 BoolOr,
752 Catch: ?&Node,
784 Catch: ?&NodePayload,
753785 Div,
754786 EqualEqual,
755787 ErrorUnion,
std/zig/parser.zig+421-120
......@@ -116,6 +116,24 @@ pub const Parser = struct {
116116 };
117117 }
118118
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
119137 const State = union(enum) {
120138 TopLevel,
121139 TopLevelExtern: TopLevelDeclCtx,
......@@ -137,15 +155,22 @@ pub const Parser = struct {
137155 ParamDecl: &ast.NodeFnProto,
138156 ParamDeclComma,
139157 FnDef: &ast.NodeFnProto,
158 LabeledExpression: LabelCtx,
159 Inline: InlineCtx,
160 While: LoopCtx,
161 For: LoopCtx,
140162 Block: &ast.NodeBlock,
163 Else: &?&ast.NodeElse,
164 WhileContinueExpr: &?&ast.Node,
141165 Statement: &ast.NodeBlock,
166 Semicolon: &const &const ast.Node,
142167 ExprListItemOrEnd: ExprListCtx,
143168 ExprListCommaOrEnd: ExprListCtx,
144169 FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer),
145170 FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer),
146171 FieldListCommaOrEnd: &ast.NodeContainerDecl,
147172 SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase),
148 Payload: DestPtr,
173 Payload: &?&ast.NodePayload,
149174 SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase),
150175 SwitchCaseItem: &ArrayList(&ast.Node),
151176 SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node),
......@@ -157,9 +182,6 @@ pub const Parser = struct {
157182 /// "leaked" nodes. TODO: Figure out if it's nessesary to handle leaked nodes.
158183 Optional: RevertState,
159184
160 /// Optional can be reverted by adding the Required state to the stack.
161 Required,
162
163185 Expression: DestPtr,
164186 RangeExpressionBegin: DestPtr,
165187 RangeExpressionEnd: DestPtr,
......@@ -598,8 +620,7 @@ pub const Parser = struct {
598620 continue;
599621 },
600622
601 State.Optional,
602 State.Required => { },
623 State.Optional => { },
603624
604625 State.Expression => |dest_ptr| {
605626 const token = self.getNextToken();
......@@ -626,10 +647,51 @@ pub const Parser = struct {
626647 continue;
627648 },
628649 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;
630676 },
631677 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;
633695 },
634696 Token.Id.Keyword_cancel => {
635697 @panic("TODO: cancel");
......@@ -707,14 +769,7 @@ pub const Parser = struct {
707769
708770 stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable;
709771 try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } });
710 try stack.append(State {
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 } });
772 try stack.append(State { .Payload = &node.op.Catch });
718773 continue;
719774 },
720775 Token.Id.QuestionMarkQuestionMark => {
......@@ -1370,16 +1425,12 @@ pub const Parser = struct {
13701425 continue;
13711426 }
13721427
1373 const block = try self.createBlock(arena, (?Token)(token), Token(undefined));
1374 dest_ptr.store(&block.base);
1375
1376 stack.append(State { .Block = block }) catch unreachable;
1377 try stack.append(State {
1378 .ExpectTokenSave = ExpectTokenSave {
1379 .id = Token.Id.LBrace,
1380 .ptr = &block.lbrace,
1428 stack.append(State {
1429 .LabeledExpression = LabelCtx {
1430 .label = token,
1431 .dest_ptr = dest_ptr
13811432 }
1382 });
1433 }) catch unreachable;
13831434 continue;
13841435 },
13851436 Token.Id.LBrace => {
......@@ -1398,26 +1449,31 @@ pub const Parser = struct {
13981449 Token.Id.Keyword_if => {
13991450 @panic("TODO: inline if");
14001451 },
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 },
14011462 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
1414 @panic("TODO: inline while");
1463 stack.append(State {
1464 .While = LoopCtx {
1465 .label = null,
1466 .inline_token = null,
1467 .loop_token = token,
1468 .dest_ptr = dest_ptr,
1469 }
1470 }) catch unreachable;
1471 continue;
14151472 },
14161473 Token.Id.Keyword_for => {
14171474 @panic("TODO: inline for");
14181475 },
14191476 Token.Id.Keyword_switch => {
1420 @breakpoint();
14211477 const node = try arena.create(ast.NodeSwitch);
14221478 *node = ast.NodeSwitch {
14231479 .base = self.initNode(ast.Node.Id.Switch),
......@@ -1558,15 +1614,7 @@ pub const Parser = struct {
15581614 try list_state.list.append(node);
15591615 stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable;
15601616 try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } });
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);
1617 try stack.append(State { .Payload = &node.payload });
15701618
15711619 const maybe_else = self.getNextToken();
15721620 if (maybe_else.id == Token.Id.Keyword_else) {
......@@ -1585,32 +1633,6 @@ pub const Parser = struct {
15851633 }
15861634 },
15871635
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
16141636 State.SwitchCaseItem => |case_items| {
16151637 stack.append(State { .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable;
16161638 try stack.append(State { .RangeExpressionBegin = DestPtr{ .Field = try case_items.addOne() } });
......@@ -1642,6 +1664,68 @@ pub const Parser = struct {
16421664 continue;
16431665 },
16441666
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
16451729 State.AddrOfModifiers => |addr_of_info| {
16461730 var token = self.getNextToken();
16471731 switch (token.id) {
......@@ -1803,6 +1887,114 @@ pub const Parser = struct {
18031887 }
18041888 },
18051889
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
18061998 State.Block => |block| {
18071999 const token = self.getNextToken();
18082000 switch (token.id) {
......@@ -1841,28 +2033,6 @@ pub const Parser = struct {
18412033 stack.append(State { .VarDecl = var_decl }) catch unreachable;
18422034 continue;
18432035 },
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 },
18662036 Token.Id.LBrace => {
18672037 const inner_block = try self.createBlock(arena, (?Token)(null), next);
18682038 try block.statements.append(&inner_block.base);
......@@ -1870,22 +2040,53 @@ pub const Parser = struct {
18702040 stack.append(State { .Block = inner_block }) catch unreachable;
18712041 continue;
18722042 },
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 },
18802043 else => {
18812044 self.putBackToken(next);
1882 stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
1883 try stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } });
2045 const statememt = try block.statements.addOne();
2046 stack.append(State { .Semicolon = statememt }) catch unreachable;
2047 try stack.append(State { .Expression = DestPtr{.Field = statememt } });
18842048 continue;
18852049 }
18862050 }
18872051
18882052 },
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 }
18892090 }
18902091 }
18912092 }
......@@ -2295,9 +2496,6 @@ pub const Parser = struct {
22952496 *revert.ptr = null;
22962497 return;
22972498 },
2298 State.Required => {
2299 return error.StateRequired;
2300 },
23012499 else => { }
23022500 }
23032501 }
......@@ -2361,6 +2559,7 @@ pub const Parser = struct {
23612559 Expression: &ast.Node,
23622560 VarDecl: &ast.NodeVarDecl,
23632561 Statement: &ast.Node,
2562 Semicolon: &ast.Node,
23642563 FieldInitializer: &ast.NodeFieldInitializer,
23652564 PrintIndent,
23662565 Indent: usize,
......@@ -2589,7 +2788,7 @@ pub const Parser = struct {
25892788 if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) {
25902789 if (prefix_op_node.op.Catch) |payload| {
25912790 try stack.append(RenderState { .Text = " " });
2592 try stack.append(RenderState { .Expression = payload });
2791 try stack.append(RenderState { .Expression = &payload.base });
25932792 }
25942793 try stack.append(RenderState { .Text = " catch " });
25952794 } else {
......@@ -3013,7 +3212,7 @@ pub const Parser = struct {
30133212 try stack.append(RenderState { .Expression = switch_case.expr });
30143213 if (switch_case.payload) |payload| {
30153214 try stack.append(RenderState { .Text = " " });
3016 try stack.append(RenderState { .Expression = payload });
3215 try stack.append(RenderState { .Expression = &payload.base });
30173216 }
30183217 try stack.append(RenderState { .Text = " => "});
30193218
......@@ -3032,7 +3231,74 @@ pub const Parser = struct {
30323231 const switch_else = @fieldParentPtr(ast.NodeSwitchElse, "base", base);
30333232 try stream.print("{}", self.tokenizer.getTokenSlice(switch_else.token));
30343233 },
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 },
30363302
30373303 ast.Node.Id.StructField,
30383304 ast.Node.Id.UnionTag,
......@@ -3077,13 +3343,45 @@ pub const Parser = struct {
30773343 const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base);
30783344 try stack.append(RenderState { .VarDecl = var_decl});
30793345 },
3080 ast.Node.Id.Block, ast.Node.Id.Switch => {
3081 try stack.append(RenderState { .Expression = base});
3082 },
30833346 else => {
3084 try stack.append(RenderState { .Text = ";"});
3085 try stack.append(RenderState { .Expression = base});
3347 try stack.append(RenderState { .Semicolon = 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;
30863381 },
3382 else => {
3383 try stack.append(RenderState { .Text = ";" });
3384 }
30873385 }
30883386 },
30893387 RenderState.Indent => |new_indent| indent = new_indent,
......@@ -3690,8 +3988,11 @@ test "zig fmt: while" {
36903988 \\ continue;
36913989 \\
36923990 \\ i = 0;
3693 \\ var j usize = 0;
3694 \\ while (i < 10) : ({ i += 1; j += 1; }) {
3991 \\ var j: usize = 0;
3992 \\ while (i < 10) : ({
3993 \\ i += 1;
3994 \\ j += 1;
3995 \\ }) {
36953996 \\ continue;
36963997 \\ }
36973998 \\
......@@ -3711,7 +4012,7 @@ test "zig fmt: while" {
37114012 \\ break 7;
37124013 \\ } else {
37134014 \\ unreachable;
3714 \\ }
4015 \\ };
37154016 \\
37164017 \\ var a: error!u8 = 0;
37174018 \\ while (a) |v| {
......@@ -3721,7 +4022,7 @@ test "zig fmt: while" {
37214022 \\ }
37224023 \\
37234024 \\ comptime var k: usize = 0;
3724 \\ inline while (i < 10) (i += 1)
4025 \\ inline while (i < 10) : (i += 1)
37254026 \\ j += 2;
37264027 \\}
37274028 \\