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 {
2020 FnProto,
2121 ParamDecl,
2222 Block,
23 Switch,
24 SwitchCase,
2325 InfixOp,
2426 PrefixOp,
2527 SuffixOp,
......@@ -55,6 +57,8 @@ pub const Node = struct {
5557 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),
5658 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),
5759 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),
5862 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
5963 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),
6064 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index),
......@@ -91,6 +95,8 @@ pub const Node = struct {
9195 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(),
9296 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),
9397 Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
98 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
99 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),
94100 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),
95101 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),
96102 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(),
......@@ -127,6 +133,8 @@ pub const Node = struct {
127133 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(),
128134 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),
129135 Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
136 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),
137 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),
130138 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),
131139 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),
132140 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(),
......@@ -506,9 +514,10 @@ pub const NodeParamDecl = struct {
506514
507515pub const NodeBlock = struct {
508516 base: Node,
509 begin_token: Token,
510 end_token: Token,
517 label: ?Token,
518 lbrace: Token,
511519 statements: ArrayList(&Node),
520 rbrace: Token,
512521
513522 pub fn iterate(self: &NodeBlock, index: usize) ?&Node {
514523 var i = index;
......@@ -520,11 +529,80 @@ pub const NodeBlock = struct {
520529 }
521530
522531 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;
524537 }
525538
526539 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();
528606 }
529607};
530608
......@@ -575,6 +653,7 @@ pub const NodeInfixOp = struct {
575653 Mult,
576654 MultWrap,
577655 Period,
656 Range,
578657 Sub,
579658 SubWrap,
580659 UnwrapMaybe,
......@@ -625,6 +704,7 @@ pub const NodeInfixOp = struct {
625704 InfixOp.Mult,
626705 InfixOp.MultWrap,
627706 InfixOp.Period,
707 InfixOp.Range,
628708 InfixOp.Sub,
629709 InfixOp.SubWrap,
630710 InfixOp.UnwrapMaybe => {},
std/zig/parser.zig+131-30
......@@ -146,6 +146,8 @@ pub const Parser = struct {
146146 Required,
147147
148148 Expression: DestPtr,
149 RangeExpressionBegin: DestPtr,
150 RangeExpressionEnd: DestPtr,
149151 AssignmentExpressionBegin: DestPtr,
150152 AssignmentExpressionEnd: DestPtr,
151153 UnwrapExpressionBegin: DestPtr,
......@@ -256,7 +258,7 @@ pub const Parser = struct {
256258 }
257259
258260 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);
260262 const test_decl = try self.createAttachTestDecl(arena, &root_node.decls, token, &name.base, block);
261263 stack.append(State { .Block = block }) catch unreachable;
262264 continue;
......@@ -643,6 +645,27 @@ pub const Parser = struct {
643645 }
644646 },
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
646669 State.AssignmentExpressionBegin => |dest_ptr| {
647670 stack.append(State { .AssignmentExpressionEnd = dest_ptr }) catch unreachable;
648671 try stack.append(State { .UnwrapExpressionBegin = dest_ptr });
......@@ -1205,10 +1228,6 @@ pub const Parser = struct {
12051228 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
12061229 continue;
12071230 },
1208 Token.Id.Identifier => {
1209 dest_ptr.store(&(try self.createIdentifier(arena, token)).base);
1210 continue;
1211 },
12121231 Token.Id.Builtin => {
12131232 const node = try arena.create(ast.NodeBuiltinCall);
12141233 *node = ast.NodeBuiltinCall {
......@@ -1348,8 +1367,32 @@ pub const Parser = struct {
13481367 },
13491368 }) catch unreachable;
13501369 },
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 },
13511390 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;
13531396 },
13541397 Token.Id.Keyword_fn => {
13551398 @panic("TODO: fn proto");
......@@ -1618,7 +1661,7 @@ pub const Parser = struct {
16181661 const token = self.getNextToken();
16191662 switch(token.id) {
16201663 Token.Id.LBrace => {
1621 const block = try self.createBlock(arena, token);
1664 const block = try self.createBlock(arena, (?Token)(null), token);
16221665 fn_proto.body_node = &block.base;
16231666 stack.append(State { .Block = block }) catch unreachable;
16241667 continue;
......@@ -1635,7 +1678,7 @@ pub const Parser = struct {
16351678 const token = self.getNextToken();
16361679 switch (token.id) {
16371680 Token.Id.RBrace => {
1638 block.end_token = token;
1681 block.rbrace = token;
16391682 continue;
16401683 },
16411684 else => {
......@@ -1648,38 +1691,64 @@ pub const Parser = struct {
16481691 },
16491692
16501693 State.Statement => |block| {
1651 {
1652 // Look for comptime var, comptime const
1653 const comptime_token = self.getNextToken();
1654 if (comptime_token.id == Token.Id.Keyword_comptime) {
1694 const next = self.getNextToken();
1695 switch (next.id) {
1696 Token.Id.Keyword_comptime => {
16551697 const mut_token = self.getNextToken();
16561698 if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {
16571699 // TODO shouldn't need these casts
16581700 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);
16601702 stack.append(State { .VarDecl = var_decl }) catch unreachable;
16611703 continue;
1704 } else {
1705 self.putBackToken(mut_token);
1706 @panic("TODO: comptime block");
16621707 }
1663 self.putBackToken(mut_token);
1664 }
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
1708 },
1709 Token.Id.Keyword_var, Token.Id.Keyword_const => {
16721710 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);
16741712 stack.append(State { .VarDecl = var_decl }) catch unreachable;
16751713 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;
16761749 }
1677 self.putBackToken(mut_token);
16781750 }
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;
16831752 },
16841753 }
16851754 }
......@@ -1905,14 +1974,15 @@ pub const Parser = struct {
19051974 return node;
19061975 }
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 {
19091978 const node = try arena.create(ast.NodeBlock);
19101979
19111980 *node = ast.NodeBlock {
19121981 .base = self.initNode(ast.Node.Id.Block),
1913 .begin_token = *begin_token,
1914 .end_token = undefined,
1982 .label = *label,
1983 .lbrace = *lbrace,
19151984 .statements = ArrayList(&ast.Node).init(arena),
1985 .rbrace = undefined,
19161986 };
19171987 return node;
19181988 }
......@@ -2340,6 +2410,10 @@ pub const Parser = struct {
23402410 },
23412411 ast.Node.Id.Block => {
23422412 const block = @fieldParentPtr(ast.NodeBlock, "base", base);
2413 if (block.label) |label| {
2414 try stream.print("{}: ", self.tokenizer.getTokenSlice(label));
2415 }
2416
23432417 if (block.statements.len == 0) {
23442418 try stream.write("{}");
23452419 } else {
......@@ -2747,6 +2821,8 @@ pub const Parser = struct {
27472821 },
27482822 ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"),
27492823 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
27512827 ast.Node.Id.StructField,
27522828 ast.Node.Id.UnionTag,
......@@ -2791,6 +2867,9 @@ pub const Parser = struct {
27912867 const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base);
27922868 try stack.append(RenderState { .VarDecl = var_decl});
27932869 },
2870 ast.Node.Id.Block => {
2871 try stack.append(RenderState { .Expression = base});
2872 },
27942873 else => {
27952874 try stack.append(RenderState { .Text = ";"});
27962875 try stack.append(RenderState { .Expression = base});
......@@ -3323,6 +3402,28 @@ test "zig fmt: catch" {
33233402 );
33243403}
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
33263427test "zig fmt: switch" {
33273428 try testCanonical(
33283429 \\test "switch" {