@@ -1386,6 +1386,7 @@ module ts {
13861386 if ( inGeneratorParameterContext ( ) ) {
13871387 setYieldContext ( false ) ;
13881388 }
1389+
13891390 node . expression = allowInAnd ( parseExpression ) ;
13901391 if ( inGeneratorParameterContext ( ) ) {
13911392 setYieldContext ( yieldContext ) ;
@@ -1405,15 +1406,17 @@ module ts {
14051406 }
14061407
14071408 function parseAnyContextualModifier ( ) : boolean {
1408- return isModifier ( token ) && tryParse ( ( ) => {
1409- if ( token === SyntaxKind . ConstKeyword ) {
1410- // 'const' is only a modifier if followed by 'enum'.
1411- return nextToken ( ) === SyntaxKind . EnumKeyword ;
1412- }
1409+ return isModifier ( token ) && tryParse ( nextTokenCanFollowContextualModifier ) ;
1410+ }
14131411
1414- nextToken ( ) ;
1415- return canFollowModifier ( ) ;
1416- } ) ;
1412+ function nextTokenCanFollowContextualModifier ( ) {
1413+ if ( token === SyntaxKind . ConstKeyword ) {
1414+ // 'const' is only a modifier if followed by 'enum'.
1415+ return nextToken ( ) === SyntaxKind . EnumKeyword ;
1416+ }
1417+
1418+ nextToken ( ) ;
1419+ return canFollowModifier ( ) ;
14171420 }
14181421
14191422 function canFollowModifier ( ) : boolean {
@@ -2531,56 +2534,55 @@ module ts {
25312534
25322535 function parseSimpleArrowFunctionExpression ( identifier : Identifier ) : Expression {
25332536 Debug . assert ( token === SyntaxKind . EqualsGreaterThanToken , "parseSimpleArrowFunctionExpression should only have been called if we had a =>" ) ;
2537+
2538+ var node = < FunctionExpression > createNode ( SyntaxKind . ArrowFunction , identifier . pos ) ;
2539+
25342540 var parameter = < ParameterDeclaration > createNode ( SyntaxKind . Parameter , identifier . pos ) ;
2535- parseExpected ( SyntaxKind . EqualsGreaterThanToken ) ;
25362541 parameter . name = identifier ;
25372542 finishNode ( parameter ) ;
25382543
2539- var parameters = < NodeArray < ParameterDeclaration > > [ ] ;
2540- parameters . push ( parameter ) ;
2541- parameters . pos = parameter . pos ;
2542- parameters . end = parameter . end ;
2544+ node . parameters = < NodeArray < ParameterDeclaration > > [ parameter ] ;
2545+ node . parameters . pos = parameter . pos ;
2546+ node . parameters . end = parameter . end ;
25432547
2544- var signature = < ParsedSignature > { parameters : parameters } ;
2548+ parseExpected ( SyntaxKind . EqualsGreaterThanToken ) ;
2549+ node . body = parseArrowFunctionExpressionBody ( ) ;
25452550
2546- return parseArrowExpressionTail ( identifier . pos , signature ) ;
2551+ return finishNode ( node ) ;
25472552 }
25482553
25492554 function tryParseParenthesizedArrowFunctionExpression ( ) : Expression {
2550- // Indicates whether we are certain that we should parse an arrow expression.
25512555 var triState = isParenthesizedArrowFunctionExpression ( ) ;
25522556
25532557 if ( triState === Tristate . False ) {
2558+ // It's definitely not a parenthesized arrow function expression.
25542559 return undefined ;
25552560 }
25562561
2557- var pos = getNodePos ( ) ;
2558-
2559- if ( triState === Tristate . True ) {
2560- // Arrow function are never generators.
2561- var sig = parseSignature ( /*yieldAndGeneratorParameterContext:*/ false ) ;
2562+ // If we definitely have an arrow function, then we can just parse one, not requiring a
2563+ // following => or { token. Otherwise, we *might* have an arrow function. Try to parse
2564+ // it out, but don't allow any ambiguity, and return 'undefined' if this could be an
2565+ // expression instead.
2566+ var arrowFunction = triState === Tristate . True
2567+ ? parseParenthesizedArrowFunctionExpressionHead ( /*allowAmbiguity:*/ true )
2568+ : tryParse ( parsePossibleParenthesizedArrowFunctionExpressionHead ) ;
25622569
2563- // If we have an arrow, then try to parse the body.
2564- // Even if not, try to parse if we have an opening brace, just in case we're in an error state.
2565- if ( parseExpected ( SyntaxKind . EqualsGreaterThanToken ) || token === SyntaxKind . OpenBraceToken ) {
2566- return parseArrowExpressionTail ( pos , sig ) ;
2567- }
2568- else {
2569- // If not, we're probably better off bailing out and returning a bogus function expression.
2570- return makeFunctionExpression ( SyntaxKind . ArrowFunction , pos , /*asteriskToken:*/ undefined , /*name:*/ undefined , sig , parseIdentifier ( Diagnostics . Expression_expected ) ) ;
2571- }
2570+ if ( ! arrowFunction ) {
2571+ // Didn't appear to actually be a parenthesized arrow function. Just bail out.
2572+ return undefined ;
25722573 }
2573-
2574- // *Maybe* we had an arrow function and we need to try to parse it out,
2575- // rolling back and trying other parses if we fail.
2576- var sig = tryParseSignatureIfArrowOrBraceFollows ( ) ;
2577- if ( sig ) {
2578- parseExpected ( SyntaxKind . EqualsGreaterThanToken ) ;
2579- return parseArrowExpressionTail ( pos , sig ) ;
2574+
2575+ // If we have an arrow, then try to parse the body. Even if not, try to parse if we
2576+ // have an opening brace, just in case we're in an error state.
2577+ if ( parseExpected ( SyntaxKind . EqualsGreaterThanToken ) || token === SyntaxKind . OpenBraceToken ) {
2578+ arrowFunction . body = parseArrowFunctionExpressionBody ( ) ;
25802579 }
25812580 else {
2582- return undefined ;
2581+ // If not, we're probably better off bailing out and returning a bogus function expression.
2582+ arrowFunction . body = parseIdentifier ( ) ;
25832583 }
2584+
2585+ return finishNode ( arrowFunction ) ;
25842586 }
25852587
25862588 // True -> We definitely expect a parenthesized arrow function here.
@@ -2662,34 +2664,37 @@ module ts {
26622664 }
26632665 }
26642666
2665- function tryParseSignatureIfArrowOrBraceFollows ( ) : ParsedSignature {
2666- return tryParse ( ( ) => {
2667- // Arrow functions are never generators.
2668- var sig = parseSignature ( /*yieldAndGeneratorParameterContext:*/ false ) ;
2667+ function parsePossibleParenthesizedArrowFunctionExpressionHead ( ) {
2668+ return parseParenthesizedArrowFunctionExpressionHead ( /*allowAmbiguity:*/ false ) ;
2669+ }
26692670
2670- // Parsing a signature isn't enough.
2671- // Parenthesized arrow signatures often look like other valid expressions.
2672- // For instance:
2673- // - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value.
2674- // - "(x,y)" is a comma expression parsed as a signature with two parameters.
2675- // - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation.
2676- //
2677- // So we need just a bit of lookahead to ensure that it can only be a signature.
2678- if ( token === SyntaxKind . EqualsGreaterThanToken || token === SyntaxKind . OpenBraceToken ) {
2679- return sig ;
2680- }
2671+ function parseParenthesizedArrowFunctionExpressionHead ( allowAmbiguity : boolean ) : FunctionExpression {
2672+ var node = < FunctionExpression > createNode ( SyntaxKind . ArrowFunction ) ;
2673+ // Arrow functions are never generators.
2674+ fillSignature ( SyntaxKind . ColonToken , /*yieldAndGeneratorParameterContext:*/ false , node ) ;
26812675
2676+ // Parsing a signature isn't enough.
2677+ // Parenthesized arrow signatures often look like other valid expressions.
2678+ // For instance:
2679+ // - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value.
2680+ // - "(x,y)" is a comma expression parsed as a signature with two parameters.
2681+ // - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation.
2682+ //
2683+ // So we need just a bit of lookahead to ensure that it can only be a signature.
2684+ if ( ! allowAmbiguity && token !== SyntaxKind . EqualsGreaterThanToken && token !== SyntaxKind . OpenBraceToken ) {
2685+ // Returning undefined here will cause our caller to rewind to where we started from.
26822686 return undefined ;
2683- } ) ;
2684- }
2687+ }
26852688
2686- function parseArrowExpressionTail ( pos : number , sig : ParsedSignature ) : FunctionExpression {
2687- var body : Block | Expression ;
2689+ return node ;
2690+ }
26882691
2692+ function parseArrowFunctionExpressionBody ( ) : Block | Expression {
26892693 if ( token === SyntaxKind . OpenBraceToken ) {
2690- body = parseFunctionBlock ( /*allowYield:*/ false , /* ignoreMissingOpenBrace */ false ) ;
2694+ return parseFunctionBlock ( /*allowYield:*/ false , /* ignoreMissingOpenBrace */ false ) ;
26912695 }
2692- else if ( isStatement ( /* inErrorRecovery */ true ) && ! isStartOfExpressionStatement ( ) && token !== SyntaxKind . FunctionKeyword ) {
2696+
2697+ if ( isStatement ( /* inErrorRecovery */ true ) && ! isStartOfExpressionStatement ( ) && token !== SyntaxKind . FunctionKeyword ) {
26932698 // Check if we got a plain statement (i.e. no expression-statements, no functions expressions/declarations)
26942699 //
26952700 // Here we try to recover from a potential error situation in the case where the
@@ -2704,13 +2709,10 @@ module ts {
27042709 // up preemptively closing the containing construct.
27052710 //
27062711 // Note: even when 'ignoreMissingOpenBrace' is passed as true, parseBody will still error.
2707- body = parseFunctionBlock ( /*allowYield:*/ false , /* ignoreMissingOpenBrace */ true ) ;
2708- }
2709- else {
2710- body = parseAssignmentExpressionOrHigher ( ) ;
2712+ return parseFunctionBlock ( /*allowYield:*/ false , /* ignoreMissingOpenBrace */ true ) ;
27112713 }
27122714
2713- return makeFunctionExpression ( SyntaxKind . ArrowFunction , pos , /*asteriskToken:*/ undefined , /*name:*/ undefined , sig , body ) ;
2715+ return parseAssignmentExpressionOrHigher ( ) ;
27142716 }
27152717
27162718 function parseConditionalExpressionRest ( leftOperand : Expression ) : Expression {
@@ -3233,15 +3235,13 @@ module ts {
32333235 // function * BindingIdentifier[Yield]opt (FormalParameters[Yield, GeneratorParameter]) { GeneratorBody[Yield] }
32343236 // FunctionExpression:
32353237 // function BindingIdentifieropt(FormalParameters) { FunctionBody }
3236-
3237- var pos = getNodePos ( ) ;
3238+ var node = < FunctionExpression > createNode ( SyntaxKind . FunctionExpression ) ;
32383239 parseExpected ( SyntaxKind . FunctionKeyword ) ;
3239- var asteriskToken = parseOptionalToken ( SyntaxKind . AsteriskToken ) ;
3240- var name = asteriskToken ? doInYieldContext ( parseOptionalIdentifier ) : parseOptionalIdentifier ( ) ;
3241- var sig = parseSignature ( /*yieldAndGeneratorParameterContext:*/ ! ! asteriskToken ) ;
3242-
3243- var body = parseFunctionBlock ( /*allowYield:*/ ! ! asteriskToken , /* ignoreMissingOpenBrace */ false ) ;
3244- return makeFunctionExpression ( SyntaxKind . FunctionExpression , pos , asteriskToken , name , sig , body ) ;
3240+ node . asteriskToken = parseOptionalToken ( SyntaxKind . AsteriskToken ) ;
3241+ node . name = node . asteriskToken ? doInYieldContext ( parseOptionalIdentifier ) : parseOptionalIdentifier ( ) ;
3242+ fillSignature ( SyntaxKind . ColonToken , /*yieldAndGeneratorParameterContext:*/ ! ! node . asteriskToken , node ) ;
3243+ node . body = parseFunctionBlock ( /*allowYield:*/ ! ! node . asteriskToken , /* ignoreMissingOpenBrace */ false ) ;
3244+ return finishNode ( node ) ;
32453245 }
32463246
32473247 function parseOptionalIdentifier ( ) {
0 commit comments