@@ -1710,61 +1710,46 @@ module TypeScript.Parser {
17101710
17111711 var _currentToken = currentToken ( ) ;
17121712 var tokenKind = _currentToken . kind ;
1713- if ( tokenKind === SyntaxKind . VarKeyword ) {
1714- // for ( var VariableDeclarationListNoIn; Expressionopt ; Expressionopt ) Statement
1713+
1714+ // If we see 'for ( ;' then there is no initializer, and this must be a 'for' statement.
1715+ // If we don't see a semicolon, then parse our a variable declaration or an initializer
1716+ // expression. Both could be hte start of a 'for' or 'for-in' statement. So, after that
1717+ // check to see if we have an 'in' keyword to make the final determination as to what we
1718+ // have.
1719+
1720+ // When trying to parse either a variable declaration or an expression do not allow 'in'
1721+ // to be parsed, as that will actually be consumed by the 'for in' statement production
1722+ // instead. Also, we allow any expression here (even though the grammar only allows for
1723+ // LeftHandSideExpression). We will make sure we actually have a LHS expression in the
1724+ // grammar walker.
1725+ var initializer = tokenKind === SyntaxKind . SemicolonToken
1726+ ? undefined
1727+ : tokenKind === SyntaxKind . VarKeyword
1728+ ? parseVariableDeclaration ( /*allowIn:*/ false )
1729+ : parseExpression ( /*allowIn:*/ false ) ;
1730+
1731+ // In order to be a 'for-in' statement, we had to have an initializer of some sort, and
1732+ // we had to actually get an 'in' keyword.
1733+ if ( initializer !== undefined && currentToken ( ) . kind === SyntaxKind . InKeyword ) {
17151734 // for ( var VariableDeclarationNoIn in Expression ) Statement
1716- return parseForOrForInStatementWithVariableDeclaration ( forKeyword , openParenToken ) ;
1717- }
1718- else if ( tokenKind === SyntaxKind . SemicolonToken ) {
1719- // for ( ; Expressionopt ; Expressionopt ) Statement
1720- return parseForStatementWithNoVariableDeclarationOrInitializer ( forKeyword , openParenToken ) ;
1721- }
1722- else {
1723- // for ( ExpressionNoInopt; Expressionopt ; Expressionopt ) Statement
17241735 // for ( LeftHandSideExpression in Expression ) Statement
1725- return parseForOrForInStatementWithInitializer ( forKeyword , openParenToken ) ;
1736+ return new ForInStatementSyntax ( parseNodeData ,
1737+ forKeyword , openParenToken , initializer , eatToken ( SyntaxKind . InKeyword ) ,
1738+ parseExpression ( /*allowIn:*/ true ) , eatToken ( SyntaxKind . CloseParenToken ) , parseStatement ( /*inErrorRecovery:*/ false ) ) ;
17261739 }
1727- }
1728-
1729- function parseForOrForInStatementWithVariableDeclaration ( forKeyword : ISyntaxToken , openParenToken : ISyntaxToken ) : IStatementSyntax {
1730- // Debug.assert(forKeyword.kind === SyntaxKind.ForKeyword && openParenToken.kind === SyntaxKind.OpenParenToken);
1731- // Debug.assert(currentToken().kind === SyntaxKind.VarKeyword);
1732-
1733- // for ( var VariableDeclarationListNoIn; Expressionopt ; Expressionopt ) Statement
1734- // for ( var VariableDeclarationNoIn in Expression ) Statement
1735-
1736- var variableDeclaration = parseVariableDeclaration ( /*allowIn:*/ false ) ;
1737- return currentToken ( ) . kind === SyntaxKind . InKeyword
1738- ? parseForInStatementWithVariableDeclarationOrInitializer ( forKeyword , openParenToken , variableDeclaration , undefined )
1739- : parseForStatementWithVariableDeclarationOrInitializer ( forKeyword , openParenToken , variableDeclaration , undefined ) ;
1740- }
1741-
1742- function parseForInStatementWithVariableDeclarationOrInitializer ( forKeyword : ISyntaxToken , openParenToken : ISyntaxToken , variableDeclaration : VariableDeclarationSyntax , initializer : IExpressionSyntax ) : ForInStatementSyntax {
1743- // for ( var VariableDeclarationNoIn in Expression ) Statement
1744-
1745- return new ForInStatementSyntax ( parseNodeData ,
1746- forKeyword , openParenToken , variableDeclaration , initializer , eatToken ( SyntaxKind . InKeyword ) ,
1747- parseExpression ( /*allowIn:*/ true ) , eatToken ( SyntaxKind . CloseParenToken ) , parseStatement ( /*inErrorRecovery:*/ false ) ) ;
1748- }
1749-
1750- function parseForOrForInStatementWithInitializer ( forKeyword : ISyntaxToken , openParenToken : ISyntaxToken ) : IStatementSyntax {
1751- // Debug.assert(forKeyword.kind === SyntaxKind.ForKeyword && openParenToken.kind === SyntaxKind.OpenParenToken);
1752-
1753- // for ( ExpressionNoInopt; Expressionopt ; Expressionopt ) Statement
1754- // for ( LeftHandSideExpression in Expression ) Statement
1755-
1756- var initializer = parseExpression ( /*allowIn:*/ false ) ;
1757- return currentToken ( ) . kind === SyntaxKind . InKeyword
1758- ? parseForInStatementWithVariableDeclarationOrInitializer ( forKeyword , openParenToken , undefined , initializer )
1759- : parseForStatementWithVariableDeclarationOrInitializer ( forKeyword , openParenToken , undefined , initializer ) ;
1760- }
1761-
1762- function parseForStatementWithNoVariableDeclarationOrInitializer ( forKeyword : ISyntaxToken , openParenToken : ISyntaxToken ) : ForStatementSyntax {
1763- // Debug.assert(forKeyword.kind === SyntaxKind.ForKeyword && openParenToken.kind === SyntaxKind.OpenParenToken);
1764- // Debug.assert(currentToken().kind === SyntaxKind.SemicolonToken);
1765- // for ( ; Expressionopt ; Expressionopt ) Statement
1740+ else {
1741+ // NOTE: From the es5 section on Automatic Semicolon Insertion.
1742+ // a semicolon is never inserted automatically if the semicolon would then ... become
1743+ // one of the two semicolons in the header of a for statement
17661744
1767- return parseForStatementWithVariableDeclarationOrInitializer ( forKeyword , openParenToken , /*variableDeclaration:*/ undefined , /*initializer:*/ undefined ) ;
1745+ // for (ExpressionNoInopt; Expressionopt ; Expressionopt ) Statement
1746+ // for (var VariableDeclarationListNoIn; Expressionopt; Expressionopt) Statement
1747+ return new ForStatementSyntax ( parseNodeData ,
1748+ forKeyword , openParenToken , initializer ,
1749+ eatToken ( SyntaxKind . SemicolonToken ) , tryParseForStatementCondition ( ) ,
1750+ eatToken ( SyntaxKind . SemicolonToken ) , tryParseForStatementIncrementor ( ) ,
1751+ eatToken ( SyntaxKind . CloseParenToken ) , parseStatement ( /*inErrorRecovery:*/ false ) ) ;
1752+ }
17681753 }
17691754
17701755 function tryParseForStatementCondition ( ) : IExpressionSyntax {
@@ -1788,18 +1773,6 @@ module TypeScript.Parser {
17881773 return undefined ;
17891774 }
17901775
1791- function parseForStatementWithVariableDeclarationOrInitializer ( forKeyword : ISyntaxToken , openParenToken : ISyntaxToken , variableDeclaration : VariableDeclarationSyntax , initializer : IExpressionSyntax ) : ForStatementSyntax {
1792- // NOTE: From the es5 section on Automatic Semicolon Insertion.
1793- // a semicolon is never inserted automatically if the semicolon would then ... become
1794- // one of the two semicolons in the header of a for statement
1795-
1796- return new ForStatementSyntax ( parseNodeData ,
1797- forKeyword , openParenToken , variableDeclaration , initializer ,
1798- eatToken ( SyntaxKind . SemicolonToken ) , tryParseForStatementCondition ( ) ,
1799- eatToken ( SyntaxKind . SemicolonToken ) , tryParseForStatementIncrementor ( ) ,
1800- eatToken ( SyntaxKind . CloseParenToken ) , parseStatement ( /*inErrorRecovery:*/ false ) ) ;
1801- }
1802-
18031776 function tryEatBreakOrContinueLabel ( ) : ISyntaxToken {
18041777 // If there is no newline after the break keyword, then we can consume an optional
18051778 // identifier.
0 commit comments