| ... | @@ -77,6 +77,12 @@ pub const Parser = struct { | ... | @@ -77,6 +77,12 @@ pub const Parser = struct { |
| 77 | ptr: &Token, | 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 | const State = union(enum) { | 86 | const State = union(enum) { |
| 81 | TopLevel, | 87 | TopLevel, |
| 82 | TopLevelExtern: ?Token, | 88 | TopLevelExtern: ?Token, |
| ... | @@ -88,7 +94,7 @@ pub const Parser = struct { | ... | @@ -88,7 +94,7 @@ pub const Parser = struct { |
| 88 | InfixOp: &ast.NodeInfixOp, | 94 | InfixOp: &ast.NodeInfixOp, |
| 89 | PrefixOp: &ast.NodePrefixOp, | 95 | PrefixOp: &ast.NodePrefixOp, |
| 90 | SuffixOp: &ast.NodeSuffixOp, | 96 | SuffixOp: &ast.NodeSuffixOp, |
| 91 | SliceOrArrayAccess, | 97 | SliceOrArrayAccess: &ast.NodeSuffixOp, |
| 92 | AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo, | 98 | AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo, |
| 93 | TypeExpr: DestPtr, | 99 | TypeExpr: DestPtr, |
| 94 | VarDecl: &ast.NodeVarDecl, | 100 | VarDecl: &ast.NodeVarDecl, |
| ... | @@ -104,8 +110,8 @@ pub const Parser = struct { | ... | @@ -104,8 +110,8 @@ pub const Parser = struct { |
| 104 | FnDef: &ast.NodeFnProto, | 110 | FnDef: &ast.NodeFnProto, |
| 105 | Block: &ast.NodeBlock, | 111 | Block: &ast.NodeBlock, |
| 106 | Statement: &ast.NodeBlock, | 112 | Statement: &ast.NodeBlock, |
| 107 | ExprListItemOrEnd: &ArrayList(&ast.Node), | 113 | ExprListItemOrEnd: ExprListState, |
| 108 | ExprListCommaOrEnd: &ArrayList(&ast.Node), | 114 | ExprListCommaOrEnd: ExprListState, |
| 109 | }; | 115 | }; |
| 110 | | 116 | |
| 111 | /// Returns an AST tree, allocated with the parser's allocator. | 117 | /// Returns an AST tree, allocated with the parser's allocator. |
| ... | @@ -529,13 +535,14 @@ pub const Parser = struct { | ... | @@ -529,13 +535,14 @@ pub const Parser = struct { |
| 529 | .Operand = &node.base | 535 | .Operand = &node.base |
| 530 | }); | 536 | }); |
| 531 | try stack.append(State.AfterOperand); | 537 | try stack.append(State.AfterOperand); |
| 532 | try stack.append(State {.ExprListItemOrEnd = &node.params }); | | |
| 533 | try stack.append(State { | 538 | try stack.append(State { |
| 534 | .ExpectTokenSave = ExpectTokenSave { | 539 | .ExprListItemOrEnd = ExprListState { |
| 535 | .id = Token.Id.LParen, | 540 | .list = &node.params, |
| | 541 | .end = Token.Id.RParen, |
| 536 | .ptr = &node.rparen_token, | 542 | .ptr = &node.rparen_token, |
| 537 | }, | 543 | } |
| 538 | }); | 544 | }); |
| | 545 | try stack.append(State { .ExpectToken = Token.Id.LParen, }); |
| 539 | continue; | 546 | continue; |
| 540 | }, | 547 | }, |
| 541 | Token.Id.StringLiteral => { | 548 | Token.Id.StringLiteral => { |
| ... | @@ -587,6 +594,46 @@ pub const Parser = struct { | ... | @@ -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 | State.AfterOperand => { | 637 | State.AfterOperand => { |
| 591 | // we'll either get an infix operator (like != or ^), | 638 | // we'll either get an infix operator (like != or ^), |
| 592 | // or a postfix operator (like () or {}), | 639 | // or a postfix operator (like () or {}), |
| ... | @@ -610,7 +657,13 @@ pub const Parser = struct { | ... | @@ -610,7 +657,13 @@ pub const Parser = struct { |
| 610 | }); | 657 | }); |
| 611 | try stack.append(State { .SuffixOp = node }); | 658 | try stack.append(State { .SuffixOp = node }); |
| 612 | try stack.append(State.AfterOperand); | 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 | try stack.append(State { | 667 | try stack.append(State { |
| 615 | .ExpectTokenSave = ExpectTokenSave { | 668 | .ExpectTokenSave = ExpectTokenSave { |
| 616 | .id = Token.Id.LParen, | 669 | .id = Token.Id.LParen, |
| ... | @@ -620,8 +673,17 @@ pub const Parser = struct { | ... | @@ -620,8 +673,17 @@ pub const Parser = struct { |
| 620 | continue; | 673 | continue; |
| 621 | | 674 | |
| 622 | } else if (token.id == Token.Id.LBracket) { | 675 | } else if (token.id == Token.Id.LBracket) { |
| 623 | try stack.append(State.SliceOrArrayAccess); | 676 | const node = try arena.create(ast.NodeSuffixOp); |
| 624 | try stack.append(State.ExpectOperand); | 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 | continue; | 687 | continue; |
| 626 | | 688 | |
| 627 | // TODO: Parse postfix operator | 689 | // TODO: Parse postfix operator |
| ... | @@ -637,48 +699,6 @@ pub const Parser = struct { | ... | @@ -637,48 +699,6 @@ pub const Parser = struct { |
| 637 | try dest_ptr.store(expression); | 699 | try dest_ptr.store(expression); |
| 638 | break; | 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 | State.InfixOp => |infix_op| { | 702 | State.InfixOp => |infix_op| { |
| 683 | infix_op.rhs = expression; | 703 | infix_op.rhs = expression; |
| 684 | infix_op.lhs = popSuffixOp(&stack); | 704 | infix_op.lhs = popSuffixOp(&stack); |
| ... | @@ -697,26 +717,31 @@ pub const Parser = struct { | ... | @@ -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 | var token = self.getNextToken(); | 721 | var token = self.getNextToken(); |
| 702 | switch (token.id) { | 722 | switch (token.id) { |
| 703 | Token.Id.RParen => continue, | 723 | Token.Id.RParen => continue, |
| 704 | else => { | 724 | else => { |
| 705 | self.putBackToken(token); | 725 | self.putBackToken(token); |
| 706 | stack.append(State { .ExprListCommaOrEnd = params }) catch unreachable; | 726 | stack.append(State { .ExprListCommaOrEnd = expr_list_state }) catch unreachable; |
| 707 | try stack.append(State { .Expression = DestPtr{.List = params} }); | 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 | var token = self.getNextToken(); | 733 | var token = self.getNextToken(); |
| 714 | switch (token.id) { | 734 | switch (token.id) { |
| 715 | Token.Id.Comma => { | 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,7 +958,6 @@ pub const Parser = struct { |
| 933 | State.PrefixOp => unreachable, | 958 | State.PrefixOp => unreachable, |
| 934 | State.SuffixOp => unreachable, | 959 | State.SuffixOp => unreachable, |
| 935 | State.Operand => unreachable, | 960 | State.Operand => unreachable, |
| 936 | State.SliceOrArrayAccess => unreachable, | | |
| 937 | } | 961 | } |
| 938 | } | 962 | } |
| 939 | } | 963 | } |
| ... | @@ -1649,6 +1673,11 @@ pub const Parser = struct { | ... | @@ -1649,6 +1673,11 @@ pub const Parser = struct { |
| 1649 | | 1673 | |
| 1650 | try stack.append(RenderState { .Expression = suffix_op.lhs }); | 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 | ast.Node.Id.IntegerLiteral => { | 1681 | ast.Node.Id.IntegerLiteral => { |
| 1653 | const integer_literal = @fieldParentPtr(ast.NodeIntegerLiteral, "base", base); | 1682 | const integer_literal = @fieldParentPtr(ast.NodeIntegerLiteral, "base", base); |
| 1654 | try stream.print("{}", self.tokenizer.getTokenSlice(integer_literal.token)); | 1683 | try stream.print("{}", self.tokenizer.getTokenSlice(integer_literal.token)); |