(precedence ast.OperatorPrecedence, leftOperand *ast.Expression, pos int)
| 4583 | } |
| 4584 | |
| 4585 | func (p *Parser) parseBinaryExpressionRest(precedence ast.OperatorPrecedence, leftOperand *ast.Expression, pos int) *ast.Expression { |
| 4586 | lastOperand := leftOperand |
| 4587 | for { |
| 4588 | // We either have a binary operator here, or we're finished. We call |
| 4589 | // reScanGreaterToken so that we merge token sequences like > and = into >= |
| 4590 | operator := p.reScanGreaterThanToken() |
| 4591 | newPrecedence := ast.GetBinaryOperatorPrecedence(operator) |
| 4592 | // Check the precedence to see if we should "take" this operator |
| 4593 | // - For left associative operator (all operator but **), consume the operator, |
| 4594 | // recursively call the function below, and parse binaryExpression as a rightOperand |
| 4595 | // of the caller if the new precedence of the operator is greater then or equal to the current precedence. |
| 4596 | // For example: |
| 4597 | // a - b - c; |
| 4598 | // ^token; leftOperand = b. Return b to the caller as a rightOperand |
| 4599 | // a * b - c |
| 4600 | // ^token; leftOperand = b. Return b to the caller as a rightOperand |
| 4601 | // a - b * c; |
| 4602 | // ^token; leftOperand = b. Return b * c to the caller as a rightOperand |
| 4603 | // - For right associative operator (**), consume the operator, recursively call the function |
| 4604 | // and parse binaryExpression as a rightOperand of the caller if the new precedence of |
| 4605 | // the operator is strictly grater than the current precedence |
| 4606 | // For example: |
| 4607 | // a ** b ** c; |
| 4608 | // ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand |
| 4609 | // a - b ** c; |
| 4610 | // ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand |
| 4611 | // a ** b - c |
| 4612 | // ^token; leftOperand = b. Return b to the caller as a rightOperand |
| 4613 | var consumeCurrentOperator bool |
| 4614 | if operator == ast.KindAsteriskAsteriskToken { |
| 4615 | consumeCurrentOperator = newPrecedence >= precedence |
| 4616 | } else { |
| 4617 | consumeCurrentOperator = newPrecedence > precedence |
| 4618 | } |
| 4619 | if !consumeCurrentOperator { |
| 4620 | break |
| 4621 | } |
| 4622 | if operator == ast.KindInKeyword && p.inDisallowInContext() { |
| 4623 | break |
| 4624 | } |
| 4625 | if operator == ast.KindAsKeyword || operator == ast.KindSatisfiesKeyword { |
| 4626 | // Make sure we *do* perform ASI for constructs like this: |
| 4627 | // var x = foo |
| 4628 | // as (Bar) |
| 4629 | // This should be parsed as an initialized variable, followed |
| 4630 | // by a function call to 'as' with the argument 'Bar' |
| 4631 | if p.hasPrecedingLineBreak() { |
| 4632 | break |
| 4633 | } else { |
| 4634 | p.nextToken() |
| 4635 | // When we have 'a ## b as SomeType' or 'a ## b satisfies SomeType', where ## is some binary |
| 4636 | // operator, we want to stop parsing on any following operator with a higher precedence than ## |
| 4637 | // because continuing would make it impossible to erase the `as` or `satisfies` without changing |
| 4638 | // the meaning of the expression. See https://github.com/microsoft/TypeScript/issues/63527. |
| 4639 | lastPrecedence := ast.OperatorPrecedenceHighest |
| 4640 | if ast.IsBinaryExpression(lastOperand) { |
| 4641 | lastPrecedence = ast.GetBinaryOperatorPrecedence(lastOperand.AsBinaryExpression().OperatorToken.Kind) |
| 4642 | } |
no test coverage detected