| ... | ... | @@ -77,6 +77,12 @@ pub const Parser = struct { |
| 77 | 77 | ptr: &Token, |
| 78 | 78 | }; |
| 79 | 79 | |
| 80 | const ExprListState = struct { |
| 81 | list: &ArrayList(&ast.Node), |
| 82 | end: Token.Id, |
| 83 | ptr: &Token, |
| 84 | }; |
| 85 | |
| 80 | 86 | const State = union(enum) { |
| 81 | 87 | TopLevel, |
| 82 | 88 | TopLevelExtern: ?Token, |
| ... | ... | @@ -88,7 +94,7 @@ pub const Parser = struct { |
| 88 | 94 | InfixOp: &ast.NodeInfixOp, |
| 89 | 95 | PrefixOp: &ast.NodePrefixOp, |
| 90 | 96 | SuffixOp: &ast.NodeSuffixOp, |
| 91 | | SliceOrArrayAccess, |
| 97 | SliceOrArrayAccess: &ast.NodeSuffixOp, |
| 92 | 98 | AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo, |
| 93 | 99 | TypeExpr: DestPtr, |
| 94 | 100 | VarDecl: &ast.NodeVarDecl, |
| ... | ... | @@ -104,8 +110,8 @@ pub const Parser = struct { |
| 104 | 110 | FnDef: &ast.NodeFnProto, |
| 105 | 111 | Block: &ast.NodeBlock, |
| 106 | 112 | Statement: &ast.NodeBlock, |
| 107 | | ExprListItemOrEnd: &ArrayList(&ast.Node), |
| 108 | | ExprListCommaOrEnd: &ArrayList(&ast.Node), |
| 113 | ExprListItemOrEnd: ExprListState, |
| 114 | ExprListCommaOrEnd: ExprListState, |
| 109 | 115 | }; |
| 110 | 116 | |
| 111 | 117 | /// Returns an AST tree, allocated with the parser's allocator. |
| ... | ... | @@ -529,13 +535,14 @@ pub const Parser = struct { |
| 529 | 535 | .Operand = &node.base |
| 530 | 536 | }); |
| 531 | 537 | try stack.append(State.AfterOperand); |
| 532 | | try stack.append(State {.ExprListItemOrEnd = &node.params }); |
| 533 | 538 | try stack.append(State { |
| 534 | | .ExpectTokenSave = ExpectTokenSave { |
| 535 | | .id = Token.Id.LParen, |
| 539 | .ExprListItemOrEnd = ExprListState { |
| 540 | .list = &node.params, |
| 541 | .end = Token.Id.RParen, |
| 536 | 542 | .ptr = &node.rparen_token, |
| 537 | | }, |
| 543 | } |
| 538 | 544 | }); |
| 545 | try stack.append(State { .ExpectToken = Token.Id.LParen, }); |
| 539 | 546 | continue; |
| 540 | 547 | }, |
| 541 | 548 | Token.Id.StringLiteral => { |
| ... | ... | @@ -587,6 +594,46 @@ pub const Parser = struct { |
| 587 | 594 | } |
| 588 | 595 | }, |
| 589 | 596 | |
| 597 | State.SliceOrArrayAccess => |node| { |
| 598 | var token = self.getNextToken(); |
| 599 | |
| 600 | switch (token.id) { |
| 601 | Token.Id.Ellipsis2 => { |
| 602 | const start = node.op.ArrayAccess; |
| 603 | node.op = ast.NodeSuffixOp.SuffixOp { |
| 604 | .Slice = ast.NodeSuffixOp.SliceRange { |
| 605 | .start = start, |
| 606 | .end = undefined, |
| 607 | } |
| 608 | }; |
| 609 | try stack.append(State { .SuffixOp = node }); |
| 610 | try stack.append(State.AfterOperand); |
| 611 | |
| 612 | const rbracket_token = self.getNextToken(); |
| 613 | if (rbracket_token.id != Token.Id.RBracket) { |
| 614 | self.putBackToken(rbracket_token); |
| 615 | try stack.append(State { |
| 616 | .ExpectTokenSave = ExpectTokenSave { |
| 617 | .id = Token.Id.RBracket, |
| 618 | .ptr = &node.rtoken, |
| 619 | } |
| 620 | }); |
| 621 | try stack.append(State { .Expression = DestPtr { .NullableField = &node.op.Slice.end } }); |
| 622 | } else { |
| 623 | node.rtoken = rbracket_token; |
| 624 | } |
| 625 | continue; |
| 626 | }, |
| 627 | Token.Id.RBracket => { |
| 628 | node.rtoken = token; |
| 629 | try stack.append(State { .SuffixOp = node }); |
| 630 | try stack.append(State.AfterOperand); |
| 631 | continue; |
| 632 | }, |
| 633 | else => return self.parseError(token, "expected ']' or '..', found {}", @tagName(token.id)) |
| 634 | } |
| 635 | }, |
| 636 | |
| 590 | 637 | State.AfterOperand => { |
| 591 | 638 | // we'll either get an infix operator (like != or ^), |
| 592 | 639 | // or a postfix operator (like () or {}), |
| ... | ... | @@ -610,7 +657,13 @@ pub const Parser = struct { |
| 610 | 657 | }); |
| 611 | 658 | try stack.append(State { .SuffixOp = node }); |
| 612 | 659 | try stack.append(State.AfterOperand); |
| 613 | | try stack.append(State {.ExprListItemOrEnd = &node.op.Call.params }); |
| 660 | try stack.append(State { |
| 661 | .ExprListItemOrEnd = ExprListState { |
| 662 | .list = &node.op.Call.params, |
| 663 | .end = Token.Id.RParen, |
| 664 | .ptr = &node.rtoken, |
| 665 | } |
| 666 | }); |
| 614 | 667 | try stack.append(State { |
| 615 | 668 | .ExpectTokenSave = ExpectTokenSave { |
| 616 | 669 | .id = Token.Id.LParen, |
| ... | ... | @@ -620,8 +673,17 @@ pub const Parser = struct { |
| 620 | 673 | continue; |
| 621 | 674 | |
| 622 | 675 | } else if (token.id == Token.Id.LBracket) { |
| 623 | | try stack.append(State.SliceOrArrayAccess); |
| 624 | | try stack.append(State.ExpectOperand); |
| 676 | const node = try arena.create(ast.NodeSuffixOp); |
| 677 | *node = ast.NodeSuffixOp { |
| 678 | .base = self.initNode(ast.Node.Id.SuffixOp), |
| 679 | .lhs = undefined, |
| 680 | .op = ast.NodeSuffixOp.SuffixOp { |
| 681 | .ArrayAccess = undefined, |
| 682 | }, |
| 683 | .rtoken = undefined, |
| 684 | }; |
| 685 | try stack.append(State { .SliceOrArrayAccess = node }); |
| 686 | try stack.append(State { .Expression = DestPtr { .Field = &node.op.ArrayAccess }}); |
| 625 | 687 | continue; |
| 626 | 688 | |
| 627 | 689 | // TODO: Parse postfix operator |
| ... | ... | @@ -637,48 +699,6 @@ pub const Parser = struct { |
| 637 | 699 | try dest_ptr.store(expression); |
| 638 | 700 | break; |
| 639 | 701 | }, |
| 640 | | State.SliceOrArrayAccess => { |
| 641 | | var rbracket_or_ellipsis2_token = self.getNextToken(); |
| 642 | | |
| 643 | | switch (rbracket_or_ellipsis2_token.id) { |
| 644 | | Token.Id.Ellipsis2 => { |
| 645 | | const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp { |
| 646 | | .Slice = ast.NodeSuffixOp.SliceRange { |
| 647 | | .start = expression, |
| 648 | | .end = null, |
| 649 | | } |
| 650 | | }); |
| 651 | | |
| 652 | | try stack.append(State { .SuffixOp = node }); |
| 653 | | try stack.append(State.AfterOperand); |
| 654 | | |
| 655 | | const rbracket_token = self.getNextToken(); |
| 656 | | if (rbracket_token.id != Token.Id.RBracket) { |
| 657 | | self.putBackToken(rbracket_token); |
| 658 | | try stack.append(State { |
| 659 | | .ExpectTokenSave = ExpectTokenSave { |
| 660 | | .id = Token.Id.RBracket, |
| 661 | | .ptr = &node.rtoken, |
| 662 | | } |
| 663 | | }); |
| 664 | | try stack.append(State { .Expression = DestPtr { .NullableField = &node.op.Slice.end } }); |
| 665 | | } else { |
| 666 | | node.rtoken = rbracket_token; |
| 667 | | } |
| 668 | | break; |
| 669 | | }, |
| 670 | | Token.Id.RBracket => { |
| 671 | | const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp { |
| 672 | | .ArrayAccess = expression |
| 673 | | }); |
| 674 | | node.rtoken = token; |
| 675 | | try stack.append(State { .SuffixOp = node }); |
| 676 | | try stack.append(State.AfterOperand); |
| 677 | | break; |
| 678 | | }, |
| 679 | | else => return self.parseError(token, "expected ']' or '..', found {}", @tagName(token.id)) |
| 680 | | } |
| 681 | | }, |
| 682 | 702 | State.InfixOp => |infix_op| { |
| 683 | 703 | infix_op.rhs = expression; |
| 684 | 704 | infix_op.lhs = popSuffixOp(&stack); |
| ... | ... | @@ -697,26 +717,31 @@ pub const Parser = struct { |
| 697 | 717 | } |
| 698 | 718 | }, |
| 699 | 719 | |
| 700 | | State.ExprListItemOrEnd => |params| { |
| 720 | State.ExprListItemOrEnd => |expr_list_state| { |
| 701 | 721 | var token = self.getNextToken(); |
| 702 | 722 | switch (token.id) { |
| 703 | 723 | Token.Id.RParen => continue, |
| 704 | 724 | else => { |
| 705 | 725 | self.putBackToken(token); |
| 706 | | stack.append(State { .ExprListCommaOrEnd = params }) catch unreachable; |
| 707 | | try stack.append(State { .Expression = DestPtr{.List = params} }); |
| 726 | stack.append(State { .ExprListCommaOrEnd = expr_list_state }) catch unreachable; |
| 727 | try stack.append(State { .Expression = DestPtr{.List = expr_list_state.list} }); |
| 708 | 728 | }, |
| 709 | 729 | } |
| 710 | 730 | }, |
| 711 | 731 | |
| 712 | | State.ExprListCommaOrEnd => |params| { |
| 732 | State.ExprListCommaOrEnd => |expr_list_state| { |
| 713 | 733 | var token = self.getNextToken(); |
| 714 | 734 | switch (token.id) { |
| 715 | 735 | Token.Id.Comma => { |
| 716 | | stack.append(State { .ExprListItemOrEnd = params }) catch unreachable; |
| 736 | stack.append(State { .ExprListItemOrEnd = expr_list_state }) catch unreachable; |
| 737 | }, |
| 738 | else => { |
| 739 | const IdTag = @TagType(Token.Id); |
| 740 | if (IdTag(expr_list_state.end) == token.id) |
| 741 | continue; |
| 742 | |
| 743 | return self.parseError(token, "expected ',' or {}, found {}", @tagName(expr_list_state.end), @tagName(token.id)); |
| 717 | 744 | }, |
| 718 | | Token.Id.RParen => continue, |
| 719 | | else => return self.parseError(token, "expected ',' or ')', found {}", @tagName(token.id)), |
| 720 | 745 | } |
| 721 | 746 | }, |
| 722 | 747 | |
| ... | ... | @@ -933,7 +958,6 @@ pub const Parser = struct { |
| 933 | 958 | State.PrefixOp => unreachable, |
| 934 | 959 | State.SuffixOp => unreachable, |
| 935 | 960 | State.Operand => unreachable, |
| 936 | | State.SliceOrArrayAccess => unreachable, |
| 937 | 961 | } |
| 938 | 962 | } |
| 939 | 963 | } |
| ... | ... | @@ -1649,6 +1673,11 @@ pub const Parser = struct { |
| 1649 | 1673 | |
| 1650 | 1674 | try stack.append(RenderState { .Expression = suffix_op.lhs }); |
| 1651 | 1675 | }, |
| 1676 | ast.Node.Id.FieldInitializer => { |
| 1677 | const field_init = @fieldParentPtr(ast.NodeFieldInitializer, "base", base); |
| 1678 | try stream.print(".{} = ", self.tokenizer.getTokenSlice(field_init.name_token)); |
| 1679 | try stack.append(RenderState { .Expression = field_init.expr }); |
| 1680 | }, |
| 1652 | 1681 | ast.Node.Id.IntegerLiteral => { |
| 1653 | 1682 | const integer_literal = @fieldParentPtr(ast.NodeIntegerLiteral, "base", base); |
| 1654 | 1683 | try stream.print("{}", self.tokenizer.getTokenSlice(integer_literal.token)); |