| ... | @@ -75,14 +75,17 @@ pub const Parser = struct { | ... | @@ -75,14 +75,17 @@ pub const Parser = struct { |
| 75 | const ExpectTokenSave = struct { | 75 | const ExpectTokenSave = struct { |
| 76 | id: Token.Id, | 76 | id: Token.Id, |
| 77 | ptr: &Token, | 77 | ptr: &Token, |
| 78 | }; | | |
| 79 | | 78 | |
| 80 | const ExprListState = struct { | | |
| 81 | list: &ArrayList(&ast.Node), | | |
| 82 | end: Token.Id, | | |
| 83 | ptr: &Token, | | |
| 84 | }; | 79 | }; |
| 85 | | 80 | |
| | 81 | fn ListState(comptime T: type) type { |
| | 82 | return struct { |
| | 83 | list: &ArrayList(T), |
| | 84 | end: Token.Id, |
| | 85 | ptr: &Token, |
| | 86 | }; |
| | 87 | } |
| | 88 | |
| 86 | const State = union(enum) { | 89 | const State = union(enum) { |
| 87 | TopLevel, | 90 | TopLevel, |
| 88 | TopLevelExtern: ?Token, | 91 | TopLevelExtern: ?Token, |
| ... | @@ -110,8 +113,10 @@ pub const Parser = struct { | ... | @@ -110,8 +113,10 @@ pub const Parser = struct { |
| 110 | FnDef: &ast.NodeFnProto, | 113 | FnDef: &ast.NodeFnProto, |
| 111 | Block: &ast.NodeBlock, | 114 | Block: &ast.NodeBlock, |
| 112 | Statement: &ast.NodeBlock, | 115 | Statement: &ast.NodeBlock, |
| 113 | ExprListItemOrEnd: ExprListState, | 116 | ExprListItemOrEnd: ListState(&ast.Node), |
| 114 | ExprListCommaOrEnd: ExprListState, | 117 | ExprListCommaOrEnd: ListState(&ast.Node), |
| | 118 | FieldInitListItemOrEnd: ListState(&ast.NodeFieldInitializer), |
| | 119 | FieldInitListCommaOrEnd: ListState(&ast.NodeFieldInitializer), |
| 115 | }; | 120 | }; |
| 116 | | 121 | |
| 117 | /// Returns an AST tree, allocated with the parser's allocator. | 122 | /// Returns an AST tree, allocated with the parser's allocator. |
| ... | @@ -536,7 +541,7 @@ pub const Parser = struct { | ... | @@ -536,7 +541,7 @@ pub const Parser = struct { |
| 536 | }); | 541 | }); |
| 537 | try stack.append(State.AfterOperand); | 542 | try stack.append(State.AfterOperand); |
| 538 | try stack.append(State { | 543 | try stack.append(State { |
| 539 | .ExprListItemOrEnd = ExprListState { | 544 | .ExprListItemOrEnd = ListState(&ast.Node) { |
| 540 | .list = &node.params, | 545 | .list = &node.params, |
| 541 | .end = Token.Id.RParen, | 546 | .end = Token.Id.RParen, |
| 542 | .ptr = &node.rparen_token, | 547 | .ptr = &node.rparen_token, |
| ... | @@ -647,8 +652,6 @@ pub const Parser = struct { | ... | @@ -647,8 +652,6 @@ pub const Parser = struct { |
| 647 | continue; | 652 | continue; |
| 648 | | 653 | |
| 649 | } else if (token.id == Token.Id.LParen) { | 654 | } else if (token.id == Token.Id.LParen) { |
| 650 | self.putBackToken(token); | | |
| 651 | | | |
| 652 | const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp { | 655 | const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp { |
| 653 | .Call = ast.NodeSuffixOp.CallInfo { | 656 | .Call = ast.NodeSuffixOp.CallInfo { |
| 654 | .params = ArrayList(&ast.Node).init(arena), | 657 | .params = ArrayList(&ast.Node).init(arena), |
| ... | @@ -658,18 +661,12 @@ pub const Parser = struct { | ... | @@ -658,18 +661,12 @@ pub const Parser = struct { |
| 658 | try stack.append(State { .SuffixOp = node }); | 661 | try stack.append(State { .SuffixOp = node }); |
| 659 | try stack.append(State.AfterOperand); | 662 | try stack.append(State.AfterOperand); |
| 660 | try stack.append(State { | 663 | try stack.append(State { |
| 661 | .ExprListItemOrEnd = ExprListState { | 664 | .ExprListItemOrEnd = ListState(&ast.Node) { |
| 662 | .list = &node.op.Call.params, | 665 | .list = &node.op.Call.params, |
| 663 | .end = Token.Id.RParen, | 666 | .end = Token.Id.RParen, |
| 664 | .ptr = &node.rtoken, | 667 | .ptr = &node.rtoken, |
| 665 | } | 668 | } |
| 666 | }); | 669 | }); |
| 667 | try stack.append(State { | | |
| 668 | .ExpectTokenSave = ExpectTokenSave { | | |
| 669 | .id = Token.Id.LParen, | | |
| 670 | .ptr = &node.rtoken, | | |
| 671 | }, | | |
| 672 | }); | | |
| 673 | continue; | 670 | continue; |
| 674 | | 671 | |
| 675 | } else if (token.id == Token.Id.LBracket) { | 672 | } else if (token.id == Token.Id.LBracket) { |
| ... | @@ -686,6 +683,47 @@ pub const Parser = struct { | ... | @@ -686,6 +683,47 @@ pub const Parser = struct { |
| 686 | try stack.append(State { .Expression = DestPtr { .Field = &node.op.ArrayAccess }}); | 683 | try stack.append(State { .Expression = DestPtr { .Field = &node.op.ArrayAccess }}); |
| 687 | continue; | 684 | continue; |
| 688 | | 685 | |
| | 686 | // TODO: This is the initializer parsing code. It doesn't work because of |
| | 687 | // the ambiguity between function bodies and initializers: |
| | 688 | // fn main() void {} or fn main() (void {}) |
| | 689 | } else if (false) { //(token.id == Token.Id.LBrace) { |
| | 690 | const next = self.getNextToken(); |
| | 691 | |
| | 692 | switch (next.id) { |
| | 693 | Token.Id.Period => { |
| | 694 | self.putBackToken(token); |
| | 695 | |
| | 696 | const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp { |
| | 697 | .StructInitializer = ArrayList(&ast.NodeFieldInitializer).init(arena), |
| | 698 | }); |
| | 699 | |
| | 700 | try stack.append(State { |
| | 701 | .FieldInitListItemOrEnd = ListState(&ast.NodeFieldInitializer) { |
| | 702 | .list = &node.op.StructInitializer, |
| | 703 | .end = Token.Id.RBrace, |
| | 704 | .ptr = &node.rtoken, |
| | 705 | } |
| | 706 | }); |
| | 707 | continue; |
| | 708 | }, |
| | 709 | else => { |
| | 710 | self.putBackToken(token); |
| | 711 | |
| | 712 | const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp { |
| | 713 | .ArrayInitializer = ArrayList(&ast.Node).init(arena), |
| | 714 | }); |
| | 715 | |
| | 716 | try stack.append(State { |
| | 717 | .ExprListItemOrEnd = ListState(&ast.Node) { |
| | 718 | .list = &node.op.ArrayInitializer, |
| | 719 | .end = Token.Id.RBrace, |
| | 720 | .ptr = &node.rtoken, |
| | 721 | } |
| | 722 | }); |
| | 723 | continue; |
| | 724 | }, |
| | 725 | } |
| | 726 | |
| 689 | // TODO: Parse postfix operator | 727 | // TODO: Parse postfix operator |
| 690 | } else { | 728 | } else { |
| 691 | // no postfix/infix operator after this operand. | 729 | // no postfix/infix operator after this operand. |
| ... | @@ -717,30 +755,89 @@ pub const Parser = struct { | ... | @@ -717,30 +755,89 @@ pub const Parser = struct { |
| 717 | } | 755 | } |
| 718 | }, | 756 | }, |
| 719 | | 757 | |
| 720 | State.ExprListItemOrEnd => |expr_list_state| { | 758 | State.ExprListItemOrEnd => |list_state| { |
| | 759 | var token = self.getNextToken(); |
| | 760 | |
| | 761 | const IdTag = @TagType(Token.Id); |
| | 762 | if (IdTag(list_state.end) == token.id) { |
| | 763 | *list_state.ptr = token; |
| | 764 | continue; |
| | 765 | } |
| | 766 | |
| | 767 | self.putBackToken(token); |
| | 768 | stack.append(State { .ExprListCommaOrEnd = list_state }) catch unreachable; |
| | 769 | try stack.append(State { .Expression = DestPtr{.List = list_state.list} }); |
| | 770 | }, |
| | 771 | |
| | 772 | State.ExprListCommaOrEnd => |list_state| { |
| 721 | var token = self.getNextToken(); | 773 | var token = self.getNextToken(); |
| 722 | switch (token.id) { | 774 | switch (token.id) { |
| 723 | Token.Id.RParen => continue, | 775 | Token.Id.Comma => { |
| | 776 | stack.append(State { .ExprListItemOrEnd = list_state }) catch unreachable; |
| | 777 | }, |
| 724 | else => { | 778 | else => { |
| 725 | self.putBackToken(token); | 779 | const IdTag = @TagType(Token.Id); |
| 726 | stack.append(State { .ExprListCommaOrEnd = expr_list_state }) catch unreachable; | 780 | if (IdTag(list_state.end) == token.id) { |
| 727 | try stack.append(State { .Expression = DestPtr{.List = expr_list_state.list} }); | 781 | *list_state.ptr = token; |
| | 782 | continue; |
| | 783 | } |
| | 784 | |
| | 785 | return self.parseError(token, "expected ',' or {}, found {}", @tagName(list_state.end), @tagName(token.id)); |
| 728 | }, | 786 | }, |
| 729 | } | 787 | } |
| 730 | }, | 788 | }, |
| 731 | | 789 | |
| 732 | State.ExprListCommaOrEnd => |expr_list_state| { | 790 | State.FieldInitListItemOrEnd => |list_state| { |
| | 791 | var token = self.getNextToken(); |
| | 792 | |
| | 793 | const IdTag = @TagType(Token.Id); |
| | 794 | if (IdTag(list_state.end) == token.id){ |
| | 795 | *list_state.ptr = token; |
| | 796 | continue; |
| | 797 | } |
| | 798 | |
| | 799 | self.putBackToken(token); |
| | 800 | |
| | 801 | const node = try arena.create(ast.NodeFieldInitializer); |
| | 802 | *node = ast.NodeFieldInitializer { |
| | 803 | .base = self.initNode(ast.Node.Id.FieldInitializer), |
| | 804 | .period_token = undefined, |
| | 805 | .name_token = undefined, |
| | 806 | .expr = undefined, |
| | 807 | }; |
| | 808 | try list_state.list.append(node); |
| | 809 | |
| | 810 | stack.append(State { .FieldInitListCommaOrEnd = list_state }) catch unreachable; |
| | 811 | try stack.append(State { .Expression = DestPtr{.Field = &node.expr} }); |
| | 812 | try stack.append(State { .ExpectToken = Token.Id.Equal }); |
| | 813 | try stack.append(State { |
| | 814 | .ExpectTokenSave = ExpectTokenSave { |
| | 815 | .id = Token.Id.Identifier, |
| | 816 | .ptr = &node.name_token, |
| | 817 | } |
| | 818 | }); |
| | 819 | try stack.append(State { |
| | 820 | .ExpectTokenSave = ExpectTokenSave { |
| | 821 | .id = Token.Id.Period, |
| | 822 | .ptr = &node.period_token, |
| | 823 | } |
| | 824 | }); |
| | 825 | }, |
| | 826 | |
| | 827 | State.FieldInitListCommaOrEnd => |list_state| { |
| 733 | var token = self.getNextToken(); | 828 | var token = self.getNextToken(); |
| 734 | switch (token.id) { | 829 | switch (token.id) { |
| 735 | Token.Id.Comma => { | 830 | Token.Id.Comma => { |
| 736 | stack.append(State { .ExprListItemOrEnd = expr_list_state }) catch unreachable; | 831 | stack.append(State { .FieldInitListItemOrEnd = list_state }) catch unreachable; |
| 737 | }, | 832 | }, |
| 738 | else => { | 833 | else => { |
| 739 | const IdTag = @TagType(Token.Id); | 834 | const IdTag = @TagType(Token.Id); |
| 740 | if (IdTag(expr_list_state.end) == token.id) | 835 | if (IdTag(list_state.end) == token.id) { |
| | 836 | *list_state.ptr = token; |
| 741 | continue; | 837 | continue; |
| | 838 | } |
| 742 | | 839 | |
| 743 | return self.parseError(token, "expected ',' or {}, found {}", @tagName(expr_list_state.end), @tagName(token.id)); | 840 | return self.parseError(token, "expected ',' or {}, found {}", @tagName(list_state.end), @tagName(token.id)); |
| 744 | }, | 841 | }, |
| 745 | } | 842 | } |
| 746 | }, | 843 | }, |