@@ -2240,9 +2240,16 @@ module ts {
22402240 return arrowExpression ;
22412241 }
22422242
2243- // Now try to handle the rest of the cases. First, see if we can parse out up to and
2244- // including a conditional expression.
2245- var expr = parseConditionalExpression ( ) ;
2243+ // Now try to see if we're in production '1', '2' or '3'. A conditional expression can
2244+ // start with a LogicalOrExpression, while the assignment productions can only start with
2245+ // LeftHandSideExpressions.
2246+ //
2247+ // So, first, we try to just parse out a BinaryExpression. If we get something that is a
2248+ // LeftHandSide or higher, then we can try to parse out the assignment expression part.
2249+ // Otherwise, we try to parse out the conditional expression bit. We want to allow any
2250+ // binary expression here, so we pass in the 'lowest' precedence here so that it matches
2251+ // and consumes anything.
2252+ var expr = parseBinaryExpressionOrHigher ( /*precedence:*/ 0 ) ;
22462253
22472254 // To avoid a look-ahead, we did not handle the case of an arrow function with a single un-parenthesized
22482255 // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single
@@ -2254,14 +2261,17 @@ module ts {
22542261 // Now see if we might be in cases '2' or '3'.
22552262 // If the expression was a LHS expression, and we have an assignment operator, then
22562263 // we're in '2' or '3'. Consume the assignment and return.
2257- if ( isLeftHandSideExpression ( expr ) && isAssignmentOperator ( token ) ) {
2264+ //
2265+ // Note: we call reScanGreaterToken so that we get an appropriately merged token
2266+ // for cases like > > = becoming >>=
2267+ if ( isLeftHandSideExpression ( expr ) && isAssignmentOperator ( reScanGreaterToken ( ) ) ) {
22582268 var operator = token ;
22592269 nextToken ( ) ;
22602270 return makeBinaryExpression ( expr , operator , parseAssignmentExpressionOrHigher ( ) ) ;
22612271 }
22622272
2263- // otherwise this was production '1'. Return whatever we parsed so far.
2264- return expr ;
2273+ // It wasn't an assignment or a lambda. This is a conditional expression:
2274+ return parseConditionalExpressionRest ( expr ) ;
22652275 }
22662276
22672277 function isYieldExpression ( ) : boolean {
@@ -2505,35 +2515,50 @@ module ts {
25052515 return makeFunctionExpression ( SyntaxKind . ArrowFunction , pos , /*asteriskToken:*/ undefined , /*name:*/ undefined , sig , body ) ;
25062516 }
25072517
2508- function parseConditionalExpression ( ) : Expression {
2509- // Note: we explicitly 'allowIn' in the whenTrue part of the condition expression, and
2510- // we do not that for the 'whenFalse' part.
2511-
2512- var expr = parseBinaryOperators ( parseUnaryExpression ( ) , /*minPrecedence:*/ 0 ) ;
2518+ function parseConditionalExpressionRest ( leftOperand : Expression ) : Expression {
2519+ // Note: we are passed in an expression which was produced from parseBinaryExpressionOrHigher.
25132520 if ( ! parseOptional ( SyntaxKind . QuestionToken ) ) {
2514- return expr ;
2521+ return leftOperand ;
25152522 }
25162523
2517- var node = < ConditionalExpression > createNode ( SyntaxKind . ConditionalExpression , expr . pos ) ;
2518- node . condition = expr ;
2524+ // Note: we explicitly 'allowIn' in the whenTrue part of the condition expression, and
2525+ // we do not that for the 'whenFalse' part.
2526+ var node = < ConditionalExpression > createNode ( SyntaxKind . ConditionalExpression , leftOperand . pos ) ;
2527+ node . condition = leftOperand ;
25192528 node . whenTrue = allowInAnd ( parseAssignmentExpressionOrHigher ) ;
25202529 parseExpected ( SyntaxKind . ColonToken ) ;
25212530 node . whenFalse = parseAssignmentExpressionOrHigher ( ) ;
25222531 return finishNode ( node ) ;
25232532 }
25242533
2525- function parseBinaryOperators ( expr : Expression , minPrecedence : number ) : Expression {
2534+ function parseBinaryExpressionOrHigher ( precedence : number ) : Expression {
2535+ var leftOperand = parseUnaryExpression ( ) ;
2536+ return parseBinaryExpressionRest ( precedence , leftOperand ) ;
2537+ }
2538+
2539+ function parseBinaryExpressionRest ( precedence : number , leftOperand : Expression ) : Expression {
25262540 while ( true ) {
2541+ // We either have a binary operator here, or we're finished. We call
2542+ // reScanGreaterToken so that we merge token sequences like > and = into >=
2543+
25272544 reScanGreaterToken ( ) ;
2528- var precedence = getOperatorPrecedence ( ) ;
2529- if ( precedence && precedence > minPrecedence && ( ! inDisallowInContext ( ) || token !== SyntaxKind . InKeyword ) ) {
2530- var operator = token ;
2531- nextToken ( ) ;
2532- expr = makeBinaryExpression ( expr , operator , parseBinaryOperators ( parseUnaryExpression ( ) , precedence ) ) ;
2533- continue ;
2545+ var newPrecedence = getOperatorPrecedence ( ) ;
2546+
2547+ // Check the precedence to see if we should "take" this operator
2548+ if ( newPrecedence <= precedence ) {
2549+ break ;
25342550 }
2535- return expr ;
2551+
2552+ if ( token === SyntaxKind . InKeyword && inDisallowInContext ( ) ) {
2553+ break ;
2554+ }
2555+
2556+ var operator = token ;
2557+ nextToken ( ) ;
2558+ leftOperand = makeBinaryExpression ( leftOperand , operator , parseBinaryExpressionOrHigher ( newPrecedence ) ) ;
25362559 }
2560+
2561+ return leftOperand ;
25372562 }
25382563
25392564 function getOperatorPrecedence ( ) : number {
@@ -2572,7 +2597,10 @@ module ts {
25722597 case SyntaxKind . PercentToken :
25732598 return 10 ;
25742599 }
2575- return undefined ;
2600+
2601+ // -1 is lower than all other precedences. Returning it will cause binary expression
2602+ // parsing to stop.
2603+ return - 1 ;
25762604 }
25772605
25782606 function makeBinaryExpression ( left : Expression , operator : SyntaxKind , right : Expression ) : BinaryExpression {
0 commit comments