authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-04 09:57:37+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-04 09:57:37+02:00
log09cf82361999c1a22819467e02fc68fd22ca188e
tree3928d070be9d88f7fdbc52d1c8fc323999b3b5da
parentec611bf8b47af0db5244af644040907bfcb63945

std.zig.parser now parses container decls


2 files changed, 176 insertions(+), 95 deletions(-)

std/zig/ast.zig+9-2
......@@ -214,12 +214,19 @@ pub const NodeVarDecl = struct {
214214
215215pub const NodeContainerDecl = struct {
216216 base: Node,
217 kind_token: Token,
217 ltoken: Token,
218 layout: Layout,
218219 kind: Kind,
219220 init_arg_expr: InitArg,
220221 fields_and_decls: ArrayList(&Node),
221222 rbrace_token: Token,
222223
224 const Layout = enum {
225 Auto,
226 Extern,
227 Packed,
228 };
229
223230 const Kind = enum {
224231 Struct,
225232 Enum,
......@@ -266,7 +273,7 @@ pub const NodeContainerDecl = struct {
266273 }
267274
268275 pub fn firstToken(self: &NodeContainerDecl) Token {
269 return self.kind_token;
276 return self.ltoken;
270277 }
271278
272279 pub fn lastToken(self: &NodeContainerDecl) Token {
std/zig/parser.zig+167-93
......@@ -59,6 +59,11 @@ pub const Parser = struct {
5959 lib_name: ?&ast.Node,
6060 };
6161
62 const ContainerExternCtx = struct {
63 ltoken: Token,
64 layout: ast.NodeContainerDecl.Layout,
65 };
66
6267 const DestPtr = union(enum) {
6368 Field: &&ast.Node,
6469 NullableField: &?&ast.Node,
......@@ -90,6 +95,7 @@ pub const Parser = struct {
9095 TopLevel,
9196 TopLevelExtern: TopLevelDeclCtx,
9297 TopLevelDecl: TopLevelDeclCtx,
98 ContainerExtern: ContainerExternCtx,
9399 ContainerDecl: &ast.NodeContainerDecl,
94100 Expression: DestPtr,
95101 ExpectOperand,
......@@ -338,6 +344,63 @@ pub const Parser = struct {
338344 return self.parseError(token, "expected '=' or ';', found {}", @tagName(token.id));
339345 },
340346
347 State.ContainerExtern => |ctx| {
348 const token = self.getNextToken();
349
350 const node = try arena.create(ast.NodeContainerDecl);
351 *node = ast.NodeContainerDecl {
352 .base = self.initNode(ast.Node.Id.ContainerDecl),
353 .ltoken = ctx.ltoken,
354 .layout = ctx.layout,
355 .kind = switch (token.id) {
356 Token.Id.Keyword_struct => ast.NodeContainerDecl.Kind.Struct,
357 Token.Id.Keyword_union => ast.NodeContainerDecl.Kind.Union,
358 Token.Id.Keyword_enum => ast.NodeContainerDecl.Kind.Enum,
359 else => {
360 return self.parseError(token, "expected {}, {} or {}, found {}",
361 @tagName(Token.Id.Keyword_struct),
362 @tagName(Token.Id.Keyword_union),
363 @tagName(Token.Id.Keyword_enum),
364 @tagName(token.id));
365 },
366 },
367 .init_arg_expr = undefined,
368 .fields_and_decls = ArrayList(&ast.Node).init(arena),
369 .rbrace_token = undefined,
370 };
371
372 try stack.append(State { .Operand = &node.base });
373 try stack.append(State.AfterOperand);
374 try stack.append(State { .ContainerDecl = node });
375 try stack.append(State { .ExpectToken = Token.Id.LBrace });
376
377 const lparen = self.getNextToken();
378 if (lparen.id != Token.Id.LParen) {
379 self.putBackToken(lparen);
380 node.init_arg_expr = ast.NodeContainerDecl.InitArg.None;
381 continue;
382 }
383
384 try stack.append(State { .ExpectToken = Token.Id.RParen });
385
386 const init_arg_token = self.getNextToken();
387 switch (init_arg_token.id) {
388 Token.Id.Keyword_enum => {
389 node.init_arg_expr = ast.NodeContainerDecl.InitArg.Enum;
390 },
391 else => {
392 self.putBackToken(init_arg_token);
393 node.init_arg_expr = ast.NodeContainerDecl.InitArg { .Type = undefined };
394 try stack.append(State {
395 .Expression = DestPtr {
396 .Field = &node.init_arg_expr.Type
397 }
398 });
399 },
400 }
401 continue;
402 },
403
341404 State.ContainerDecl => |container_decl| {
342405 const token = self.getNextToken();
343406
......@@ -633,52 +696,30 @@ pub const Parser = struct {
633696 try stack.append(State.AfterOperand);
634697 continue;
635698 },
636 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {
637 const node = try arena.create(ast.NodeContainerDecl);
638 *node = ast.NodeContainerDecl {
639 .base = self.initNode(ast.Node.Id.ContainerDecl),
640 .kind_token = token,
641 .kind = switch (token.id) {
642 Token.Id.Keyword_struct => ast.NodeContainerDecl.Kind.Struct,
643 Token.Id.Keyword_union => ast.NodeContainerDecl.Kind.Union,
644 Token.Id.Keyword_enum => ast.NodeContainerDecl.Kind.Enum,
645 else => unreachable,
699 Token.Id.Keyword_packed => {
700 try stack.append(State {
701 .ContainerExtern = ContainerExternCtx {
702 .ltoken = token,
703 .layout = ast.NodeContainerDecl.Layout.Packed,
646704 },
647 .init_arg_expr = undefined,
648 .fields_and_decls = ArrayList(&ast.Node).init(arena),
649 .rbrace_token = undefined,
650 };
651
652 try stack.append(State { .Operand = &node.base });
653 try stack.append(State.AfterOperand);
654 try stack.append(State { .ContainerDecl = node });
655 try stack.append(State { .ExpectToken = Token.Id.LBrace });
656
657 const lparen = self.getNextToken();
658 if (lparen.id != Token.Id.LParen) {
659 self.putBackToken(lparen);
660 node.init_arg_expr = ast.NodeContainerDecl.InitArg.None;
661 continue;
662 }
663
664 try stack.append(State { .ExpectToken = Token.Id.RParen });
665
666 const init_arg_token = self.getNextToken();
667 switch (init_arg_token.id) {
668 Token.Id.Keyword_enum => {
669 node.init_arg_expr = ast.NodeContainerDecl.InitArg.Enum;
705 });
706 },
707 Token.Id.Keyword_extern => {
708 try stack.append(State {
709 .ContainerExtern = ContainerExternCtx {
710 .ltoken = token,
711 .layout = ast.NodeContainerDecl.Layout.Extern,
670712 },
671 else => {
672 self.putBackToken(lparen);
673 node.init_arg_expr = ast.NodeContainerDecl.InitArg { .Type = undefined };
674 try stack.append(State {
675 .Expression = DestPtr {
676 .Field = &node.init_arg_expr.Type
677 }
678 });
713 });
714 },
715 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {
716 self.putBackToken(token);
717 try stack.append(State {
718 .ContainerExtern = ContainerExternCtx {
719 .ltoken = token,
720 .layout = ast.NodeContainerDecl.Layout.Auto,
679721 },
680 }
681 continue;
722 });
682723 },
683724 Token.Id.Builtin => {
684725 const node = try arena.create(ast.NodeBuiltinCall);
......@@ -1706,6 +1747,29 @@ pub const Parser = struct {
17061747 try stack.append(RenderState { .Text = " " });
17071748 try stack.append(RenderState { .Expression = test_decl.name });
17081749 },
1750 ast.Node.Id.StructField => {
1751 const field = @fieldParentPtr(ast.NodeStructField, "base", decl);
1752 try stream.print("{}: ", self.tokenizer.getTokenSlice(field.name_token));
1753 try stack.append(RenderState { .Expression = field.type_expr});
1754 },
1755 ast.Node.Id.UnionTag => {
1756 const tag = @fieldParentPtr(ast.NodeUnionTag, "base", decl);
1757 try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token));
1758
1759 if (tag.type_expr) |type_expr| {
1760 try stream.print(": ");
1761 try stack.append(RenderState { .Expression = type_expr});
1762 }
1763 },
1764 ast.Node.Id.EnumTag => {
1765 const tag = @fieldParentPtr(ast.NodeEnumTag, "base", decl);
1766 try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token));
1767
1768 if (tag.value) |value| {
1769 try stream.print(" = ");
1770 try stack.append(RenderState { .Expression = value});
1771 }
1772 },
17091773 else => unreachable,
17101774 }
17111775 },
......@@ -1990,27 +2054,30 @@ pub const Parser = struct {
19902054 },
19912055 ast.Node.Id.ContainerDecl => {
19922056 const container_decl = @fieldParentPtr(ast.NodeContainerDecl, "base", base);
1993 try stream.print("{} {{", self.tokenizer.getTokenSlice(container_decl.kind_token));
2057
2058 switch (container_decl.layout) {
2059 ast.NodeContainerDecl.Layout.Packed => try stream.print("packed "),
2060 ast.NodeContainerDecl.Layout.Extern => try stream.print("extern "),
2061 ast.NodeContainerDecl.Layout.Auto => { },
2062 }
2063
2064 switch (container_decl.kind) {
2065 ast.NodeContainerDecl.Kind.Struct => try stream.print("struct"),
2066 ast.NodeContainerDecl.Kind.Enum => try stream.print("enum"),
2067 ast.NodeContainerDecl.Kind.Union => try stream.print("union"),
2068 }
2069
19942070 try stack.append(RenderState { .Text = "}"});
19952071 try stack.append(RenderState.PrintIndent);
19962072 try stack.append(RenderState { .Indent = indent });
2073 try stack.append(RenderState { .Text = "\n"});
19972074
19982075 const fields_and_decls = container_decl.fields_and_decls.toSliceConst();
19992076 var i = fields_and_decls.len;
20002077 while (i != 0) {
20012078 i -= 1;
20022079 const node = fields_and_decls[i];
2003 if (i != 0) {
2004 switch (node.id) {
2005 ast.Node.Id.StructField,
2006 ast.Node.Id.UnionTag,
2007 ast.Node.Id.EnumTag => {
2008 try stack.append(RenderState { .Text = "," });
2009 },
2010 else => { }
2011 }
2012 }
2013 try stack.append(RenderState { .Expression = node});
2080 try stack.append(RenderState { .TopLevelDecl = node});
20142081 try stack.append(RenderState.PrintIndent);
20152082 try stack.append(RenderState {
20162083 .Text = blk: {
......@@ -2025,22 +2092,43 @@ pub const Parser = struct {
20252092 break :blk "\n";
20262093 },
20272094 });
2095
2096 if (i != 0) {
2097 const prev_node = fields_and_decls[i - 1];
2098 switch (prev_node.id) {
2099 ast.Node.Id.StructField,
2100 ast.Node.Id.UnionTag,
2101 ast.Node.Id.EnumTag => {
2102 try stack.append(RenderState { .Text = "," });
2103 },
2104 else => { }
2105 }
2106 }
20282107 }
20292108 try stack.append(RenderState { .Indent = indent + indent_delta});
2109 try stack.append(RenderState { .Text = "{"});
2110
2111 switch (container_decl.init_arg_expr) {
2112 ast.NodeContainerDecl.InitArg.None => try stack.append(RenderState { .Text = " "}),
2113 ast.NodeContainerDecl.InitArg.Enum => try stack.append(RenderState { .Text = "(enum) "}),
2114 ast.NodeContainerDecl.InitArg.Type => |type_expr| {
2115 try stack.append(RenderState { .Text = ") "});
2116 try stack.append(RenderState { .Expression = type_expr});
2117 try stack.append(RenderState { .Text = "("});
2118 },
2119 }
20302120 },
20312121 ast.Node.Id.MultilineStringLiteral => {
20322122 const multiline_str_literal = @fieldParentPtr(ast.NodeMultilineStringLiteral, "base", base);
20332123 try stream.print("\n");
20342124
20352125 var i : usize = 0;
2036 indent += 4;
20372126 while (i < multiline_str_literal.tokens.len) : (i += 1) {
20382127 const t = multiline_str_literal.tokens.at(i);
2039 try stream.writeByteNTimes(' ', indent);
2128 try stream.writeByteNTimes(' ', indent + indent_delta);
20402129 try stream.print("{}", self.tokenizer.getTokenSlice(t));
20412130 }
2042 try stream.writeByteNTimes(' ', indent);
2043 indent -= 4;
2131 try stream.writeByteNTimes(' ', indent + indent_delta);
20442132 },
20452133 ast.Node.Id.UndefinedLiteral => {
20462134 const undefined_literal = @fieldParentPtr(ast.NodeUndefinedLiteral, "base", base);
......@@ -2060,31 +2148,12 @@ pub const Parser = struct {
20602148 }
20612149 }
20622150 },
2063 ast.Node.Id.StructField => {
2064 const field = @fieldParentPtr(ast.NodeStructField, "base", base);
2065 try stream.print("{}:", self.tokenizer.getTokenSlice(field.name_token));
2066 },
2067 ast.Node.Id.UnionTag => {
2068 const tag = @fieldParentPtr(ast.NodeUnionTag, "base", base);
2069 try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token));
2070
2071 if (tag.type_expr) |type_expr| {
2072 try stream.print(": ");
2073 try stack.append(RenderState { .Expression = type_expr});
2074 }
2075 },
2076 ast.Node.Id.EnumTag => {
2077 const tag = @fieldParentPtr(ast.NodeEnumTag, "base", base);
2078 try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token));
2079
2080 if (tag.value) |value| {
2081 try stream.print(" = ");
2082 try stack.append(RenderState { .Expression = value});
2083 }
2084 },
20852151 ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"),
20862152 ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"),
20872153
2154 ast.Node.Id.StructField,
2155 ast.Node.Id.UnionTag,
2156 ast.Node.Id.EnumTag,
20882157 ast.Node.Id.Root,
20892158 ast.Node.Id.VarDecl,
20902159 ast.Node.Id.TestDecl,
......@@ -2489,21 +2558,21 @@ test "zig fmt: struct declaration" {
24892558 \\ return *self;
24902559 \\ }
24912560 \\
2492 \\ f2: u8,
2561 \\ f2: u8
24932562 \\};
24942563 \\
24952564 \\const Ps = packed struct {
24962565 \\ a: u8,
24972566 \\ b: u8,
24982567 \\
2499 \\ c: u8,
2568 \\ c: u8
25002569 \\};
25012570 \\
25022571 \\const Es = extern struct {
25032572 \\ a: u8,
25042573 \\ b: u8,
25052574 \\
2506 \\ c: u8,
2575 \\ c: u8
25072576 \\};
25082577 \\
25092578 );
......@@ -2513,25 +2582,25 @@ test "zig fmt: enum declaration" {
25132582 try testCanonical(
25142583 \\const E = enum {
25152584 \\ Ok,
2516 \\ SomethingElse = 0,
2585 \\ SomethingElse = 0
25172586 \\};
25182587 \\
25192588 \\const E2 = enum(u8) {
25202589 \\ Ok,
25212590 \\ SomethingElse = 255,
2522 \\ SomethingThird,
2591 \\ SomethingThird
25232592 \\};
25242593 \\
25252594 \\const Ee = extern enum {
25262595 \\ Ok,
25272596 \\ SomethingElse,
2528 \\ SomethingThird,
2597 \\ SomethingThird
25292598 \\};
25302599 \\
25312600 \\const Ep = packed enum {
25322601 \\ Ok,
25332602 \\ SomethingElse,
2534 \\ SomethingThird,
2603 \\ SomethingThird
25352604 \\};
25362605 \\
25372606 );
......@@ -2542,31 +2611,36 @@ test "zig fmt: union declaration" {
25422611 \\const U = union {
25432612 \\ Int: u8,
25442613 \\ Float: f32,
2545 \\ Bool: bool,
2614 \\ None,
2615 \\ Bool: bool
25462616 \\};
25472617 \\
25482618 \\const Ue = union(enum) {
25492619 \\ Int: u8,
25502620 \\ Float: f32,
2551 \\ Bool: bool,
2621 \\ None,
2622 \\ Bool: bool
25522623 \\};
25532624 \\
25542625 \\const E = enum {
25552626 \\ Int,
25562627 \\ Float,
2557 \\ Bool,
2628 \\ None,
2629 \\ Bool
25582630 \\};
25592631 \\
25602632 \\const Ue2 = union(E) {
25612633 \\ Int: u8,
25622634 \\ Float: f32,
2563 \\ Bool: bool,
2635 \\ None,
2636 \\ Bool: bool
25642637 \\};
25652638 \\
25662639 \\const Eu = extern union {
25672640 \\ Int: u8,
25682641 \\ Float: f32,
2569 \\ Bool: bool,
2642 \\ None,
2643 \\ Bool: bool
25702644 \\};
25712645 \\
25722646 );