authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-06 15:37:49+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-06 15:37:49+02:00
log820de1716b83ee99ed94461996ca592a302eccae
tree5ba081a342a6c8a1f5b6e8a2fc586f61274b6151
parentf667744d44b0fc3599c85c01d3fcf3b63c4e68a6

std.zig.parser now parses labeled blocks.

* There is also some code for switch range parsing

2 files changed, 215 insertions(+), 34 deletions(-)

std/zig/ast.zig+84-4
...@@ -20,6 +20,8 @@ pub const Node = struct {...@@ -20,6 +20,8 @@ pub const Node = struct {
20 FnProto,20 FnProto,
21 ParamDecl,21 ParamDecl,
22 Block,22 Block,
23 Switch,
24 SwitchCase,
23 InfixOp,25 InfixOp,
24 PrefixOp,26 PrefixOp,
25 SuffixOp,27 SuffixOp,
...@@ -55,6 +57,8 @@ pub const Node = struct {...@@ -55,6 +57,8 @@ pub const Node = struct {
55 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),57 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),
56 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),58 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),
57 Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),59 Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
60 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
61 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index),
58 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),62 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
59 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),63 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),
60 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index),64 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index),
...@@ -91,6 +95,8 @@ pub const Node = struct {...@@ -91,6 +95,8 @@ pub const Node = struct {
91 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(),95 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(),
92 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),96 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),
93 Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),97 Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
98 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
99 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),
94 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),100 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),
95 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),101 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),
96 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(),102 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(),
...@@ -127,6 +133,8 @@ pub const Node = struct {...@@ -127,6 +133,8 @@ pub const Node = struct {
127 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(),133 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(),
128 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),134 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),
129 Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),135 Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
136 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),
137 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),
130 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),138 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),
131 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),139 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),
132 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(),140 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(),
...@@ -506,9 +514,10 @@ pub const NodeParamDecl = struct {...@@ -506,9 +514,10 @@ pub const NodeParamDecl = struct {
506514
507pub const NodeBlock = struct {515pub const NodeBlock = struct {
508 base: Node,516 base: Node,
509 begin_token: Token,517 label: ?Token,
510 end_token: Token,518 lbrace: Token,
511 statements: ArrayList(&Node),519 statements: ArrayList(&Node),
520 rbrace: Token,
512521
513 pub fn iterate(self: &NodeBlock, index: usize) ?&Node {522 pub fn iterate(self: &NodeBlock, index: usize) ?&Node {
514 var i = index;523 var i = index;
...@@ -520,11 +529,80 @@ pub const NodeBlock = struct {...@@ -520,11 +529,80 @@ pub const NodeBlock = struct {
520 }529 }
521530
522 pub fn firstToken(self: &NodeBlock) Token {531 pub fn firstToken(self: &NodeBlock) Token {
523 return self.begin_token;532 if (self.label) |label| {
533 return label;
534 }
535
536 return self.lbrace;
524 }537 }
525538
526 pub fn lastToken(self: &NodeBlock) Token {539 pub fn lastToken(self: &NodeBlock) Token {
527 return self.end_token;540 return self.rbrace;
541 }
542};
543
544pub const NodeSwitch = struct {
545 base: Node,
546 switch_token: Token,
547 expr: &Node,
548 cases: ArrayList(&NodeSwitchCase),
549 rbrace: Token,
550
551 pub fn iterate(self: &NodeSwitch, index: usize) ?&Node {
552 var i = index;
553
554 if (i < 1) return self.expr;
555 i -= 1;
556
557 if (i < self.cases.len) return self.cases.at(i);
558 i -= self.cases.len;
559
560 return null;
561 }
562
563 pub fn firstToken(self: &NodeSwitch) Token {
564 return self.switch_token;
565 }
566
567 pub fn lastToken(self: &NodeSwitch) Token {
568 return self.rbrace;
569 }
570};
571
572pub const NodeSwitchCase = struct {
573 base: Node,
574 items: ArrayList(&Node),
575 capture: ?Capture,
576 expr: &Node,
577
578 const Capture = struct {
579 symbol: &NodeIdentifier,
580 is_ptr: bool,
581 };
582
583 pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node {
584 var i = index;
585
586 if (i < self.items.len) return self.items.at(i);
587 i -= self.items.len;
588
589 if (self.capture) |capture| {
590 if (i < 1) return &capture.base;
591 i -= 1;
592 }
593
594 if (i < 1) return self.expr;
595 i -= 1;
596
597 return null;
598 }
599
600 pub fn firstToken(self: &NodeSwitchCase) Token {
601 return self.items.at(0).firstToken();
602 }
603
604 pub fn lastToken(self: &NodeSwitchCase) Token {
605 return self.expr.lastToken();
528 }606 }
529};607};
530608
...@@ -575,6 +653,7 @@ pub const NodeInfixOp = struct {...@@ -575,6 +653,7 @@ pub const NodeInfixOp = struct {
575 Mult,653 Mult,
576 MultWrap,654 MultWrap,
577 Period,655 Period,
656 Range,
578 Sub,657 Sub,
579 SubWrap,658 SubWrap,
580 UnwrapMaybe,659 UnwrapMaybe,
...@@ -625,6 +704,7 @@ pub const NodeInfixOp = struct {...@@ -625,6 +704,7 @@ pub const NodeInfixOp = struct {
625 InfixOp.Mult,704 InfixOp.Mult,
626 InfixOp.MultWrap,705 InfixOp.MultWrap,
627 InfixOp.Period,706 InfixOp.Period,
707 InfixOp.Range,
628 InfixOp.Sub,708 InfixOp.Sub,
629 InfixOp.SubWrap,709 InfixOp.SubWrap,
630 InfixOp.UnwrapMaybe => {},710 InfixOp.UnwrapMaybe => {},
std/zig/parser.zig+131-30
...@@ -146,6 +146,8 @@ pub const Parser = struct {...@@ -146,6 +146,8 @@ pub const Parser = struct {
146 Required,146 Required,
147147
148 Expression: DestPtr,148 Expression: DestPtr,
149 RangeExpressionBegin: DestPtr,
150 RangeExpressionEnd: DestPtr,
149 AssignmentExpressionBegin: DestPtr,151 AssignmentExpressionBegin: DestPtr,
150 AssignmentExpressionEnd: DestPtr,152 AssignmentExpressionEnd: DestPtr,
151 UnwrapExpressionBegin: DestPtr,153 UnwrapExpressionBegin: DestPtr,
...@@ -256,7 +258,7 @@ pub const Parser = struct {...@@ -256,7 +258,7 @@ pub const Parser = struct {
256 }258 }
257259
258 const name = try self.createStringLiteral(arena, name_token);260 const name = try self.createStringLiteral(arena, name_token);
259 const block = try self.createBlock(arena, token);261 const block = try self.createBlock(arena, (?Token)(null), token);
260 const test_decl = try self.createAttachTestDecl(arena, &root_node.decls, token, &name.base, block);262 const test_decl = try self.createAttachTestDecl(arena, &root_node.decls, token, &name.base, block);
261 stack.append(State { .Block = block }) catch unreachable;263 stack.append(State { .Block = block }) catch unreachable;
262 continue;264 continue;
...@@ -643,6 +645,27 @@ pub const Parser = struct {...@@ -643,6 +645,27 @@ pub const Parser = struct {
643 }645 }
644 },646 },
645647
648 State.RangeExpressionBegin => |dest_ptr| {
649 stack.append(State { .RangeExpressionEnd = dest_ptr }) catch unreachable;
650 try stack.append(State { .Expression = dest_ptr });
651 continue;
652 },
653
654 State.RangeExpressionEnd => |dest_ptr| {
655 const token = self.getNextToken();
656 if (token.id == Token.Id.Ellipsis3) {
657 const node = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.Range);
658 node.lhs = dest_ptr.get();
659 dest_ptr.store(&node.base);
660
661 stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }) catch unreachable;
662 continue;
663 } else {
664 self.putBackToken(token);
665 continue;
666 }
667 },
668
646 State.AssignmentExpressionBegin => |dest_ptr| {669 State.AssignmentExpressionBegin => |dest_ptr| {
647 stack.append(State { .AssignmentExpressionEnd = dest_ptr }) catch unreachable;670 stack.append(State { .AssignmentExpressionEnd = dest_ptr }) catch unreachable;
648 try stack.append(State { .UnwrapExpressionBegin = dest_ptr });671 try stack.append(State { .UnwrapExpressionBegin = dest_ptr });
...@@ -1205,10 +1228,6 @@ pub const Parser = struct {...@@ -1205,10 +1228,6 @@ pub const Parser = struct {
1205 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });1228 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
1206 continue;1229 continue;
1207 },1230 },
1208 Token.Id.Identifier => {
1209 dest_ptr.store(&(try self.createIdentifier(arena, token)).base);
1210 continue;
1211 },
1212 Token.Id.Builtin => {1231 Token.Id.Builtin => {
1213 const node = try arena.create(ast.NodeBuiltinCall);1232 const node = try arena.create(ast.NodeBuiltinCall);
1214 *node = ast.NodeBuiltinCall {1233 *node = ast.NodeBuiltinCall {
...@@ -1348,8 +1367,32 @@ pub const Parser = struct {...@@ -1348,8 +1367,32 @@ pub const Parser = struct {
1348 },1367 },
1349 }) catch unreachable;1368 }) catch unreachable;
1350 },1369 },
1370 Token.Id.Identifier => {
1371 const next = self.getNextToken();
1372 if (next.id != Token.Id.Colon) {
1373 self.putBackToken(next);
1374 dest_ptr.store(&(try self.createIdentifier(arena, token)).base);
1375 continue;
1376 }
1377
1378 const block = try self.createBlock(arena, (?Token)(token), Token(undefined));
1379 dest_ptr.store(&block.base);
1380
1381 stack.append(State { .Block = block }) catch unreachable;
1382 try stack.append(State {
1383 .ExpectTokenSave = ExpectTokenSave {
1384 .id = Token.Id.LBrace,
1385 .ptr = &block.lbrace,
1386 }
1387 });
1388 continue;
1389 },
1351 Token.Id.LBrace => {1390 Token.Id.LBrace => {
1352 @panic("TODO: Block expr");1391 const block = try self.createBlock(arena, (?Token)(null), token);
1392 dest_ptr.store(&block.base);
1393
1394 stack.append(State { .Block = block }) catch unreachable;
1395 continue;
1353 },1396 },
1354 Token.Id.Keyword_fn => {1397 Token.Id.Keyword_fn => {
1355 @panic("TODO: fn proto");1398 @panic("TODO: fn proto");
...@@ -1618,7 +1661,7 @@ pub const Parser = struct {...@@ -1618,7 +1661,7 @@ pub const Parser = struct {
1618 const token = self.getNextToken();1661 const token = self.getNextToken();
1619 switch(token.id) {1662 switch(token.id) {
1620 Token.Id.LBrace => {1663 Token.Id.LBrace => {
1621 const block = try self.createBlock(arena, token);1664 const block = try self.createBlock(arena, (?Token)(null), token);
1622 fn_proto.body_node = &block.base;1665 fn_proto.body_node = &block.base;
1623 stack.append(State { .Block = block }) catch unreachable;1666 stack.append(State { .Block = block }) catch unreachable;
1624 continue;1667 continue;
...@@ -1635,7 +1678,7 @@ pub const Parser = struct {...@@ -1635,7 +1678,7 @@ pub const Parser = struct {
1635 const token = self.getNextToken();1678 const token = self.getNextToken();
1636 switch (token.id) {1679 switch (token.id) {
1637 Token.Id.RBrace => {1680 Token.Id.RBrace => {
1638 block.end_token = token;1681 block.rbrace = token;
1639 continue;1682 continue;
1640 },1683 },
1641 else => {1684 else => {
...@@ -1648,38 +1691,64 @@ pub const Parser = struct {...@@ -1648,38 +1691,64 @@ pub const Parser = struct {
1648 },1691 },
16491692
1650 State.Statement => |block| {1693 State.Statement => |block| {
1651 {1694 const next = self.getNextToken();
1652 // Look for comptime var, comptime const1695 switch (next.id) {
1653 const comptime_token = self.getNextToken();1696 Token.Id.Keyword_comptime => {
1654 if (comptime_token.id == Token.Id.Keyword_comptime) {
1655 const mut_token = self.getNextToken();1697 const mut_token = self.getNextToken();
1656 if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {1698 if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {
1657 // TODO shouldn't need these casts1699 // TODO shouldn't need these casts
1658 const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),1700 const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),
1659 mut_token, (?Token)(comptime_token), (?Token)(null), null);1701 mut_token, (?Token)(next), (?Token)(null), null);
1660 stack.append(State { .VarDecl = var_decl }) catch unreachable;1702 stack.append(State { .VarDecl = var_decl }) catch unreachable;
1661 continue;1703 continue;
1704 } else {
1705 self.putBackToken(mut_token);
1706 @panic("TODO: comptime block");
1662 }1707 }
1663 self.putBackToken(mut_token);1708 },
1664 }1709 Token.Id.Keyword_var, Token.Id.Keyword_const => {
1665 self.putBackToken(comptime_token);
1666 }
1667 {
1668 // Look for const, var
1669 const mut_token = self.getNextToken();
1670 if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {
1671 // TODO shouldn't need these casts
1672 const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),1710 const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),
1673 mut_token, (?Token)(null), (?Token)(null), null);1711 next, (?Token)(null), (?Token)(null), null);
1674 stack.append(State { .VarDecl = var_decl }) catch unreachable;1712 stack.append(State { .VarDecl = var_decl }) catch unreachable;
1675 continue;1713 continue;
1714 },
1715 Token.Id.Identifier => {
1716 const maybe_colon = self.getNextToken();
1717 if (maybe_colon.id != Token.Id.Colon) {
1718 self.putBackToken(maybe_colon);
1719 self.putBackToken(next);
1720 stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
1721 try stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } });
1722 continue;
1723 }
1724
1725 const inner_block = try self.createBlock(arena, (?Token)(next), Token(undefined));
1726 try block.statements.append(&inner_block.base);
1727
1728 stack.append(State { .Block = inner_block }) catch unreachable;
1729 try stack.append(State {
1730 .ExpectTokenSave = ExpectTokenSave {
1731 .id = Token.Id.LBrace,
1732 .ptr = &inner_block.lbrace,
1733 }
1734 });
1735 continue;
1736 },
1737 Token.Id.LBrace => {
1738 const inner_block = try self.createBlock(arena, (?Token)(null), next);
1739 try block.statements.append(&inner_block.base);
1740
1741 stack.append(State { .Block = inner_block }) catch unreachable;
1742 continue;
1743 },
1744 else => {
1745 self.putBackToken(next);
1746 stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
1747 try stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } });
1748 continue;
1676 }1749 }
1677 self.putBackToken(mut_token);
1678 }1750 }
16791751
1680 stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
1681 try stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } });
1682 continue;
1683 },1752 },
1684 }1753 }
1685 }1754 }
...@@ -1905,14 +1974,15 @@ pub const Parser = struct {...@@ -1905,14 +1974,15 @@ pub const Parser = struct {
1905 return node;1974 return node;
1906 }1975 }
19071976
1908 fn createBlock(self: &Parser, arena: &mem.Allocator, begin_token: &const Token) !&ast.NodeBlock {1977 fn createBlock(self: &Parser, arena: &mem.Allocator, label: &const ?Token, lbrace: &const Token) !&ast.NodeBlock {
1909 const node = try arena.create(ast.NodeBlock);1978 const node = try arena.create(ast.NodeBlock);
19101979
1911 *node = ast.NodeBlock {1980 *node = ast.NodeBlock {
1912 .base = self.initNode(ast.Node.Id.Block),1981 .base = self.initNode(ast.Node.Id.Block),
1913 .begin_token = *begin_token,1982 .label = *label,
1914 .end_token = undefined,1983 .lbrace = *lbrace,
1915 .statements = ArrayList(&ast.Node).init(arena),1984 .statements = ArrayList(&ast.Node).init(arena),
1985 .rbrace = undefined,
1916 };1986 };
1917 return node;1987 return node;
1918 }1988 }
...@@ -2340,6 +2410,10 @@ pub const Parser = struct {...@@ -2340,6 +2410,10 @@ pub const Parser = struct {
2340 },2410 },
2341 ast.Node.Id.Block => {2411 ast.Node.Id.Block => {
2342 const block = @fieldParentPtr(ast.NodeBlock, "base", base);2412 const block = @fieldParentPtr(ast.NodeBlock, "base", base);
2413 if (block.label) |label| {
2414 try stream.print("{}: ", self.tokenizer.getTokenSlice(label));
2415 }
2416
2343 if (block.statements.len == 0) {2417 if (block.statements.len == 0) {
2344 try stream.write("{}");2418 try stream.write("{}");
2345 } else {2419 } else {
...@@ -2747,6 +2821,8 @@ pub const Parser = struct {...@@ -2747,6 +2821,8 @@ pub const Parser = struct {
2747 },2821 },
2748 ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"),2822 ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"),
2749 ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"),2823 ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"),
2824 ast.Node.Id.Switch => @panic("TODO switch"),
2825 ast.Node.Id.SwitchCase => @panic("TODO switch case"),
27502826
2751 ast.Node.Id.StructField,2827 ast.Node.Id.StructField,
2752 ast.Node.Id.UnionTag,2828 ast.Node.Id.UnionTag,
...@@ -2791,6 +2867,9 @@ pub const Parser = struct {...@@ -2791,6 +2867,9 @@ pub const Parser = struct {
2791 const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base);2867 const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base);
2792 try stack.append(RenderState { .VarDecl = var_decl});2868 try stack.append(RenderState { .VarDecl = var_decl});
2793 },2869 },
2870 ast.Node.Id.Block => {
2871 try stack.append(RenderState { .Expression = base});
2872 },
2794 else => {2873 else => {
2795 try stack.append(RenderState { .Text = ";"});2874 try stack.append(RenderState { .Text = ";"});
2796 try stack.append(RenderState { .Expression = base});2875 try stack.append(RenderState { .Expression = base});
...@@ -3323,6 +3402,28 @@ test "zig fmt: catch" {...@@ -3323,6 +3402,28 @@ test "zig fmt: catch" {
3323 );3402 );
3324}3403}
33253404
3405test "zig fmt: blocks" {
3406 try testCanonical(
3407 \\test "blocks" {
3408 \\ {
3409 \\ const a = 0;
3410 \\ const b = 0;
3411 \\ }
3412 \\
3413 \\ blk: {
3414 \\ const a = 0;
3415 \\ const b = 0;
3416 \\ }
3417 \\
3418 \\ const r = blk: {
3419 \\ const a = 0;
3420 \\ const b = 0;
3421 \\ };
3422 \\}
3423 \\
3424 );
3425}
3426
3326test "zig fmt: switch" {3427test "zig fmt: switch" {
3327 try testCanonical(3428 try testCanonical(
3328 \\test "switch" {3429 \\test "switch" {