Ejemplo n.º 1
0
      //---------------------------------------------------------------------------------------
      // ParseSwitchStatement
      //
      //  SwitchStatement :
      //    'switch' '(' Expression ')' '{' CaseBlock '}'
      //
      //  CaseBlock :
      //    CaseList DefaultCaseClause CaseList
      //
      //  CaseList :
      //    <empty> |
      //    CaseClause CaseList
      //
      //  CaseClause :
      //    'case' Expression ':' OptionalStatements
      //
      //  DefaultCaseClause :
      //    <empty> |
      //    'default' ':' OptionalStatements
      //---------------------------------------------------------------------------------------
      private AST ParseSwitchStatement(){
        Context switchCtx = this.currentToken.Clone();
        AST expr = null;
        ASTList cases = null;
        this.blockType.Add(BlockType.Switch);
        try{
          // read switch(expr)
        GetNextToken();
        if (JSToken.LeftParen != this.currentToken.token)
            ReportError(JSError.NoLeftParen);
        GetNextToken();
          this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
          this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
          try{
            expr = ParseExpression();

          if (JSToken.RightParen != this.currentToken.token){
              ReportError(JSError.NoRightParen);
            }

          GetNextToken();
          if (JSToken.LeftCurly != this.currentToken.token){
              ReportError(JSError.NoLeftCurly);
            }
            GetNextToken();

          }catch(RecoveryTokenException exc){
            if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1
                  && IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exc) == -1 ){
              // give up
              exc._partiallyComputedNode = null;
              throw exc;
            }else{
              if (exc._partiallyComputedNode == null)
                expr = new ConstantWrapper(true, CurrentPositionContext());
              else
                expr = exc._partiallyComputedNode;

              if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) != -1){
                if (exc._token == JSToken.RightParen)
                  GetNextToken();

                if (JSToken.LeftCurly != this.currentToken.token){
                  ReportError(JSError.NoLeftCurly);
                }
                GetNextToken();
              }

            }
          }finally{
            this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
            this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
          }

          // parse the switch body
          cases = new ASTList(this.currentToken.Clone());
        bool defaultStatement = false;
          this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet);
          try{
            while (JSToken.RightCurly != this.currentToken.token){
              SwitchCase caseClause = null;
              AST caseValue = null;
              Context caseCtx = this.currentToken.Clone();
              this.noSkipTokenSet.Add(NoSkipTokenSet.s_CaseNoSkipTokenSet);
              try{
                if (JSToken.Case == this.currentToken.token){
                  // get the case
                  GetNextToken();
                  caseValue = ParseExpression();
                }else if (JSToken.Default == this.currentToken.token){
                  // get the default
                  if (defaultStatement)
                    // we report an error but we still accept the default
                    ReportError(JSError.DupDefault, true);
                  else
                    defaultStatement = true;
                  GetNextToken();
                }else{
                  // This is an error, there is no case or default. Assume a default was missing and keep going
                  defaultStatement = true;
                  ReportError(JSError.BadSwitch);
                }
                if (JSToken.Colon != this.currentToken.token)
                  ReportError(JSError.NoColon);

                // read the statements inside the case or default
                GetNextToken();
              }catch(RecoveryTokenException exc){
                // right now we can only get here for the 'case' statement
                if (IndexOfToken(NoSkipTokenSet.s_CaseNoSkipTokenSet, exc) == -1){
                  // ignore the current case or default
                  exc._partiallyComputedNode = null;
                  throw exc;
                }else{
                  caseValue = exc._partiallyComputedNode;

                  if (exc._token == JSToken.Colon)
                    GetNextToken();
                }
              }finally{
                this.noSkipTokenSet.Remove(NoSkipTokenSet.s_CaseNoSkipTokenSet);
              }

              this.blockType.Add(BlockType.Block);
              try{
                Block statements = new Block(this.currentToken.Clone());
                this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
                this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
                try{
                  while (JSToken.RightCurly != this.currentToken.token && JSToken.Case != this.currentToken.token && JSToken.Default != this.currentToken.token){
                    try{
                      statements.Append(ParseStatement());
                    }catch(RecoveryTokenException exc){
                      if (exc._partiallyComputedNode != null){
                        statements.Append(exc._partiallyComputedNode);
                        exc._partiallyComputedNode = null;
                      }
                      if (IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exc) == -1)
                        throw exc;
                    }
                  }
                }catch(RecoveryTokenException exc){
                  if (IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exc) == -1){
                    if (null == caseValue)
                      caseClause = new SwitchCase(caseCtx, statements);
                    else
                      caseClause = new SwitchCase(caseCtx, caseValue, statements);
                    cases.Append(caseClause);

                    throw exc;
                  }
                }finally{
                  this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
                  this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
                }
                if (JSToken.RightCurly == this.currentToken.token)
                  statements.context.UpdateWith(this.currentToken);
                if (null == caseValue){
                  caseCtx.UpdateWith(statements.context);
                  caseClause = new SwitchCase(caseCtx, statements);
                }else{
                  caseCtx.UpdateWith(statements.context);
                  caseClause = new SwitchCase(caseCtx, caseValue, statements);
                }
                cases.Append(caseClause);
              }finally{
                this.blockType.RemoveAt(this.blockType.Count - 1);
              }
            }
          }catch(RecoveryTokenException exc){
            if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){
              //save what you can a rethrow
              switchCtx.UpdateWith(CurrentPositionContext());
              exc._partiallyComputedNode = new Switch(switchCtx, expr, cases);
              throw exc;
            }
          }finally{
            this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet);
          }
          switchCtx.UpdateWith(this.currentToken);
          GetNextToken();
        }finally{
          this.blockType.RemoveAt(this.blockType.Count - 1);
        }

        return new Switch(switchCtx, expr, cases);
      }
 private AST ParseSwitchStatement()
 {
     Context context = this.currentToken.Clone();
     AST expression = null;
     ASTList cases = null;
     this.blockType.Add(BlockType.Switch);
     try
     {
         this.GetNextToken();
         if (JSToken.LeftParen != this.currentToken.token)
         {
             this.ReportError(JSError.NoLeftParen);
         }
         this.GetNextToken();
         this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
         this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
         try
         {
             expression = this.ParseExpression();
             if (JSToken.RightParen != this.currentToken.token)
             {
                 this.ReportError(JSError.NoRightParen);
             }
             this.GetNextToken();
             if (JSToken.LeftCurly != this.currentToken.token)
             {
                 this.ReportError(JSError.NoLeftCurly);
             }
             this.GetNextToken();
         }
         catch (RecoveryTokenException exception)
         {
             if ((this.IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exception) == -1) && (this.IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exception) == -1))
             {
                 exception._partiallyComputedNode = null;
                 throw exception;
             }
             if (exception._partiallyComputedNode == null)
             {
                 expression = new ConstantWrapper(true, this.CurrentPositionContext());
             }
             else
             {
                 expression = exception._partiallyComputedNode;
             }
             if (this.IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exception) != -1)
             {
                 if (exception._token == JSToken.RightParen)
                 {
                     this.GetNextToken();
                 }
                 if (JSToken.LeftCurly != this.currentToken.token)
                 {
                     this.ReportError(JSError.NoLeftCurly);
                 }
                 this.GetNextToken();
             }
         }
         finally
         {
             this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
             this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
         }
         cases = new ASTList(this.currentToken.Clone());
         bool flag = false;
         this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet);
         try
         {
             while (JSToken.RightCurly != this.currentToken.token)
             {
                 SwitchCase elem = null;
                 AST ast2 = null;
                 Context context2 = this.currentToken.Clone();
                 this.noSkipTokenSet.Add(NoSkipTokenSet.s_CaseNoSkipTokenSet);
                 try
                 {
                     if (JSToken.Case == this.currentToken.token)
                     {
                         this.GetNextToken();
                         ast2 = this.ParseExpression();
                     }
                     else if (JSToken.Default == this.currentToken.token)
                     {
                         if (flag)
                         {
                             this.ReportError(JSError.DupDefault, true);
                         }
                         else
                         {
                             flag = true;
                         }
                         this.GetNextToken();
                     }
                     else
                     {
                         flag = true;
                         this.ReportError(JSError.BadSwitch);
                     }
                     if (JSToken.Colon != this.currentToken.token)
                     {
                         this.ReportError(JSError.NoColon);
                     }
                     this.GetNextToken();
                 }
                 catch (RecoveryTokenException exception2)
                 {
                     if (this.IndexOfToken(NoSkipTokenSet.s_CaseNoSkipTokenSet, exception2) == -1)
                     {
                         exception2._partiallyComputedNode = null;
                         throw exception2;
                     }
                     ast2 = exception2._partiallyComputedNode;
                     if (exception2._token == JSToken.Colon)
                     {
                         this.GetNextToken();
                     }
                 }
                 finally
                 {
                     this.noSkipTokenSet.Remove(NoSkipTokenSet.s_CaseNoSkipTokenSet);
                 }
                 this.blockType.Add(BlockType.Block);
                 try
                 {
                     Block statements = new Block(this.currentToken.Clone());
                     this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
                     this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
                     try
                     {
                         while (((JSToken.RightCurly != this.currentToken.token) && (JSToken.Case != this.currentToken.token)) && (JSToken.Default != this.currentToken.token))
                         {
                             try
                             {
                                 statements.Append(this.ParseStatement());
                                 continue;
                             }
                             catch (RecoveryTokenException exception3)
                             {
                                 if (exception3._partiallyComputedNode != null)
                                 {
                                     statements.Append(exception3._partiallyComputedNode);
                                     exception3._partiallyComputedNode = null;
                                 }
                                 if (this.IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exception3) == -1)
                                 {
                                     throw exception3;
                                 }
                                 continue;
                             }
                         }
                     }
                     catch (RecoveryTokenException exception4)
                     {
                         if (this.IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exception4) == -1)
                         {
                             if (ast2 == null)
                             {
                                 elem = new SwitchCase(context2, statements);
                             }
                             else
                             {
                                 elem = new SwitchCase(context2, ast2, statements);
                             }
                             cases.Append(elem);
                             throw exception4;
                         }
                     }
                     finally
                     {
                         this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
                         this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
                     }
                     if (JSToken.RightCurly == this.currentToken.token)
                     {
                         statements.context.UpdateWith(this.currentToken);
                     }
                     if (ast2 == null)
                     {
                         context2.UpdateWith(statements.context);
                         elem = new SwitchCase(context2, statements);
                     }
                     else
                     {
                         context2.UpdateWith(statements.context);
                         elem = new SwitchCase(context2, ast2, statements);
                     }
                     cases.Append(elem);
                     continue;
                 }
                 finally
                 {
                     this.blockType.RemoveAt(this.blockType.Count - 1);
                 }
             }
         }
         catch (RecoveryTokenException exception5)
         {
             if (this.IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exception5) == -1)
             {
                 context.UpdateWith(this.CurrentPositionContext());
                 exception5._partiallyComputedNode = new Switch(context, expression, cases);
                 throw exception5;
             }
         }
         finally
         {
             this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet);
         }
         context.UpdateWith(this.currentToken);
         this.GetNextToken();
     }
     finally
     {
         this.blockType.RemoveAt(this.blockType.Count - 1);
     }
     return new Switch(context, expression, cases);
 }