| ... | ... | @@ -669,6 +669,7 @@ pub const Parser = struct { |
| 669 | 669 | const node = try self.createAttachNode(arena, &container_decl.fields_and_decls, ast.NodeStructField, |
| 670 | 670 | ast.NodeStructField { |
| 671 | 671 | .base = undefined, |
| 672 | .visib_token = null, |
| 672 | 673 | .name_token = token, |
| 673 | 674 | .type_expr = undefined, |
| 674 | 675 | } |
| ... | ... | @@ -721,7 +722,42 @@ pub const Parser = struct { |
| 721 | 722 | }, |
| 722 | 723 | } |
| 723 | 724 | }, |
| 724 | | Token.Id.Keyword_pub, Token.Id.Keyword_export => { |
| 725 | Token.Id.Keyword_pub => { |
| 726 | if (self.eatToken(Token.Id.Identifier)) |identifier| { |
| 727 | switch (container_decl.kind) { |
| 728 | ast.NodeContainerDecl.Kind.Struct => { |
| 729 | const node = try self.createAttachNode(arena, &container_decl.fields_and_decls, ast.NodeStructField, |
| 730 | ast.NodeStructField { |
| 731 | .base = undefined, |
| 732 | .visib_token = token, |
| 733 | .name_token = identifier, |
| 734 | .type_expr = undefined, |
| 735 | } |
| 736 | ); |
| 737 | |
| 738 | stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable; |
| 739 | try stack.append(State { .Expression = DestPtr { .Field = &node.type_expr } }); |
| 740 | try stack.append(State { .ExpectToken = Token.Id.Colon }); |
| 741 | continue; |
| 742 | }, |
| 743 | else => { |
| 744 | self.putBackToken(identifier); |
| 745 | } |
| 746 | } |
| 747 | } |
| 748 | |
| 749 | stack.append(State{ .ContainerDecl = container_decl }) catch unreachable; |
| 750 | try stack.append(State { |
| 751 | .TopLevelExtern = TopLevelDeclCtx { |
| 752 | .decls = &container_decl.fields_and_decls, |
| 753 | .visib_token = token, |
| 754 | .extern_token = null, |
| 755 | .lib_name = null, |
| 756 | } |
| 757 | }); |
| 758 | continue; |
| 759 | }, |
| 760 | Token.Id.Keyword_export => { |
| 725 | 761 | stack.append(State{ .ContainerDecl = container_decl }) catch unreachable; |
| 726 | 762 | try stack.append(State { |
| 727 | 763 | .TopLevelExtern = TopLevelDeclCtx { |
| ... | ... | @@ -864,111 +900,11 @@ pub const Parser = struct { |
| 864 | 900 | stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }) catch unreachable; |
| 865 | 901 | continue; |
| 866 | 902 | }, |
| 867 | | Token.Id.Keyword_suspend => { |
| 868 | | const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSuspend, |
| 869 | | ast.NodeSuspend { |
| 870 | | .base = undefined, |
| 871 | | .suspend_token = token, |
| 872 | | .payload = null, |
| 873 | | .body = null, |
| 874 | | } |
| 875 | | ); |
| 876 | | |
| 877 | | stack.append(State { .SuspendBody = node }) catch unreachable; |
| 878 | | try stack.append(State { .Payload = &node.payload }); |
| 879 | | continue; |
| 880 | | }, |
| 881 | | Token.Id.Keyword_if => { |
| 882 | | const node = try self.createToDestNode(arena, dest_ptr, ast.NodeIf, |
| 883 | | ast.NodeIf { |
| 884 | | .base = undefined, |
| 885 | | .if_token = token, |
| 886 | | .condition = undefined, |
| 887 | | .payload = null, |
| 888 | | .body = undefined, |
| 889 | | .@"else" = null, |
| 890 | | } |
| 891 | | ); |
| 892 | | |
| 893 | | stack.append(State { .Else = &node.@"else" }) catch unreachable; |
| 894 | | try stack.append(State { .Expression = DestPtr { .Field = &node.body } }); |
| 895 | | try stack.append(State { .PointerPayload = &node.payload }); |
| 896 | | try stack.append(State { .ExpectToken = Token.Id.RParen }); |
| 897 | | try stack.append(State { .Expression = DestPtr { .Field = &node.condition } }); |
| 898 | | try stack.append(State { .ExpectToken = Token.Id.LParen }); |
| 899 | | continue; |
| 900 | | }, |
| 901 | | Token.Id.Keyword_while => { |
| 902 | | stack.append(State { |
| 903 | | .While = LoopCtx { |
| 904 | | .label = null, |
| 905 | | .inline_token = null, |
| 906 | | .loop_token = token, |
| 907 | | .dest_ptr = dest_ptr, |
| 908 | | } |
| 909 | | }) catch unreachable; |
| 910 | | continue; |
| 911 | | }, |
| 912 | | Token.Id.Keyword_for => { |
| 913 | | stack.append(State { |
| 914 | | .For = LoopCtx { |
| 915 | | .label = null, |
| 916 | | .inline_token = null, |
| 917 | | .loop_token = token, |
| 918 | | .dest_ptr = dest_ptr, |
| 919 | | } |
| 920 | | }) catch unreachable; |
| 921 | | continue; |
| 922 | | }, |
| 923 | | Token.Id.Keyword_switch => { |
| 924 | | const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSwitch, |
| 925 | | ast.NodeSwitch { |
| 926 | | .base = undefined, |
| 927 | | .switch_token = token, |
| 928 | | .expr = undefined, |
| 929 | | .cases = ArrayList(&ast.NodeSwitchCase).init(arena), |
| 930 | | .rbrace = undefined, |
| 931 | | } |
| 932 | | ); |
| 933 | | |
| 934 | | stack.append(State { |
| 935 | | .SwitchCaseOrEnd = ListSave(&ast.NodeSwitchCase) { |
| 936 | | .list = &node.cases, |
| 937 | | .ptr = &node.rbrace, |
| 938 | | }, |
| 939 | | }) catch unreachable; |
| 940 | | try stack.append(State { .ExpectToken = Token.Id.LBrace }); |
| 941 | | try stack.append(State { .ExpectToken = Token.Id.RParen }); |
| 942 | | try stack.append(State { .Expression = DestPtr { .Field = &node.expr } }); |
| 943 | | try stack.append(State { .ExpectToken = Token.Id.LParen }); |
| 944 | | }, |
| 945 | | Token.Id.Keyword_comptime => { |
| 946 | | const node = try self.createToDestNode(arena, dest_ptr, ast.NodeComptime, |
| 947 | | ast.NodeComptime { |
| 948 | | .base = undefined, |
| 949 | | .comptime_token = token, |
| 950 | | .expr = undefined, |
| 951 | | } |
| 952 | | ); |
| 953 | | try stack.append(State { .Expression = DestPtr { .Field = &node.expr } }); |
| 954 | | continue; |
| 955 | | }, |
| 956 | | Token.Id.LBrace => { |
| 957 | | const block = try self.createToDestNode(arena, dest_ptr, ast.NodeBlock, |
| 958 | | ast.NodeBlock { |
| 959 | | .base = undefined, |
| 960 | | .label = null, |
| 961 | | .lbrace = token, |
| 962 | | .statements = ArrayList(&ast.Node).init(arena), |
| 963 | | .rbrace = undefined, |
| 964 | | } |
| 965 | | ); |
| 966 | | stack.append(State { .Block = block }) catch unreachable; |
| 967 | | continue; |
| 968 | | }, |
| 969 | 903 | else => { |
| 970 | | self.putBackToken(token); |
| 971 | | stack.append(State { .UnwrapExpressionBegin = dest_ptr }) catch unreachable; |
| 904 | if (!try self.parseBlockExpr(&stack, arena, dest_ptr, token)) { |
| 905 | self.putBackToken(token); |
| 906 | stack.append(State { .UnwrapExpressionBegin = dest_ptr }) catch unreachable; |
| 907 | } |
| 972 | 908 | continue; |
| 973 | 909 | } |
| 974 | 910 | } |
| ... | ... | @@ -1407,7 +1343,7 @@ pub const Parser = struct { |
| 1407 | 1343 | State.PrefixOpExpression => |dest_ptr| { |
| 1408 | 1344 | const token = self.getNextToken(); |
| 1409 | 1345 | if (tokenIdToPrefixOp(token.id)) |prefix_id| { |
| 1410 | | const node = try self.createToDestNode(arena, dest_ptr, ast.NodePrefixOp, |
| 1346 | var node = try self.createToDestNode(arena, dest_ptr, ast.NodePrefixOp, |
| 1411 | 1347 | ast.NodePrefixOp { |
| 1412 | 1348 | .base = undefined, |
| 1413 | 1349 | .op_token = token, |
| ... | ... | @@ -1415,6 +1351,20 @@ pub const Parser = struct { |
| 1415 | 1351 | .rhs = undefined, |
| 1416 | 1352 | } |
| 1417 | 1353 | ); |
| 1354 | |
| 1355 | if (token.id == Token.Id.AsteriskAsterisk) { |
| 1356 | const child = try self.createNode(arena, ast.NodePrefixOp, |
| 1357 | ast.NodePrefixOp { |
| 1358 | .base = undefined, |
| 1359 | .op_token = token, |
| 1360 | .op = prefix_id, |
| 1361 | .rhs = undefined, |
| 1362 | } |
| 1363 | ); |
| 1364 | node.rhs = &child.base; |
| 1365 | node = child; |
| 1366 | } |
| 1367 | |
| 1418 | 1368 | stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.rhs } }) catch unreachable; |
| 1419 | 1369 | if (node.op == ast.NodePrefixOp.PrefixOp.AddrOf) { |
| 1420 | 1370 | try stack.append(State { .AddrOfModifiers = &node.op.AddrOf }); |
| ... | ... | @@ -1871,7 +1821,9 @@ pub const Parser = struct { |
| 1871 | 1821 | continue; |
| 1872 | 1822 | }, |
| 1873 | 1823 | else => { |
| 1874 | | try self.parseError(&stack, token, "expected primary expression, found {}", @tagName(token.id)); |
| 1824 | if (!try self.parseBlockExpr(&stack, arena, dest_ptr, token)) { |
| 1825 | try self.parseError(&stack, token, "expected primary expression, found {}", @tagName(token.id)); |
| 1826 | } |
| 1875 | 1827 | continue; |
| 1876 | 1828 | } |
| 1877 | 1829 | } |
| ... | ... | @@ -2790,6 +2742,117 @@ pub const Parser = struct { |
| 2790 | 2742 | } |
| 2791 | 2743 | } |
| 2792 | 2744 | |
| 2745 | fn parseBlockExpr(self: &Parser, stack: &ArrayList(State), arena: &mem.Allocator, dest_ptr: &const DestPtr, token: &const Token) !bool { |
| 2746 | switch (token.id) { |
| 2747 | Token.Id.Keyword_suspend => { |
| 2748 | const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSuspend, |
| 2749 | ast.NodeSuspend { |
| 2750 | .base = undefined, |
| 2751 | .suspend_token = *token, |
| 2752 | .payload = null, |
| 2753 | .body = null, |
| 2754 | } |
| 2755 | ); |
| 2756 | |
| 2757 | stack.append(State { .SuspendBody = node }) catch unreachable; |
| 2758 | try stack.append(State { .Payload = &node.payload }); |
| 2759 | return true; |
| 2760 | }, |
| 2761 | Token.Id.Keyword_if => { |
| 2762 | const node = try self.createToDestNode(arena, dest_ptr, ast.NodeIf, |
| 2763 | ast.NodeIf { |
| 2764 | .base = undefined, |
| 2765 | .if_token = *token, |
| 2766 | .condition = undefined, |
| 2767 | .payload = null, |
| 2768 | .body = undefined, |
| 2769 | .@"else" = null, |
| 2770 | } |
| 2771 | ); |
| 2772 | |
| 2773 | stack.append(State { .Else = &node.@"else" }) catch unreachable; |
| 2774 | try stack.append(State { .Expression = DestPtr { .Field = &node.body } }); |
| 2775 | try stack.append(State { .PointerPayload = &node.payload }); |
| 2776 | try stack.append(State { .ExpectToken = Token.Id.RParen }); |
| 2777 | try stack.append(State { .Expression = DestPtr { .Field = &node.condition } }); |
| 2778 | try stack.append(State { .ExpectToken = Token.Id.LParen }); |
| 2779 | return true; |
| 2780 | }, |
| 2781 | Token.Id.Keyword_while => { |
| 2782 | stack.append(State { |
| 2783 | .While = LoopCtx { |
| 2784 | .label = null, |
| 2785 | .inline_token = null, |
| 2786 | .loop_token = *token, |
| 2787 | .dest_ptr = *dest_ptr, |
| 2788 | } |
| 2789 | }) catch unreachable; |
| 2790 | return true; |
| 2791 | }, |
| 2792 | Token.Id.Keyword_for => { |
| 2793 | stack.append(State { |
| 2794 | .For = LoopCtx { |
| 2795 | .label = null, |
| 2796 | .inline_token = null, |
| 2797 | .loop_token = *token, |
| 2798 | .dest_ptr = *dest_ptr, |
| 2799 | } |
| 2800 | }) catch unreachable; |
| 2801 | return true; |
| 2802 | }, |
| 2803 | Token.Id.Keyword_switch => { |
| 2804 | const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSwitch, |
| 2805 | ast.NodeSwitch { |
| 2806 | .base = undefined, |
| 2807 | .switch_token = *token, |
| 2808 | .expr = undefined, |
| 2809 | .cases = ArrayList(&ast.NodeSwitchCase).init(arena), |
| 2810 | .rbrace = undefined, |
| 2811 | } |
| 2812 | ); |
| 2813 | |
| 2814 | stack.append(State { |
| 2815 | .SwitchCaseOrEnd = ListSave(&ast.NodeSwitchCase) { |
| 2816 | .list = &node.cases, |
| 2817 | .ptr = &node.rbrace, |
| 2818 | }, |
| 2819 | }) catch unreachable; |
| 2820 | try stack.append(State { .ExpectToken = Token.Id.LBrace }); |
| 2821 | try stack.append(State { .ExpectToken = Token.Id.RParen }); |
| 2822 | try stack.append(State { .Expression = DestPtr { .Field = &node.expr } }); |
| 2823 | try stack.append(State { .ExpectToken = Token.Id.LParen }); |
| 2824 | return true; |
| 2825 | }, |
| 2826 | Token.Id.Keyword_comptime => { |
| 2827 | const node = try self.createToDestNode(arena, dest_ptr, ast.NodeComptime, |
| 2828 | ast.NodeComptime { |
| 2829 | .base = undefined, |
| 2830 | .comptime_token = *token, |
| 2831 | .expr = undefined, |
| 2832 | } |
| 2833 | ); |
| 2834 | try stack.append(State { .Expression = DestPtr { .Field = &node.expr } }); |
| 2835 | return true; |
| 2836 | }, |
| 2837 | Token.Id.LBrace => { |
| 2838 | const block = try self.createToDestNode(arena, dest_ptr, ast.NodeBlock, |
| 2839 | ast.NodeBlock { |
| 2840 | .base = undefined, |
| 2841 | .label = null, |
| 2842 | .lbrace = *token, |
| 2843 | .statements = ArrayList(&ast.Node).init(arena), |
| 2844 | .rbrace = undefined, |
| 2845 | } |
| 2846 | ); |
| 2847 | stack.append(State { .Block = block }) catch unreachable; |
| 2848 | return true; |
| 2849 | }, |
| 2850 | else => { |
| 2851 | return false; |
| 2852 | } |
| 2853 | } |
| 2854 | } |
| 2855 | |
| 2793 | 2856 | fn commaOrEnd(self: &Parser, stack: &ArrayList(State), end: &const Token.Id, maybe_ptr: ?&Token, state_after_comma: &const State) !void { |
| 2794 | 2857 | var token = self.getNextToken(); |
| 2795 | 2858 | switch (token.id) { |
| ... | ... | @@ -2881,7 +2944,7 @@ pub const Parser = struct { |
| 2881 | 2944 | Token.Id.Tilde => ast.NodePrefixOp.PrefixOp { .BitNot = void{} }, |
| 2882 | 2945 | Token.Id.Minus => ast.NodePrefixOp.PrefixOp { .Negation = void{} }, |
| 2883 | 2946 | Token.Id.MinusPercent => ast.NodePrefixOp.PrefixOp { .NegationWrap = void{} }, |
| 2884 | | Token.Id.Asterisk => ast.NodePrefixOp.PrefixOp { .Deref = void{} }, |
| 2947 | Token.Id.Asterisk, Token.Id.AsteriskAsterisk => ast.NodePrefixOp.PrefixOp { .Deref = void{} }, |
| 2885 | 2948 | Token.Id.Ampersand => ast.NodePrefixOp.PrefixOp { |
| 2886 | 2949 | .AddrOf = ast.NodePrefixOp.AddrOfInfo { |
| 2887 | 2950 | .align_expr = null, |
| ... | ... | @@ -3126,6 +3189,9 @@ pub const Parser = struct { |
| 3126 | 3189 | }, |
| 3127 | 3190 | ast.Node.Id.StructField => { |
| 3128 | 3191 | const field = @fieldParentPtr(ast.NodeStructField, "base", decl); |
| 3192 | if (field.visib_token) |visib_token| { |
| 3193 | try stream.print("{} ", self.tokenizer.getTokenSlice(visib_token)); |
| 3194 | } |
| 3129 | 3195 | try stream.print("{}: ", self.tokenizer.getTokenSlice(field.name_token)); |
| 3130 | 3196 | try stack.append(RenderState { .Expression = field.type_expr}); |
| 3131 | 3197 | }, |
| ... | ... | @@ -4573,6 +4639,7 @@ test "zig fmt: struct declaration" { |
| 4573 | 4639 | \\const S = struct { |
| 4574 | 4640 | \\ const Self = this; |
| 4575 | 4641 | \\ f1: u8, |
| 4642 | \\ pub f3: u8, |
| 4576 | 4643 | \\ |
| 4577 | 4644 | \\ fn method(self: &Self) Self { |
| 4578 | 4645 | \\ return *self; |
| ... | ... | @@ -4583,14 +4650,14 @@ test "zig fmt: struct declaration" { |
| 4583 | 4650 | \\ |
| 4584 | 4651 | \\const Ps = packed struct { |
| 4585 | 4652 | \\ a: u8, |
| 4586 | | \\ b: u8, |
| 4653 | \\ pub b: u8, |
| 4587 | 4654 | \\ |
| 4588 | 4655 | \\ c: u8 |
| 4589 | 4656 | \\}; |
| 4590 | 4657 | \\ |
| 4591 | 4658 | \\const Es = extern struct { |
| 4592 | 4659 | \\ a: u8, |
| 4593 | | \\ b: u8, |
| 4660 | \\ pub b: u8, |
| 4594 | 4661 | \\ |
| 4595 | 4662 | \\ c: u8 |
| 4596 | 4663 | \\}; |
| ... | ... | @@ -4895,6 +4962,7 @@ test "zig fmt: if" { |
| 4895 | 4962 | \\ } |
| 4896 | 4963 | \\ |
| 4897 | 4964 | \\ const is_world_broken = if (10 < 0) true else false; |
| 4965 | \\ const some_number = 1 + if (10 < 0) 2 else 3; |
| 4898 | 4966 | \\ |
| 4899 | 4967 | \\ const a: ?u8 = 10; |
| 4900 | 4968 | \\ const b: ?u8 = null; |