| ... | ... | @@ -75,14 +75,17 @@ pub const Parser = struct { |
| 75 | 75 | const ExpectTokenSave = struct { |
| 76 | 76 | id: Token.Id, |
| 77 | 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 | 89 | const State = union(enum) { |
| 87 | 90 | TopLevel, |
| 88 | 91 | TopLevelExtern: ?Token, |
| ... | ... | @@ -110,8 +113,10 @@ pub const Parser = struct { |
| 110 | 113 | FnDef: &ast.NodeFnProto, |
| 111 | 114 | Block: &ast.NodeBlock, |
| 112 | 115 | Statement: &ast.NodeBlock, |
| 113 | | ExprListItemOrEnd: ExprListState, |
| 114 | | ExprListCommaOrEnd: ExprListState, |
| 116 | ExprListItemOrEnd: ListState(&ast.Node), |
| 117 | ExprListCommaOrEnd: ListState(&ast.Node), |
| 118 | FieldInitListItemOrEnd: ListState(&ast.NodeFieldInitializer), |
| 119 | FieldInitListCommaOrEnd: ListState(&ast.NodeFieldInitializer), |
| 115 | 120 | }; |
| 116 | 121 | |
| 117 | 122 | /// Returns an AST tree, allocated with the parser's allocator. |
| ... | ... | @@ -536,7 +541,7 @@ pub const Parser = struct { |
| 536 | 541 | }); |
| 537 | 542 | try stack.append(State.AfterOperand); |
| 538 | 543 | try stack.append(State { |
| 539 | | .ExprListItemOrEnd = ExprListState { |
| 544 | .ExprListItemOrEnd = ListState(&ast.Node) { |
| 540 | 545 | .list = &node.params, |
| 541 | 546 | .end = Token.Id.RParen, |
| 542 | 547 | .ptr = &node.rparen_token, |
| ... | ... | @@ -647,8 +652,6 @@ pub const Parser = struct { |
| 647 | 652 | continue; |
| 648 | 653 | |
| 649 | 654 | } else if (token.id == Token.Id.LParen) { |
| 650 | | self.putBackToken(token); |
| 651 | | |
| 652 | 655 | const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp { |
| 653 | 656 | .Call = ast.NodeSuffixOp.CallInfo { |
| 654 | 657 | .params = ArrayList(&ast.Node).init(arena), |
| ... | ... | @@ -658,18 +661,12 @@ pub const Parser = struct { |
| 658 | 661 | try stack.append(State { .SuffixOp = node }); |
| 659 | 662 | try stack.append(State.AfterOperand); |
| 660 | 663 | try stack.append(State { |
| 661 | | .ExprListItemOrEnd = ExprListState { |
| 664 | .ExprListItemOrEnd = ListState(&ast.Node) { |
| 662 | 665 | .list = &node.op.Call.params, |
| 663 | 666 | .end = Token.Id.RParen, |
| 664 | 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 | 670 | continue; |
| 674 | 671 | |
| 675 | 672 | } else if (token.id == Token.Id.LBracket) { |
| ... | ... | @@ -686,6 +683,47 @@ pub const Parser = struct { |
| 686 | 683 | try stack.append(State { .Expression = DestPtr { .Field = &node.op.ArrayAccess }}); |
| 687 | 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 | 727 | // TODO: Parse postfix operator |
| 690 | 728 | } else { |
| 691 | 729 | // no postfix/infix operator after this operand. |
| ... | ... | @@ -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 | 773 | var token = self.getNextToken(); |
| 722 | 774 | switch (token.id) { |
| 723 | | Token.Id.RParen => continue, |
| 775 | Token.Id.Comma => { |
| 776 | stack.append(State { .ExprListItemOrEnd = list_state }) catch unreachable; |
| 777 | }, |
| 724 | 778 | else => { |
| 725 | | self.putBackToken(token); |
| 726 | | stack.append(State { .ExprListCommaOrEnd = expr_list_state }) catch unreachable; |
| 727 | | try stack.append(State { .Expression = DestPtr{.List = expr_list_state.list} }); |
| 779 | const IdTag = @TagType(Token.Id); |
| 780 | if (IdTag(list_state.end) == token.id) { |
| 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 | 828 | var token = self.getNextToken(); |
| 734 | 829 | switch (token.id) { |
| 735 | 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 | 833 | else => { |
| 739 | 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 | 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 | }, |