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 {...@@ -21,6 +21,7 @@ pub const Node = struct {
21 ParamDecl,21 ParamDecl,
22 Block,22 Block,
23 Payload,23 Payload,
24 Else,
24 Switch,25 Switch,
25 SwitchCase,26 SwitchCase,
26 SwitchElse,27 SwitchElse,
...@@ -61,6 +62,7 @@ pub const Node = struct {...@@ -61,6 +62,7 @@ pub const Node = struct {
61 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),62 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),
62 Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),63 Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
63 Id.Payload => @fieldParentPtr(NodePayload, "base", base).iterate(index),64 Id.Payload => @fieldParentPtr(NodePayload, "base", base).iterate(index),
65 Id.Else => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
64 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),66 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
65 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index),67 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index),
66 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).iterate(index),68 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).iterate(index),
...@@ -102,6 +104,7 @@ pub const Node = struct {...@@ -102,6 +104,7 @@ pub const Node = struct {
102 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),104 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),
103 Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),105 Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
104 Id.Payload => @fieldParentPtr(NodePayload, "base", base).firstToken(),106 Id.Payload => @fieldParentPtr(NodePayload, "base", base).firstToken(),
107 Id.Else => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
105 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),108 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
106 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),109 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),
107 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(),110 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(),
...@@ -143,6 +146,7 @@ pub const Node = struct {...@@ -143,6 +146,7 @@ pub const Node = struct {
143 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),146 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),
144 Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),147 Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
145 Id.Payload => @fieldParentPtr(NodePayload, "base", base).lastToken(),148 Id.Payload => @fieldParentPtr(NodePayload, "base", base).lastToken(),
149 Id.Else => @fieldParentPtr(NodeElse, "base", base).lastToken(),
146 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),150 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),
147 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),151 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),
148 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).lastToken(),152 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).lastToken(),
...@@ -578,6 +582,35 @@ pub const NodePayload = struct {...@@ -578,6 +582,35 @@ pub const NodePayload = struct {
578 }582 }
579};583};
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
581pub const NodeSwitch = struct {614pub const NodeSwitch = struct {
582 base: Node,615 base: Node,
583 switch_token: Token,616 switch_token: Token,
...@@ -609,7 +642,7 @@ pub const NodeSwitch = struct {...@@ -609,7 +642,7 @@ pub const NodeSwitch = struct {
609pub const NodeSwitchCase = struct {642pub const NodeSwitchCase = struct {
610 base: Node,643 base: Node,
611 items: ArrayList(&Node),644 items: ArrayList(&Node),
612 payload: ?&Node,645 payload: ?&NodePayload,
613 expr: &Node,646 expr: &Node,
614647
615 pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node {648 pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node {
...@@ -657,18 +690,14 @@ pub const NodeSwitchElse = struct {...@@ -657,18 +690,14 @@ pub const NodeSwitchElse = struct {
657690
658pub const NodeWhile = struct {691pub const NodeWhile = struct {
659 base: Node,692 base: Node,
693 label: ?Token,
694 inline_token: ?Token,
660 while_token: Token,695 while_token: Token,
661 condition: &Node,696 condition: &Node,
662 payload: ?&NodePayload,697 payload: ?&NodePayload,
663 continue_expr: ?&Node,698 continue_expr: ?&Node,
664 body: &Node,699 body: &Node,
665 @"else": ?Else,700 @"else": ?&NodeElse,
666
667 const Else = struct {
668 capture: ?&NodeIdentifier,
669 body: &Node,
670 };
671
672701
673 pub fn iterate(self: &NodeWhile, index: usize) ?&Node {702 pub fn iterate(self: &NodeWhile, index: usize) ?&Node {
674 var i = index;703 var i = index;
...@@ -690,12 +719,7 @@ pub const NodeWhile = struct {...@@ -690,12 +719,7 @@ pub const NodeWhile = struct {
690 i -= 1;719 i -= 1;
691720
692 if (self.@"else") |@"else"| {721 if (self.@"else") |@"else"| {
693 if (@"else".capture) |capture| {722 if (i < 1) return &@"else".base;
694 if (i < 1) return &capture.base;
695 i -= 1;
696 }
697
698 if (i < 1) return @"else".body;
699 i -= 1;723 i -= 1;
700 }724 }
701725
...@@ -703,6 +727,14 @@ pub const NodeWhile = struct {...@@ -703,6 +727,14 @@ pub const NodeWhile = struct {
703 }727 }
704728
705 pub fn firstToken(self: &NodeWhile) Token {729 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
706 return self.while_token;738 return self.while_token;
707 }739 }
708740
...@@ -749,7 +781,7 @@ pub const NodeInfixOp = struct {...@@ -749,7 +781,7 @@ pub const NodeInfixOp = struct {
749 BitXor,781 BitXor,
750 BoolAnd,782 BoolAnd,
751 BoolOr,783 BoolOr,
752 Catch: ?&Node,784 Catch: ?&NodePayload,
753 Div,785 Div,
754 EqualEqual,786 EqualEqual,
755 ErrorUnion,787 ErrorUnion,
std/zig/parser.zig+421-120
...@@ -116,6 +116,24 @@ pub const Parser = struct {...@@ -116,6 +116,24 @@ pub const Parser = struct {
116 };116 };
117 }117 }
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
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,
159184
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 },
600622
601 State.Optional,623 State.Optional => { },
602 State.Required => { },
603624
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 {
707769
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 }
13721427
1373 const block = try self.createBlock(arena, (?Token)(token), Token(undefined));1428 stack.append(State {
1374 dest_ptr.store(&block.base);1429 .LabeledExpression = LabelCtx {
13751430 .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);
15701618
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 },
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
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 },
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
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 },
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
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 }
18872051
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 = " => "});
30193218
...@@ -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 },
30363302
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 \\