mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-14 16:56:06 -05:00
Modified associativity rules due to addition of exponentiation operator.
This commit is contained in:
@@ -135,22 +135,7 @@ namespace ts {
|
||||
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
// export function createSourceFileNode(): SourceFile {
|
||||
// let node = <SourceFile>createNode(SyntaxKind.SourceFile);
|
||||
// return node;
|
||||
// }
|
||||
|
||||
// export function updateSourceFileNode(node: SourceFile, statements: NodeArray<Statement>, endOfFileToken: Node): SourceFile {
|
||||
// if (statements !== node.statements || endOfFileToken !== node.endOfFileToken) {
|
||||
// let newNode = createNode<SourceFile>(SyntaxKind.SourceFile);
|
||||
// newNode.statements = statements;
|
||||
// newNode.endOfFileToken = endOfFileToken;
|
||||
// return updateFrom(node, newNode);
|
||||
// }
|
||||
// return node;
|
||||
// }
|
||||
|
||||
|
||||
export function createNumericLiteral2(value: number, location?: TextRange, flags?: NodeFlags): LiteralExpression {
|
||||
let node = createNumericLiteral(String(value), location, flags);
|
||||
return node;
|
||||
@@ -168,30 +153,54 @@ namespace ts {
|
||||
return nodeIsSynthesized(node) ? node : cloneNode(node);
|
||||
}
|
||||
|
||||
export function parenthesizeForBinary(expr: Expression, operator: SyntaxKind) {
|
||||
const enum BinaryOperandSide {
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
|
||||
function parenthesizeForBinary(operand: Expression, operator: SyntaxKind, side: BinaryOperandSide) {
|
||||
// When diagnosing whether the expression needs parentheses, the decision should be based
|
||||
// on the innermost expression in a chain of nested type assertions.
|
||||
while (expr.kind === SyntaxKind.TypeAssertionExpression || expr.kind === SyntaxKind.AsExpression) {
|
||||
expr = (<AssertionExpression>expr).expression;
|
||||
while (operand.kind === SyntaxKind.TypeAssertionExpression || operand.kind === SyntaxKind.AsExpression) {
|
||||
operand = (<AssertionExpression>operand).expression;
|
||||
}
|
||||
|
||||
// If the resulting expression is already parenthesized, we do not need to do any further processing.
|
||||
if (isParenthesizedExpression(expr)) {
|
||||
return expr;
|
||||
if (isParenthesizedExpression(operand)) {
|
||||
return operand;
|
||||
}
|
||||
|
||||
let exprPrecedence = getExpressionPrecedence(expr);
|
||||
return needsParenthesesForBinary(operand, operator, side)
|
||||
? createParenthesizedExpression(operand)
|
||||
: operand;
|
||||
}
|
||||
|
||||
function needsParenthesesForBinary(operand: Expression, operator: SyntaxKind, side: BinaryOperandSide) {
|
||||
let operandPrecedence = getExpressionPrecedence(operand);
|
||||
let operatorPrecedence = getBinaryOperatorPrecedence(operator);
|
||||
if (exprPrecedence < operatorPrecedence) {
|
||||
// lower precedence, the expression needs parenthesis
|
||||
return createParenthesizedExpression(expr);
|
||||
}
|
||||
else {
|
||||
// higher precedence.
|
||||
return expr;
|
||||
switch (compareValues(operandPrecedence, operatorPrecedence)) {
|
||||
case Comparison.LessThan:
|
||||
return true;
|
||||
case Comparison.EqualTo:
|
||||
return isRightAssociativeOperandOnLeftHandSide(operand, side)
|
||||
|| isModuloOperandOnRightHandSide(operand, operator, side);
|
||||
case Comparison.GreaterThan:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isRightAssociativeOperandOnLeftHandSide(operand: Expression, side: BinaryOperandSide) {
|
||||
return side === BinaryOperandSide.Left
|
||||
&& getExpressionAssociativity(operand) === Associativity.Right;
|
||||
}
|
||||
|
||||
function isModuloOperandOnRightHandSide(operand: Expression, operator: SyntaxKind, side: BinaryOperandSide) {
|
||||
return side === BinaryOperandSide.Right
|
||||
&& operator !== SyntaxKind.PercentToken
|
||||
&& isBinaryExpression(operand)
|
||||
&& operand.operatorToken.kind === SyntaxKind.PercentToken;
|
||||
}
|
||||
|
||||
export function parenthesizeForAccess(expr: Expression): LeftHandSideExpression {
|
||||
// When diagnosing whether the expression needs parentheses, the decision should be based
|
||||
// on the innermost expression in a chain of nested type assertions.
|
||||
@@ -262,7 +271,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function createBinaryExpression2(left: Expression, operator: SyntaxKind, right: Expression, location?: TextRange) {
|
||||
return createBinaryExpression(parenthesizeForBinary(left, operator), createNode(operator), parenthesizeForBinary(right, operator), location);
|
||||
return createBinaryExpression(parenthesizeForBinary(left, operator, BinaryOperandSide.Left), createNode(operator), parenthesizeForBinary(right, operator, BinaryOperandSide.Right), location);
|
||||
}
|
||||
|
||||
export function createConditionalExpression2(condition: Expression, whenTrue: Expression, whenFalse: Expression, location?: TextRange, flags?: NodeFlags) {
|
||||
|
||||
@@ -1072,6 +1072,56 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export const enum Associativity {
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
|
||||
export function getExpressionAssociativity(expr: Expression) {
|
||||
return getOperatorAssociativity(expr.kind, getOperator(expr), isNewExpression(expr) && !expr.arguments);
|
||||
}
|
||||
|
||||
export function getBinaryOperatorAssociativity(operator: SyntaxKind) {
|
||||
return getOperatorAssociativity(SyntaxKind.BinaryExpression, operator);
|
||||
}
|
||||
|
||||
export function getOperatorAssociativity(kind: SyntaxKind, operator: SyntaxKind, isNewExpressionWithoutArguments?: boolean) {
|
||||
switch (kind) {
|
||||
case SyntaxKind.NewExpression:
|
||||
return isNewExpressionWithoutArguments ? Associativity.Right : Associativity.Left;
|
||||
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
case SyntaxKind.TypeOfExpression:
|
||||
case SyntaxKind.VoidExpression:
|
||||
case SyntaxKind.DeleteExpression:
|
||||
case SyntaxKind.AwaitExpression:
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
case SyntaxKind.YieldExpression:
|
||||
return Associativity.Right;
|
||||
|
||||
case SyntaxKind.BinaryExpression:
|
||||
switch (operator) {
|
||||
case SyntaxKind.AsteriskAsteriskToken:
|
||||
case SyntaxKind.EqualsToken:
|
||||
case SyntaxKind.PlusEqualsToken:
|
||||
case SyntaxKind.MinusEqualsToken:
|
||||
case SyntaxKind.AsteriskAsteriskEqualsToken:
|
||||
case SyntaxKind.AsteriskEqualsToken:
|
||||
case SyntaxKind.SlashEqualsToken:
|
||||
case SyntaxKind.PercentEqualsToken:
|
||||
case SyntaxKind.LessThanLessThanEqualsToken:
|
||||
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
|
||||
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
|
||||
case SyntaxKind.AmpersandEqualsToken:
|
||||
case SyntaxKind.CaretEqualsToken:
|
||||
case SyntaxKind.BarEqualsToken:
|
||||
return Associativity.Right;
|
||||
}
|
||||
}
|
||||
|
||||
return Associativity.Left;
|
||||
}
|
||||
|
||||
export function getExpressionPrecedence(expr: Expression) {
|
||||
return getOperatorPrecedence(expr.kind, getOperator(expr), isNewExpression(expr) && !expr.arguments)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user