Пример #1
0
      //---------------------------------------------------------------------------------------
      // ParseForStatement
      //
      //  ForStatement :
      //    'for' '(' OptionalExpressionNoIn ';' OptionalExpression ';' OptionalExpression ')'
      //    'for' '(' 'var' VariableDeclarationListNoIn ';' OptionalExpression ';' OptionalExpression ')'
      //    'for' '(' LeftHandSideExpression 'in' Expression')'
      //    'for' '(' 'var' Identifier OptionalInitializerNoIn 'in' Expression')'
      //
      //  OptionalExpressionNoIn :
      //    <empty> |
      //    ExpressionNoIn // same as Expression but does not process 'in' as an operator
      //
      //  OptionalInitializerNoIn :
      //    <empty> |
      //    InitializerNoIn // same as initializer but does not process 'in' as an operator
      //---------------------------------------------------------------------------------------
      private AST ParseForStatement(){
        this.blockType.Add(BlockType.Loop);
        AST forNode = null;
        try{
          Context forCtx = this.currentToken.Clone();
          GetNextToken();
          if (JSToken.LeftParen != this.currentToken.token)
            ReportError(JSError.NoLeftParen);
          GetNextToken();
          bool isForIn = false, recoveryInForIn = false;
          AST lhs = null, initializer = null, condOrColl = null, increment = null;

          try{
            if (JSToken.Var == this.currentToken.token){
              isForIn = true;
              initializer = ParseIdentifierInitializer(JSToken.In, (FieldAttributes)0, null, JSToken.Var);

              // a list of variable initializers is allowed only in a for(;;)
              AST var = null;
              while (JSToken.Comma == this.currentToken.token){
                isForIn = false;
                var = ParseIdentifierInitializer(JSToken.In, (FieldAttributes)0, null, JSToken.Var);
                initializer = new Comma(initializer.context.CombineWith(var.context), initializer, var);
              }

              // if it could still be a for..in, now it's time to get the 'in'
              if (isForIn){
                if (JSToken.In == this.currentToken.token){
                  GetNextToken();
                  condOrColl = ParseExpression();
                }else
                  isForIn = false;
              }
            }else{
              if (JSToken.Semicolon != this.currentToken.token){
                bool isLHS;
                initializer = ParseUnaryExpression(out isLHS, false);
                if (isLHS && JSToken.In == this.currentToken.token){
                  isForIn = true;
                  lhs = initializer;
                  initializer = null;
                  GetNextToken();
                  this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                  try{
                    condOrColl = ParseExpression();
                  }catch(RecoveryTokenException exc){
                    if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1){
                      exc._partiallyComputedNode = null;
                      throw exc;
                    }else{
                      if (exc._partiallyComputedNode == null)
                        condOrColl = new ConstantWrapper(true, CurrentPositionContext()); // what could we put here?
                      else
                        condOrColl = exc._partiallyComputedNode;
                    }
                    if (exc._token == JSToken.RightParen){
                      GetNextToken();
                      recoveryInForIn = true;
                    }
                  }finally{
                    this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                  }
                }else
                  initializer = ParseExpression(initializer, false, isLHS, JSToken.In);
              }else
                initializer = new EmptyLiteral(CurrentPositionContext());
          }
          }catch(RecoveryTokenException exc){
            // error is too early abort for
            exc._partiallyComputedNode = null;
            throw exc;
          }

          // at this point we know whether or not is a for..in
          if (isForIn){
            if (!recoveryInForIn){
              if (JSToken.RightParen != this.currentToken.token)
                ReportError(JSError.NoRightParen);
              forCtx.UpdateWith(this.currentToken);
              GetNextToken();
            }
            AST body = null;
            try{
              body = ParseStatement();
            }catch(RecoveryTokenException exc){
              if (exc._partiallyComputedNode == null)
                body = new Block(CurrentPositionContext());
              else
                body = exc._partiallyComputedNode;
              exc._partiallyComputedNode = new ForIn(forCtx, lhs, initializer, condOrColl, body);
              throw exc;
            }
            forNode = new ForIn(forCtx, lhs, initializer, condOrColl, body);
          }else{
            this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
            try{
              if (JSToken.Semicolon != this.currentToken.token){
                ReportError(JSError.NoSemicolon);
                if (JSToken.Colon == this.currentToken.token){
                  this.noSkipTokenSet.Add(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet);
                  try{
                    SkipTokensAndThrow();
                  }catch(RecoveryTokenException exc){
                    if (JSToken.Semicolon == this.currentToken.token)
                      this.errorToken = null;
                    else
                      throw exc;
                  }finally{
                    this.noSkipTokenSet.Remove(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet);
                  }
                }
              }
              GetNextToken();
              if (JSToken.Semicolon != this.currentToken.token){
                condOrColl = ParseExpression();
                if (JSToken.Semicolon != this.currentToken.token)
                  ReportError(JSError.NoSemicolon);
              }else
                condOrColl = new ConstantWrapper(true, CurrentPositionContext());
              GetNextToken();
              if (JSToken.RightParen != this.currentToken.token)
                increment = ParseExpression();
              else
                increment = new EmptyLiteral(CurrentPositionContext());
              if (JSToken.RightParen != this.currentToken.token)
                ReportError(JSError.NoRightParen);
              forCtx.UpdateWith(this.currentToken);
              GetNextToken();
            }catch(RecoveryTokenException exc){
              if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1){
                exc._partiallyComputedNode = null;
                throw exc;
              }else{
                // discard any partial info, just genrate empty condition and increment and keep going
                exc._partiallyComputedNode = null;
                if (condOrColl == null)
                  condOrColl = new ConstantWrapper(true, CurrentPositionContext());
                if (increment == null)
                  increment = new EmptyLiteral(CurrentPositionContext());
              }
              if (exc._token == JSToken.RightParen){
                GetNextToken();
              }
            }finally{
              this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
            }
            AST body = null;
            try{
              body = ParseStatement();
            }catch(RecoveryTokenException exc){
              if (exc._partiallyComputedNode == null)
                body = new Block(CurrentPositionContext());
              else
                body = exc._partiallyComputedNode;
              exc._partiallyComputedNode = new For(forCtx, initializer, condOrColl, increment, body);
              throw exc;
            }
            forNode = new For(forCtx, initializer, condOrColl, increment, body);
          }
        }finally{
          this.blockType.RemoveAt(this.blockType.Count - 1);
        }

        return forNode;
      }
 private AST ParseForStatement()
 {
     this.blockType.Add(BlockType.Loop);
     AST ast = null;
     try
     {
         Context context = this.currentToken.Clone();
         this.GetNextToken();
         if (JSToken.LeftParen != this.currentToken.token)
         {
             this.ReportError(JSError.NoLeftParen);
         }
         this.GetNextToken();
         bool flag = false;
         bool flag2 = false;
         AST var = null;
         AST ast3 = null;
         AST collection = null;
         AST incrementer = null;
         try
         {
             if (JSToken.Var == this.currentToken.token)
             {
                 flag = true;
                 ast3 = this.ParseIdentifierInitializer(JSToken.In, FieldAttributes.PrivateScope, null, JSToken.Var);
                 AST ast6 = null;
                 while (JSToken.Comma == this.currentToken.token)
                 {
                     flag = false;
                     ast6 = this.ParseIdentifierInitializer(JSToken.In, FieldAttributes.PrivateScope, null, JSToken.Var);
                     ast3 = new Comma(ast3.context.CombineWith(ast6.context), ast3, ast6);
                 }
                 if (flag)
                 {
                     if (JSToken.In == this.currentToken.token)
                     {
                         this.GetNextToken();
                         collection = this.ParseExpression();
                     }
                     else
                     {
                         flag = false;
                     }
                 }
             }
             else if (JSToken.Semicolon != this.currentToken.token)
             {
                 bool flag3;
                 ast3 = this.ParseUnaryExpression(out flag3, false);
                 if (flag3 && (JSToken.In == this.currentToken.token))
                 {
                     flag = true;
                     var = ast3;
                     ast3 = null;
                     this.GetNextToken();
                     this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                     try
                     {
                         try
                         {
                             collection = this.ParseExpression();
                         }
                         catch (RecoveryTokenException exception)
                         {
                             if (this.IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exception) == -1)
                             {
                                 exception._partiallyComputedNode = null;
                                 throw exception;
                             }
                             if (exception._partiallyComputedNode == null)
                             {
                                 collection = new ConstantWrapper(true, this.CurrentPositionContext());
                             }
                             else
                             {
                                 collection = exception._partiallyComputedNode;
                             }
                             if (exception._token == JSToken.RightParen)
                             {
                                 this.GetNextToken();
                                 flag2 = true;
                             }
                         }
                         goto Label_01E1;
                     }
                     finally
                     {
                         this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                     }
                 }
                 ast3 = this.ParseExpression(ast3, false, flag3, JSToken.In);
             }
             else
             {
                 ast3 = new EmptyLiteral(this.CurrentPositionContext());
             }
         }
         catch (RecoveryTokenException exception2)
         {
             exception2._partiallyComputedNode = null;
             throw exception2;
         }
     Label_01E1:
         if (flag)
         {
             if (!flag2)
             {
                 if (JSToken.RightParen != this.currentToken.token)
                 {
                     this.ReportError(JSError.NoRightParen);
                 }
                 context.UpdateWith(this.currentToken);
                 this.GetNextToken();
             }
             AST ast7 = null;
             try
             {
                 ast7 = this.ParseStatement();
             }
             catch (RecoveryTokenException exception3)
             {
                 if (exception3._partiallyComputedNode == null)
                 {
                     ast7 = new Block(this.CurrentPositionContext());
                 }
                 else
                 {
                     ast7 = exception3._partiallyComputedNode;
                 }
                 exception3._partiallyComputedNode = new ForIn(context, var, ast3, collection, ast7);
                 throw exception3;
             }
             return new ForIn(context, var, ast3, collection, ast7);
         }
         this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
         try
         {
             if (JSToken.Semicolon != this.currentToken.token)
             {
                 this.ReportError(JSError.NoSemicolon);
                 if (JSToken.Colon == this.currentToken.token)
                 {
                     this.noSkipTokenSet.Add(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet);
                     try
                     {
                         this.SkipTokensAndThrow();
                     }
                     catch (RecoveryTokenException exception4)
                     {
                         if (JSToken.Semicolon != this.currentToken.token)
                         {
                             throw exception4;
                         }
                         this.errorToken = null;
                     }
                     finally
                     {
                         this.noSkipTokenSet.Remove(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet);
                     }
                 }
             }
             this.GetNextToken();
             if (JSToken.Semicolon != this.currentToken.token)
             {
                 collection = this.ParseExpression();
                 if (JSToken.Semicolon != this.currentToken.token)
                 {
                     this.ReportError(JSError.NoSemicolon);
                 }
             }
             else
             {
                 collection = new ConstantWrapper(true, this.CurrentPositionContext());
             }
             this.GetNextToken();
             if (JSToken.RightParen != this.currentToken.token)
             {
                 incrementer = this.ParseExpression();
             }
             else
             {
                 incrementer = new EmptyLiteral(this.CurrentPositionContext());
             }
             if (JSToken.RightParen != this.currentToken.token)
             {
                 this.ReportError(JSError.NoRightParen);
             }
             context.UpdateWith(this.currentToken);
             this.GetNextToken();
         }
         catch (RecoveryTokenException exception5)
         {
             if (this.IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exception5) == -1)
             {
                 exception5._partiallyComputedNode = null;
                 throw exception5;
             }
             exception5._partiallyComputedNode = null;
             if (collection == null)
             {
                 collection = new ConstantWrapper(true, this.CurrentPositionContext());
             }
             if (incrementer == null)
             {
                 incrementer = new EmptyLiteral(this.CurrentPositionContext());
             }
             if (exception5._token == JSToken.RightParen)
             {
                 this.GetNextToken();
             }
         }
         finally
         {
             this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
         }
         AST body = null;
         try
         {
             body = this.ParseStatement();
         }
         catch (RecoveryTokenException exception6)
         {
             if (exception6._partiallyComputedNode == null)
             {
                 body = new Block(this.CurrentPositionContext());
             }
             else
             {
                 body = exception6._partiallyComputedNode;
             }
             exception6._partiallyComputedNode = new For(context, ast3, collection, incrementer, body);
             throw exception6;
         }
         ast = new For(context, ast3, collection, incrementer, body);
     }
     finally
     {
         this.blockType.RemoveAt(this.blockType.Count - 1);
     }
     return ast;
 }