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 {...@@ -214,12 +214,19 @@ pub const NodeVarDecl = struct {
214214
215pub const NodeContainerDecl = struct {215pub const NodeContainerDecl = struct {
216 base: Node,216 base: Node,
217 kind_token: Token,217 ltoken: Token,
218 layout: Layout,
218 kind: Kind,219 kind: Kind,
219 init_arg_expr: InitArg,220 init_arg_expr: InitArg,
220 fields_and_decls: ArrayList(&Node),221 fields_and_decls: ArrayList(&Node),
221 rbrace_token: Token,222 rbrace_token: Token,
222223
224 const Layout = enum {
225 Auto,
226 Extern,
227 Packed,
228 };
229
223 const Kind = enum {230 const Kind = enum {
224 Struct,231 Struct,
225 Enum,232 Enum,
...@@ -266,7 +273,7 @@ pub const NodeContainerDecl = struct {...@@ -266,7 +273,7 @@ pub const NodeContainerDecl = struct {
266 }273 }
267274
268 pub fn firstToken(self: &NodeContainerDecl) Token {275 pub fn firstToken(self: &NodeContainerDecl) Token {
269 return self.kind_token;276 return self.ltoken;
270 }277 }
271278
272 pub fn lastToken(self: &NodeContainerDecl) Token {279 pub fn lastToken(self: &NodeContainerDecl) Token {
std/zig/parser.zig+167-93
...@@ -59,6 +59,11 @@ pub const Parser = struct {...@@ -59,6 +59,11 @@ pub const Parser = struct {
59 lib_name: ?&ast.Node,59 lib_name: ?&ast.Node,
60 };60 };
6161
62 const ContainerExternCtx = struct {
63 ltoken: Token,
64 layout: ast.NodeContainerDecl.Layout,
65 };
66
62 const DestPtr = union(enum) {67 const DestPtr = union(enum) {
63 Field: &&ast.Node,68 Field: &&ast.Node,
64 NullableField: &?&ast.Node,69 NullableField: &?&ast.Node,
...@@ -90,6 +95,7 @@ pub const Parser = struct {...@@ -90,6 +95,7 @@ pub const Parser = struct {
90 TopLevel,95 TopLevel,
91 TopLevelExtern: TopLevelDeclCtx,96 TopLevelExtern: TopLevelDeclCtx,
92 TopLevelDecl: TopLevelDeclCtx,97 TopLevelDecl: TopLevelDeclCtx,
98 ContainerExtern: ContainerExternCtx,
93 ContainerDecl: &ast.NodeContainerDecl,99 ContainerDecl: &ast.NodeContainerDecl,
94 Expression: DestPtr,100 Expression: DestPtr,
95 ExpectOperand,101 ExpectOperand,
...@@ -338,6 +344,63 @@ pub const Parser = struct {...@@ -338,6 +344,63 @@ pub const Parser = struct {
338 return self.parseError(token, "expected '=' or ';', found {}", @tagName(token.id));344 return self.parseError(token, "expected '=' or ';', found {}", @tagName(token.id));
339 },345 },
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
341 State.ContainerDecl => |container_decl| {404 State.ContainerDecl => |container_decl| {
342 const token = self.getNextToken();405 const token = self.getNextToken();
343406
...@@ -633,52 +696,30 @@ pub const Parser = struct {...@@ -633,52 +696,30 @@ pub const Parser = struct {
633 try stack.append(State.AfterOperand);696 try stack.append(State.AfterOperand);
634 continue;697 continue;
635 },698 },
636 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {699 Token.Id.Keyword_packed => {
637 const node = try arena.create(ast.NodeContainerDecl);700 try stack.append(State {
638 *node = ast.NodeContainerDecl {701 .ContainerExtern = ContainerExternCtx {
639 .base = self.initNode(ast.Node.Id.ContainerDecl),702 .ltoken = token,
640 .kind_token = token,703 .layout = ast.NodeContainerDecl.Layout.Packed,
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,
646 },704 },
647 .init_arg_expr = undefined,705 });
648 .fields_and_decls = ArrayList(&ast.Node).init(arena),706 },
649 .rbrace_token = undefined,707 Token.Id.Keyword_extern => {
650 };708 try stack.append(State {
651709 .ContainerExtern = ContainerExternCtx {
652 try stack.append(State { .Operand = &node.base });710 .ltoken = token,
653 try stack.append(State.AfterOperand);711 .layout = ast.NodeContainerDecl.Layout.Extern,
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;
670 },712 },
671 else => {713 });
672 self.putBackToken(lparen);714 },
673 node.init_arg_expr = ast.NodeContainerDecl.InitArg { .Type = undefined };715 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {
674 try stack.append(State {716 self.putBackToken(token);
675 .Expression = DestPtr {717 try stack.append(State {
676 .Field = &node.init_arg_expr.Type718 .ContainerExtern = ContainerExternCtx {
677 }719 .ltoken = token,
678 });720 .layout = ast.NodeContainerDecl.Layout.Auto,
679 },721 },
680 }722 });
681 continue;
682 },723 },
683 Token.Id.Builtin => {724 Token.Id.Builtin => {
684 const node = try arena.create(ast.NodeBuiltinCall);725 const node = try arena.create(ast.NodeBuiltinCall);
...@@ -1706,6 +1747,29 @@ pub const Parser = struct {...@@ -1706,6 +1747,29 @@ pub const Parser = struct {
1706 try stack.append(RenderState { .Text = " " });1747 try stack.append(RenderState { .Text = " " });
1707 try stack.append(RenderState { .Expression = test_decl.name });1748 try stack.append(RenderState { .Expression = test_decl.name });
1708 },1749 },
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 },
1709 else => unreachable,1773 else => unreachable,
1710 }1774 }
1711 },1775 },
...@@ -1990,27 +2054,30 @@ pub const Parser = struct {...@@ -1990,27 +2054,30 @@ pub const Parser = struct {
1990 },2054 },
1991 ast.Node.Id.ContainerDecl => {2055 ast.Node.Id.ContainerDecl => {
1992 const container_decl = @fieldParentPtr(ast.NodeContainerDecl, "base", base);2056 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
1994 try stack.append(RenderState { .Text = "}"});2070 try stack.append(RenderState { .Text = "}"});
1995 try stack.append(RenderState.PrintIndent);2071 try stack.append(RenderState.PrintIndent);
1996 try stack.append(RenderState { .Indent = indent });2072 try stack.append(RenderState { .Indent = indent });
2073 try stack.append(RenderState { .Text = "\n"});
19972074
1998 const fields_and_decls = container_decl.fields_and_decls.toSliceConst();2075 const fields_and_decls = container_decl.fields_and_decls.toSliceConst();
1999 var i = fields_and_decls.len;2076 var i = fields_and_decls.len;
2000 while (i != 0) {2077 while (i != 0) {
2001 i -= 1;2078 i -= 1;
2002 const node = fields_and_decls[i];2079 const node = fields_and_decls[i];
2003 if (i != 0) {2080 try stack.append(RenderState { .TopLevelDecl = node});
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});
2014 try stack.append(RenderState.PrintIndent);2081 try stack.append(RenderState.PrintIndent);
2015 try stack.append(RenderState {2082 try stack.append(RenderState {
2016 .Text = blk: {2083 .Text = blk: {
...@@ -2025,22 +2092,43 @@ pub const Parser = struct {...@@ -2025,22 +2092,43 @@ pub const Parser = struct {
2025 break :blk "\n";2092 break :blk "\n";
2026 },2093 },
2027 });2094 });
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 }
2028 }2107 }
2029 try stack.append(RenderState { .Indent = indent + indent_delta});2108 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 }
2030 },2120 },
2031 ast.Node.Id.MultilineStringLiteral => {2121 ast.Node.Id.MultilineStringLiteral => {
2032 const multiline_str_literal = @fieldParentPtr(ast.NodeMultilineStringLiteral, "base", base);2122 const multiline_str_literal = @fieldParentPtr(ast.NodeMultilineStringLiteral, "base", base);
2033 try stream.print("\n");2123 try stream.print("\n");
20342124
2035 var i : usize = 0;2125 var i : usize = 0;
2036 indent += 4;
2037 while (i < multiline_str_literal.tokens.len) : (i += 1) {2126 while (i < multiline_str_literal.tokens.len) : (i += 1) {
2038 const t = multiline_str_literal.tokens.at(i);2127 const t = multiline_str_literal.tokens.at(i);
2039 try stream.writeByteNTimes(' ', indent);2128 try stream.writeByteNTimes(' ', indent + indent_delta);
2040 try stream.print("{}", self.tokenizer.getTokenSlice(t));2129 try stream.print("{}", self.tokenizer.getTokenSlice(t));
2041 }2130 }
2042 try stream.writeByteNTimes(' ', indent);2131 try stream.writeByteNTimes(' ', indent + indent_delta);
2043 indent -= 4;
2044 },2132 },
2045 ast.Node.Id.UndefinedLiteral => {2133 ast.Node.Id.UndefinedLiteral => {
2046 const undefined_literal = @fieldParentPtr(ast.NodeUndefinedLiteral, "base", base);2134 const undefined_literal = @fieldParentPtr(ast.NodeUndefinedLiteral, "base", base);
...@@ -2060,31 +2148,12 @@ pub const Parser = struct {...@@ -2060,31 +2148,12 @@ pub const Parser = struct {
2060 }2148 }
2061 }2149 }
2062 },2150 },
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 },
2085 ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"),2151 ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"),
2086 ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"),2152 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,
2088 ast.Node.Id.Root,2157 ast.Node.Id.Root,
2089 ast.Node.Id.VarDecl,2158 ast.Node.Id.VarDecl,
2090 ast.Node.Id.TestDecl,2159 ast.Node.Id.TestDecl,
...@@ -2489,21 +2558,21 @@ test "zig fmt: struct declaration" {...@@ -2489,21 +2558,21 @@ test "zig fmt: struct declaration" {
2489 \\ return *self;2558 \\ return *self;
2490 \\ }2559 \\ }
2491 \\2560 \\
2492 \\ f2: u8,2561 \\ f2: u8
2493 \\};2562 \\};
2494 \\2563 \\
2495 \\const Ps = packed struct {2564 \\const Ps = packed struct {
2496 \\ a: u8,2565 \\ a: u8,
2497 \\ b: u8,2566 \\ b: u8,
2498 \\2567 \\
2499 \\ c: u8,2568 \\ c: u8
2500 \\};2569 \\};
2501 \\2570 \\
2502 \\const Es = extern struct {2571 \\const Es = extern struct {
2503 \\ a: u8,2572 \\ a: u8,
2504 \\ b: u8,2573 \\ b: u8,
2505 \\2574 \\
2506 \\ c: u8,2575 \\ c: u8
2507 \\};2576 \\};
2508 \\2577 \\
2509 );2578 );
...@@ -2513,25 +2582,25 @@ test "zig fmt: enum declaration" {...@@ -2513,25 +2582,25 @@ test "zig fmt: enum declaration" {
2513 try testCanonical(2582 try testCanonical(
2514 \\const E = enum {2583 \\const E = enum {
2515 \\ Ok,2584 \\ Ok,
2516 \\ SomethingElse = 0,2585 \\ SomethingElse = 0
2517 \\};2586 \\};
2518 \\2587 \\
2519 \\const E2 = enum(u8) {2588 \\const E2 = enum(u8) {
2520 \\ Ok,2589 \\ Ok,
2521 \\ SomethingElse = 255,2590 \\ SomethingElse = 255,
2522 \\ SomethingThird,2591 \\ SomethingThird
2523 \\};2592 \\};
2524 \\2593 \\
2525 \\const Ee = extern enum {2594 \\const Ee = extern enum {
2526 \\ Ok,2595 \\ Ok,
2527 \\ SomethingElse,2596 \\ SomethingElse,
2528 \\ SomethingThird,2597 \\ SomethingThird
2529 \\};2598 \\};
2530 \\2599 \\
2531 \\const Ep = packed enum {2600 \\const Ep = packed enum {
2532 \\ Ok,2601 \\ Ok,
2533 \\ SomethingElse,2602 \\ SomethingElse,
2534 \\ SomethingThird,2603 \\ SomethingThird
2535 \\};2604 \\};
2536 \\2605 \\
2537 );2606 );
...@@ -2542,31 +2611,36 @@ test "zig fmt: union declaration" {...@@ -2542,31 +2611,36 @@ test "zig fmt: union declaration" {
2542 \\const U = union {2611 \\const U = union {
2543 \\ Int: u8,2612 \\ Int: u8,
2544 \\ Float: f32,2613 \\ Float: f32,
2545 \\ Bool: bool,2614 \\ None,
2615 \\ Bool: bool
2546 \\};2616 \\};
2547 \\2617 \\
2548 \\const Ue = union(enum) {2618 \\const Ue = union(enum) {
2549 \\ Int: u8,2619 \\ Int: u8,
2550 \\ Float: f32,2620 \\ Float: f32,
2551 \\ Bool: bool,2621 \\ None,
2622 \\ Bool: bool
2552 \\};2623 \\};
2553 \\2624 \\
2554 \\const E = enum {2625 \\const E = enum {
2555 \\ Int,2626 \\ Int,
2556 \\ Float,2627 \\ Float,
2557 \\ Bool,2628 \\ None,
2629 \\ Bool
2558 \\};2630 \\};
2559 \\2631 \\
2560 \\const Ue2 = union(E) {2632 \\const Ue2 = union(E) {
2561 \\ Int: u8,2633 \\ Int: u8,
2562 \\ Float: f32,2634 \\ Float: f32,
2563 \\ Bool: bool,2635 \\ None,
2636 \\ Bool: bool
2564 \\};2637 \\};
2565 \\2638 \\
2566 \\const Eu = extern union {2639 \\const Eu = extern union {
2567 \\ Int: u8,2640 \\ Int: u8,
2568 \\ Float: f32,2641 \\ Float: f32,
2569 \\ Bool: bool,2642 \\ None,
2643 \\ Bool: bool
2570 \\};2644 \\};
2571 \\2645 \\
2572 );2646 );