authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-07 01:38:38+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-07 01:38:38+02:00
logbdff5bfa3e9f6ab490771b54109cb200b180b4da
tree9176bf8191165fe5af14c7d466934c1c5a1be3b5
parent820de1716b83ee99ed94461996ca592a302eccae

std.zig.parser now parses switch


3 files changed, 251 insertions(+), 36 deletions(-)

std/zig/ast.zig+21
...@@ -22,6 +22,7 @@ pub const Node = struct {...@@ -22,6 +22,7 @@ pub const Node = struct {
22 Block,22 Block,
23 Switch,23 Switch,
24 SwitchCase,24 SwitchCase,
25 SwitchElse,
25 InfixOp,26 InfixOp,
26 PrefixOp,27 PrefixOp,
27 SuffixOp,28 SuffixOp,
...@@ -59,6 +60,7 @@ pub const Node = struct {...@@ -59,6 +60,7 @@ pub const Node = struct {
59 Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),60 Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
60 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),61 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
61 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index),62 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index),
63 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).iterate(index),
62 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),64 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
63 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),65 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),
64 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index),66 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index),
...@@ -97,6 +99,7 @@ pub const Node = struct {...@@ -97,6 +99,7 @@ pub const Node = struct {
97 Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),99 Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
98 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),100 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
99 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),101 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),
102 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(),
100 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),103 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),
101 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),104 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),
102 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(),105 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(),
...@@ -135,6 +138,7 @@ pub const Node = struct {...@@ -135,6 +138,7 @@ pub const Node = struct {
135 Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),138 Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
136 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),139 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),
137 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),140 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),
141 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(),
138 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),142 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),
139 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),143 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),
140 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(),144 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(),
...@@ -606,6 +610,23 @@ pub const NodeSwitchCase = struct {...@@ -606,6 +610,23 @@ pub const NodeSwitchCase = struct {
606 }610 }
607};611};
608612
613pub const NodeSwitchElse = struct {
614 base: Node,
615 token: Token,
616
617 pub fn iterate(self: &NodeSwitchElse, index: usize) ?&Node {
618 return null;
619 }
620
621 pub fn firstToken(self: &NodeSwitchElse) Token {
622 return self.token;
623 }
624
625 pub fn lastToken(self: &NodeSwitchElse) Token {
626 return self.token;
627 }
628};
629
609pub const NodeInfixOp = struct {630pub const NodeInfixOp = struct {
610 base: Node,631 base: Node,
611 op_token: Token,632 op_token: Token,
std/zig/parser.zig+224-36
...@@ -98,10 +98,15 @@ pub const Parser = struct {...@@ -98,10 +98,15 @@ pub const Parser = struct {
98 ptr: &?&ast.Node,98 ptr: &?&ast.Node,
99 };99 };
100100
101 fn ListState(comptime T: type) type {101 const ExprListCtx = struct {
102 list: &ArrayList(&ast.Node),
103 end: Token.Id,
104 ptr: &Token,
105 };
106
107 fn ListSave(comptime T: type) type {
102 return struct {108 return struct {
103 list: &ArrayList(T),109 list: &ArrayList(T),
104 end: Token.Id,
105 ptr: &Token,110 ptr: &Token,
106 };111 };
107 }112 }
...@@ -129,11 +134,16 @@ pub const Parser = struct {...@@ -129,11 +134,16 @@ pub const Parser = struct {
129 FnDef: &ast.NodeFnProto,134 FnDef: &ast.NodeFnProto,
130 Block: &ast.NodeBlock,135 Block: &ast.NodeBlock,
131 Statement: &ast.NodeBlock,136 Statement: &ast.NodeBlock,
132 ExprListItemOrEnd: ListState(&ast.Node),137 ExprListItemOrEnd: ExprListCtx,
133 ExprListCommaOrEnd: ListState(&ast.Node),138 ExprListCommaOrEnd: ExprListCtx,
134 FieldInitListItemOrEnd: ListState(&ast.NodeFieldInitializer),139 FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer),
135 FieldInitListCommaOrEnd: ListState(&ast.NodeFieldInitializer),140 FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer),
136 FieldListCommaOrEnd: &ast.NodeContainerDecl,141 FieldListCommaOrEnd: &ast.NodeContainerDecl,
142 SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase),
143 SwitchCaseCapture: &?ast.NodeSwitchCase.Capture,
144 SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase),
145 SwitchCaseItem: &ArrayList(&ast.Node),
146 SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node),
137147
138 /// A state that can be appended before any other State. If an error occures,148 /// A state that can be appended before any other State. If an error occures,
139 /// the parser will first try looking for the closest optional state. If an149 /// the parser will first try looking for the closest optional state. If an
...@@ -245,17 +255,8 @@ pub const Parser = struct {...@@ -245,17 +255,8 @@ pub const Parser = struct {
245 Token.Id.Keyword_test => {255 Token.Id.Keyword_test => {
246 stack.append(State.TopLevel) catch unreachable;256 stack.append(State.TopLevel) catch unreachable;
247257
248 const name_token = self.getNextToken();258 const name_token = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue;
249 if (name_token.id != Token.Id.StringLiteral) {259 const lbrace = (try self.eatToken(&stack, Token.Id.LBrace)) ?? continue;
250 try self.parseError(&stack, token, "expected {}, found {}", @tagName(Token.Id.StringLiteral), @tagName(name_token.id));
251 continue;
252 }
253
254 const lbrace = self.getNextToken();
255 if (lbrace.id != Token.Id.LBrace) {
256 try self.parseError(&stack, token, "expected {}, found {}", @tagName(Token.Id.LBrace), @tagName(name_token.id));
257 continue;
258 }
259260
260 const name = try self.createStringLiteral(arena, name_token);261 const name = try self.createStringLiteral(arena, name_token);
261 const block = try self.createBlock(arena, (?Token)(null), token);262 const block = try self.createBlock(arena, (?Token)(null), token);
...@@ -974,9 +975,8 @@ pub const Parser = struct {...@@ -974,9 +975,8 @@ pub const Parser = struct {
974975
975 stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;976 stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;
976 try stack.append(State {977 try stack.append(State {
977 .FieldInitListItemOrEnd = ListState(&ast.NodeFieldInitializer) {978 .FieldInitListItemOrEnd = ListSave(&ast.NodeFieldInitializer) {
978 .list = &node.op.StructInitializer,979 .list = &node.op.StructInitializer,
979 .end = Token.Id.RBrace,
980 .ptr = &node.rtoken,980 .ptr = &node.rtoken,
981 }981 }
982 });982 });
...@@ -992,7 +992,7 @@ pub const Parser = struct {...@@ -992,7 +992,7 @@ pub const Parser = struct {
992992
993 stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;993 stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;
994 try stack.append(State {994 try stack.append(State {
995 .ExprListItemOrEnd = ListState(&ast.Node) {995 .ExprListItemOrEnd = ExprListCtx {
996 .list = &node.op.ArrayInitializer,996 .list = &node.op.ArrayInitializer,
997 .end = Token.Id.RBrace,997 .end = Token.Id.RBrace,
998 .ptr = &node.rtoken,998 .ptr = &node.rtoken,
...@@ -1084,7 +1084,7 @@ pub const Parser = struct {...@@ -1084,7 +1084,7 @@ pub const Parser = struct {
10841084
1085 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;1085 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;
1086 try stack.append(State {1086 try stack.append(State {
1087 .ExprListItemOrEnd = ListState(&ast.Node) {1087 .ExprListItemOrEnd = ExprListCtx {
1088 .list = &node.op.Call.params,1088 .list = &node.op.Call.params,
1089 .end = Token.Id.RParen,1089 .end = Token.Id.RParen,
1090 .ptr = &node.rtoken,1090 .ptr = &node.rtoken,
...@@ -1238,7 +1238,7 @@ pub const Parser = struct {...@@ -1238,7 +1238,7 @@ pub const Parser = struct {
1238 };1238 };
1239 dest_ptr.store(&node.base);1239 dest_ptr.store(&node.base);
1240 stack.append(State {1240 stack.append(State {
1241 .ExprListItemOrEnd = ListState(&ast.Node) {1241 .ExprListItemOrEnd = ExprListCtx {
1242 .list = &node.params,1242 .list = &node.params,
1243 .end = Token.Id.RParen,1243 .end = Token.Id.RParen,
1244 .ptr = &node.rparen_token,1244 .ptr = &node.rparen_token,
...@@ -1400,6 +1400,43 @@ pub const Parser = struct {...@@ -1400,6 +1400,43 @@ pub const Parser = struct {
1400 Token.Id.Keyword_asm => {1400 Token.Id.Keyword_asm => {
1401 @panic("TODO: inline asm");1401 @panic("TODO: inline asm");
1402 },1402 },
1403 Token.Id.Keyword_if => {
1404 @panic("TODO: inline if");
1405 },
1406 Token.Id.Keyword_while => {
1407 @panic("TODO: inline while");
1408 },
1409 Token.Id.Keyword_for => {
1410 @panic("TODO: inline for");
1411 },
1412 Token.Id.Keyword_switch => {
1413 const node = try arena.create(ast.NodeSwitch);
1414 *node = ast.NodeSwitch {
1415 .base = self.initNode(ast.Node.Id.Switch),
1416 .switch_token = token,
1417 .expr = undefined,
1418 .cases = ArrayList(&ast.NodeSwitchCase).init(arena),
1419 .rbrace = undefined,
1420 };
1421 dest_ptr.store(&node.base);
1422
1423 stack.append(State {
1424 .SwitchCaseOrEnd = ListSave(&ast.NodeSwitchCase) {
1425 .list = &node.cases,
1426 .ptr = &node.rbrace,
1427 },
1428 }) catch unreachable;
1429 try stack.append(State { .ExpectToken = Token.Id.LBrace });
1430 try stack.append(State { .ExpectToken = Token.Id.RParen });
1431 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
1432 try stack.append(State { .ExpectToken = Token.Id.LParen });
1433 },
1434 Token.Id.Keyword_comptime => {
1435 @panic("TODO: inline comptime");
1436 },
1437 Token.Id.Keyword_suspend => {
1438 @panic("TODO: inline suspend");
1439 },
1403 else => {1440 else => {
1404 try self.parseError(&stack, token, "expected primary expression, found {}", @tagName(token.id));1441 try self.parseError(&stack, token, "expected primary expression, found {}", @tagName(token.id));
1405 continue;1442 continue;
...@@ -1463,8 +1500,7 @@ pub const Parser = struct {...@@ -1463,8 +1500,7 @@ pub const Parser = struct {
1463 State.FieldInitListItemOrEnd => |list_state| {1500 State.FieldInitListItemOrEnd => |list_state| {
1464 var token = self.getNextToken();1501 var token = self.getNextToken();
14651502
1466 const IdTag = @TagType(Token.Id);1503 if (token.id == Token.Id.RBrace){
1467 if (IdTag(list_state.end) == token.id){
1468 *list_state.ptr = token;1504 *list_state.ptr = token;
1469 continue;1505 continue;
1470 }1506 }
...@@ -1497,13 +1533,82 @@ pub const Parser = struct {...@@ -1497,13 +1533,82 @@ pub const Parser = struct {
1497 });1533 });
1498 },1534 },
14991535
1536 State.SwitchCaseOrEnd => |list_state| {
1537 var token = self.getNextToken();
1538
1539 if (token.id == Token.Id.RBrace){
1540 *list_state.ptr = token;
1541 continue;
1542 }
1543
1544 self.putBackToken(token);
1545
1546 const node = try arena.create(ast.NodeSwitchCase);
1547 *node = ast.NodeSwitchCase {
1548 .base = self.initNode(ast.Node.Id.SwitchCase),
1549 .items = ArrayList(&ast.Node).init(arena),
1550 .capture = null,
1551 .expr = undefined,
1552 };
1553 try list_state.list.append(node);
1554 stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable;
1555 try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } });
1556 try stack.append(State { .SwitchCaseCapture = &node.capture });
1557
1558 const maybe_else = self.getNextToken();
1559 if (maybe_else.id == Token.Id.Keyword_else) {
1560 const else_node = try arena.create(ast.NodeSwitchElse);
1561 *else_node = ast.NodeSwitchElse {
1562 .base = self.initNode(ast.Node.Id.SwitchElse),
1563 .token = maybe_else,
1564 };
1565 try node.items.append(&else_node.base);
1566 try stack.append(State { .ExpectToken = Token.Id.EqualAngleBracketRight });
1567 continue;
1568 } else {
1569 self.putBackToken(maybe_else);
1570 try stack.append(State { .SwitchCaseItem = &node.items });
1571 continue;
1572 }
1573 },
1574
1575 State.SwitchCaseCapture => |capture| {
1576 const token = self.getNextToken();
1577 if (token.id != Token.Id.Pipe) {
1578 self.putBackToken(token);
1579 continue;
1580 }
1581
1582 const is_ptr = blk: {
1583 const asterik = self.getNextToken();
1584 if (asterik.id == Token.Id.Asterisk) {
1585 break :blk true;
1586 } else {
1587 self.putBackToken(asterik);
1588 break :blk false;
1589 }
1590 };
1591
1592 const ident = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
1593 _ = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
1594 *capture = ast.NodeSwitchCase.Capture {
1595 .symbol = try self.createIdentifier(arena, ident),
1596 .is_ptr = is_ptr
1597 };
1598 },
1599
1600 State.SwitchCaseItem => |case_items| {
1601 stack.append(State { .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable;
1602 try stack.append(State { .RangeExpressionBegin = DestPtr{ .Field = try case_items.addOne() } });
1603 },
1604
1500 State.ExprListCommaOrEnd => |list_state| {1605 State.ExprListCommaOrEnd => |list_state| {
1501 try self.commaOrEnd(&stack, list_state.end, list_state.ptr, State { .ExprListItemOrEnd = list_state });1606 try self.commaOrEnd(&stack, list_state.end, list_state.ptr, State { .ExprListItemOrEnd = list_state });
1502 continue;1607 continue;
1503 },1608 },
15041609
1505 State.FieldInitListCommaOrEnd => |list_state| {1610 State.FieldInitListCommaOrEnd => |list_state| {
1506 try self.commaOrEnd(&stack, list_state.end, list_state.ptr, State { .FieldInitListItemOrEnd = list_state });1611 try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .FieldInitListItemOrEnd = list_state });
1507 continue;1612 continue;
1508 },1613 },
15091614
...@@ -1513,6 +1618,16 @@ pub const Parser = struct {...@@ -1513,6 +1618,16 @@ pub const Parser = struct {
1513 continue;1618 continue;
1514 },1619 },
15151620
1621 State.SwitchCaseCommaOrEnd => |list_state| {
1622 try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .SwitchCaseOrEnd = list_state });
1623 continue;
1624 },
1625
1626 State.SwitchCaseItemCommaOrEnd => |case_items| {
1627 try self.commaOrEnd(&stack, Token.Id.EqualAngleBracketRight, null, State { .SwitchCaseItem = case_items });
1628 continue;
1629 },
1630
1516 State.AddrOfModifiers => |addr_of_info| {1631 State.AddrOfModifiers => |addr_of_info| {
1517 var token = self.getNextToken();1632 var token = self.getNextToken();
1518 switch (token.id) {1633 switch (token.id) {
...@@ -1741,6 +1856,11 @@ pub const Parser = struct {...@@ -1741,6 +1856,11 @@ pub const Parser = struct {
1741 stack.append(State { .Block = inner_block }) catch unreachable;1856 stack.append(State { .Block = inner_block }) catch unreachable;
1742 continue;1857 continue;
1743 },1858 },
1859 Token.Id.Keyword_switch => {
1860 self.putBackToken(next);
1861 stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } }) catch unreachable;
1862 continue;
1863 },
1744 else => {1864 else => {
1745 self.putBackToken(next);1865 self.putBackToken(next);
1746 stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;1866 stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
...@@ -1754,7 +1874,7 @@ pub const Parser = struct {...@@ -1754,7 +1874,7 @@ pub const Parser = struct {
1754 }1874 }
1755 }1875 }
17561876
1757 fn commaOrEnd(self: &Parser, stack: &ArrayList(State), end: &const Token.Id, ptr: &Token, state_after_comma: &const State) !void {1877 fn commaOrEnd(self: &Parser, stack: &ArrayList(State), end: &const Token.Id, maybe_ptr: ?&Token, state_after_comma: &const State) !void {
1758 var token = self.getNextToken();1878 var token = self.getNextToken();
1759 switch (token.id) {1879 switch (token.id) {
1760 Token.Id.Comma => {1880 Token.Id.Comma => {
...@@ -1763,7 +1883,9 @@ pub const Parser = struct {...@@ -1763,7 +1883,9 @@ pub const Parser = struct {
1763 else => {1883 else => {
1764 const IdTag = @TagType(Token.Id);1884 const IdTag = @TagType(Token.Id);
1765 if (IdTag(*end) == token.id) {1885 if (IdTag(*end) == token.id) {
1766 *ptr = token;1886 if (maybe_ptr) |ptr| {
1887 *ptr = token;
1888 }
1767 return;1889 return;
1768 }1890 }
17691891
...@@ -2498,7 +2620,8 @@ pub const Parser = struct {...@@ -2498,7 +2620,8 @@ pub const Parser = struct {
2498 ast.NodeInfixOp.InfixOp.Sub => " - ",2620 ast.NodeInfixOp.InfixOp.Sub => " - ",
2499 ast.NodeInfixOp.InfixOp.SubWrap => " -% ",2621 ast.NodeInfixOp.InfixOp.SubWrap => " -% ",
2500 ast.NodeInfixOp.InfixOp.UnwrapMaybe => " ?? ",2622 ast.NodeInfixOp.InfixOp.UnwrapMaybe => " ?? ",
2501 else => unreachable,2623 ast.NodeInfixOp.InfixOp.Range => " ... ",
2624 ast.NodeInfixOp.InfixOp.Catch => unreachable,
2502 };2625 };
25032626
2504 try stack.append(RenderState { .Text = text });2627 try stack.append(RenderState { .Text = text });
...@@ -2821,8 +2944,73 @@ pub const Parser = struct {...@@ -2821,8 +2944,73 @@ pub const Parser = struct {
2821 },2944 },
2822 ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"),2945 ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"),
2823 ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"),2946 ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"),
2824 ast.Node.Id.Switch => @panic("TODO switch"),2947 ast.Node.Id.Switch => {
2825 ast.Node.Id.SwitchCase => @panic("TODO switch case"),2948 const switch_node = @fieldParentPtr(ast.NodeSwitch, "base", base);
2949 try stream.print("{} (", self.tokenizer.getTokenSlice(switch_node.switch_token));
2950
2951 try stack.append(RenderState { .Text = "}"});
2952 try stack.append(RenderState.PrintIndent);
2953 try stack.append(RenderState { .Indent = indent });
2954 try stack.append(RenderState { .Text = "\n"});
2955
2956 const cases = switch_node.cases.toSliceConst();
2957 var i = cases.len;
2958 while (i != 0) {
2959 i -= 1;
2960 const node = cases[i];
2961 try stack.append(RenderState { .Expression = &node.base});
2962 try stack.append(RenderState.PrintIndent);
2963 try stack.append(RenderState {
2964 .Text = blk: {
2965 if (i != 0) {
2966 const prev_node = cases[i - 1];
2967 const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, node.firstToken());
2968 if (loc.line >= 2) {
2969 break :blk "\n\n";
2970 }
2971 }
2972 break :blk "\n";
2973 },
2974 });
2975
2976 if (i != 0) {
2977 try stack.append(RenderState { .Text = "," });
2978 }
2979 }
2980 try stack.append(RenderState { .Indent = indent + indent_delta});
2981 try stack.append(RenderState { .Text = ") {"});
2982 try stack.append(RenderState { .Expression = switch_node.expr });
2983 },
2984 ast.Node.Id.SwitchCase => {
2985 const switch_case = @fieldParentPtr(ast.NodeSwitchCase, "base", base);
2986
2987 try stack.append(RenderState { .Expression = switch_case.expr });
2988 if (switch_case.capture) |capture| {
2989 try stack.append(RenderState { .Text = "| "});
2990 try stack.append(RenderState { .Expression = &capture.symbol.base });
2991
2992 if (capture.is_ptr) {
2993 try stack.append(RenderState { .Text = "*"});
2994 }
2995 try stack.append(RenderState { .Text = "|"});
2996 }
2997 try stack.append(RenderState { .Text = " => "});
2998
2999 const items = switch_case.items.toSliceConst();
3000 var i = items.len;
3001 while (i != 0) {
3002 i -= 1;
3003 try stack.append(RenderState { .Expression = items[i] });
3004
3005 if (i != 0) {
3006 try stack.append(RenderState { .Text = ", " });
3007 }
3008 }
3009 },
3010 ast.Node.Id.SwitchElse => {
3011 const switch_else = @fieldParentPtr(ast.NodeSwitchElse, "base", base);
3012 try stream.print("{}", self.tokenizer.getTokenSlice(switch_else.token));
3013 },
28263014
2827 ast.Node.Id.StructField,3015 ast.Node.Id.StructField,
2828 ast.Node.Id.UnionTag,3016 ast.Node.Id.UnionTag,
...@@ -2867,7 +3055,7 @@ pub const Parser = struct {...@@ -2867,7 +3055,7 @@ pub const Parser = struct {
2867 const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base);3055 const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base);
2868 try stack.append(RenderState { .VarDecl = var_decl});3056 try stack.append(RenderState { .VarDecl = var_decl});
2869 },3057 },
2870 ast.Node.Id.Block => {3058 ast.Node.Id.Block, ast.Node.Id.Switch => {
2871 try stack.append(RenderState { .Expression = base});3059 try stack.append(RenderState { .Expression = base});
2872 },3060 },
2873 else => {3061 else => {
...@@ -3436,24 +3624,24 @@ test "zig fmt: switch" {...@@ -3436,24 +3624,24 @@ test "zig fmt: switch" {
3436 \\ else => {3624 \\ else => {
3437 \\ const a = 1;3625 \\ const a = 1;
3438 \\ const b = a;3626 \\ const b = a;
3439 \\ },3627 \\ }
3440 \\ }3628 \\ }
3441 \\3629 \\
3442 \\ const res = switch (0) {3630 \\ const res = switch (0) {
3443 \\ 0 => 0,3631 \\ 0 => 0,
3444 \\ 1 => 2,3632 \\ 1 => 2,
3445 \\ else => 4,3633 \\ else => 4
3446 \\ };3634 \\ };
3447 \\3635 \\
3448 \\ const Union = union(enum) {3636 \\ const Union = union(enum) {
3449 \\ Int: i64,3637 \\ Int: i64,
3450 \\ Float: f64,3638 \\ Float: f64
3451 \\ };3639 \\ };
3452 \\3640 \\
3453 \\ const u = Union { .Int = 0 };3641 \\ const u = Union{ .Int = 0 };
3454 \\ switch (u) {3642 \\ switch (u) {
3455 \\ Union.Int => |int| {},3643 \\ Union.Int => |int| {},
3456 \\ Union.Float => |*float| unreachable,3644 \\ Union.Float => |*float| unreachable
3457 \\ }3645 \\ }
3458 \\}3646 \\}
3459 \\3647 \\
std/zig/tokenizer.zig+6
...@@ -86,6 +86,7 @@ pub const Token = struct {...@@ -86,6 +86,7 @@ pub const Token = struct {
86 PipeEqual,86 PipeEqual,
87 Equal,87 Equal,
88 EqualEqual,88 EqualEqual,
89 EqualAngleBracketRight,
89 BangEqual,90 BangEqual,
90 LParen,91 LParen,
91 RParen,92 RParen,
...@@ -688,6 +689,11 @@ pub const Tokenizer = struct {...@@ -688,6 +689,11 @@ pub const Tokenizer = struct {
688 self.index += 1;689 self.index += 1;
689 break;690 break;
690 },691 },
692 '>' => {
693 result.id = Token.Id.EqualAngleBracketRight;
694 self.index += 1;
695 break;
696 },
691 else => {697 else => {
692 result.id = Token.Id.Equal;698 result.id = Token.Id.Equal;
693 break;699 break;