()
| 762 | |
| 763 | // decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE |
| 764 | private _parseDecorator(): DecoratorNode { |
| 765 | let atOperator = this._getNextToken() as OperatorToken; |
| 766 | assert.equal(atOperator.operatorType, OperatorType.MatrixMultiply); |
| 767 | |
| 768 | let callNameExpr: ExpressionNode | undefined; |
| 769 | while (true) { |
| 770 | let namePart = this._getTokenIfIdentifier(); |
| 771 | if (!namePart) { |
| 772 | this._addError('Expected decorator name', this._peekToken()); |
| 773 | break; |
| 774 | } |
| 775 | |
| 776 | let namePartNode = new NameNode(namePart); |
| 777 | |
| 778 | if (!callNameExpr) { |
| 779 | callNameExpr = namePartNode; |
| 780 | } else { |
| 781 | callNameExpr = new MemberAccessExpressionNode(callNameExpr, namePartNode); |
| 782 | } |
| 783 | |
| 784 | if (!this._consumeTokenIfType(TokenType.Dot)) { |
| 785 | break; |
| 786 | } |
| 787 | } |
| 788 | |
| 789 | if (!callNameExpr) { |
| 790 | callNameExpr = new ErrorExpressionNode(this._peekToken()); |
| 791 | } |
| 792 | |
| 793 | let decoratorNode = new DecoratorNode(atOperator, callNameExpr); |
| 794 | |
| 795 | if (this._consumeTokenIfType(TokenType.OpenParenthesis)) { |
| 796 | decoratorNode.arguments = this._parseArgList(); |
| 797 | |
| 798 | let nextToken = this._peekToken(); |
| 799 | if (!this._consumeTokenIfType(TokenType.CloseParenthesis)) { |
| 800 | this._addError('Expected ")"', this._peekToken()); |
| 801 | } else { |
| 802 | decoratorNode.extend(nextToken); |
| 803 | } |
| 804 | } |
| 805 | |
| 806 | if (!this._consumeTokenIfType(TokenType.NewLine)) { |
| 807 | this._addError('Expected new line at end of decorator', this._peekToken()); |
| 808 | this._consumeTokensUntilType(TokenType.NewLine); |
| 809 | } |
| 810 | |
| 811 | return decoratorNode; |
| 812 | } |
| 813 | |
| 814 | // classdef: 'class' NAME ['(' [arglist] ')'] suite |
| 815 | private _parseClassDef(decorators?: DecoratorNode[]): ClassNode { |
no test coverage detected