Пример #1
0
      //---------------------------------------------------------------------------------------
      // ParseTryStatement
      //
      //  TryStatement :
      //    'try' Block CatchList Finally
      //
      //  CatchList :
      //    <empty> |
      //    CatchList Catch
      //
      //  Catch :
      //    'catch' '(' Identifier Type ')' Block
      //
      //  Finally :
      //    <empty> |
      //    'finally' Block
      //---------------------------------------------------------------------------------------
      private AST ParseTryStatement(){
        Context tryCtx = this.currentToken.Clone();
        Context tryEndContext = null;
        AST body = null;
        AST id = null;
        AST handler = null;
        AST finally_block = null;
        RecoveryTokenException excInFinally = null;
        TypeExpression type = null;
        this.blockType.Add(BlockType.Block);
        try{
          bool catchOrFinally = false;
          bool foundCatchAll = false;
          GetNextToken();
          if (JSToken.LeftCurly != this.currentToken.token)
            ReportError(JSError.NoLeftCurly);
          this.noSkipTokenSet.Add(NoSkipTokenSet.s_NoTrySkipTokenSet);
          try{
            body = ParseBlock(out tryEndContext);
          }catch(RecoveryTokenException exc){
            if (IndexOfToken(NoSkipTokenSet.s_NoTrySkipTokenSet, exc) == -1)
              // do nothing and just return the containing block, if any
              throw exc;
            else
              body = exc._partiallyComputedNode;
          }finally{
            this.noSkipTokenSet.Remove(NoSkipTokenSet.s_NoTrySkipTokenSet);
          }
          while (JSToken.Catch == this.currentToken.token){
            this.noSkipTokenSet.Add(NoSkipTokenSet.s_NoTrySkipTokenSet);
            try{
              if (handler != null){
                body = new Try(tryCtx, body, id, type, handler, null, false, tryEndContext);
                id = null;
                type = null;
                handler = null;
              }
              catchOrFinally = true;
              GetNextToken();
              if (JSToken.LeftParen != this.currentToken.token)
                ReportError(JSError.NoLeftParen);
              GetNextToken();
              if (JSToken.Identifier != this.currentToken.token){
                string identifier = JSKeyword.CanBeIdentifier(this.currentToken.token);
                if (null != identifier){
                  ForceReportInfo(JSError.KeywordUsedAsIdentifier);
                  id = new Lookup(identifier, this.currentToken.Clone());
                }else{
                  ReportError(JSError.NoIdentifier);
                  id = new Lookup("##Exc##" + s_cDummyName++, CurrentPositionContext());
                }
              }else
                id = new Lookup(this.scanner.GetIdentifier(), this.currentToken.Clone());
              GetNextToken();
              this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
              try{
                if (JSToken.Colon == this.currentToken.token)
                  type = ParseTypeExpression();
                else{
                  if (foundCatchAll) //no point in having another
                    ForceReportInfo(id.context, JSError.UnreachableCatch);
                  foundCatchAll = true;
                }
                if (JSToken.RightParen != this.currentToken.token)
                  ReportError(JSError.NoRightParen);
                GetNextToken();
              }catch(RecoveryTokenException exc){
                if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1){
                  exc._partiallyComputedNode = null;
                  // rethrow
                  throw exc;
                }else{
                  type = (TypeExpression)exc._partiallyComputedNode;
                  if (this.currentToken.token == JSToken.RightParen)
                    GetNextToken();
                }
              }finally{
                this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
              }
              if (JSToken.LeftCurly != this.currentToken.token)
                ReportError(JSError.NoLeftCurly);
              handler = ParseBlock();
              tryCtx.UpdateWith(handler.context);
            }catch(RecoveryTokenException exc){
              if (exc._partiallyComputedNode == null)
                handler = new Block(CurrentPositionContext());
              else
                handler = exc._partiallyComputedNode;
              if (IndexOfToken(NoSkipTokenSet.s_NoTrySkipTokenSet, exc) == -1){
                Debug.Assert((type == null) ? exc._partiallyComputedNode == null : true);
                if (type != null)
                  exc._partiallyComputedNode = new Try(tryCtx, body, id, type, handler, null, false, tryEndContext);
                throw exc;
              }
            }finally{
              this.noSkipTokenSet.Remove(NoSkipTokenSet.s_NoTrySkipTokenSet);
            }
          }

          try{
            if (JSToken.Finally == this.currentToken.token){
              GetNextToken();
              this.blockType.Add(BlockType.Finally);
              try{
                finally_block = ParseBlock();
                catchOrFinally = true;
              }finally{
                this.blockType.RemoveAt(this.blockType.Count - 1);
              }
              tryCtx.UpdateWith(finally_block.context);
            }
          }catch(RecoveryTokenException exc){
            excInFinally = exc; // thrown later so we can execute code below
          }

          if (!catchOrFinally){
            ReportError(JSError.NoCatch, true);
            finally_block = new Block(CurrentPositionContext()); // make a dummy empty block
          }
        }finally{
          this.blockType.RemoveAt(this.blockType.Count - 1);
        }

        bool isFinallyEscaped = false;
        if (this.finallyEscaped > 0){
          this.finallyEscaped--;
          isFinallyEscaped = true;
        }
        if (excInFinally != null){
          excInFinally._partiallyComputedNode = new Try(tryCtx, body, id, type, handler, finally_block, isFinallyEscaped, tryEndContext);
          throw excInFinally;
        }else
          return new Try(tryCtx, body, id, type, handler, finally_block, isFinallyEscaped, tryEndContext);
      }
Пример #2
0
        /**
         * Whether the "catch (e: e instanceof Exception) { ... }" syntax
         * is implemented.
         */
        AST StatementHelper(AST parent)
        {
            AST pn = null;

            // If skipsemi == true, don't add SEMI + EOL to source at the
            // end of this statment.  For compound statements, IF/FOR etc.
            bool skip_semi = false;

            int tt;
            tt = ts.GetToken ();

            if (tt == Token.IF) {
                skip_semi = true;
                decompiler.AddToken (Token.IF);
                AST cond = Condition (parent);

                decompiler.AddEOL (Token.LC);

                AST if_true = Statement (parent);
                AST if_false = null;

                if (ts.MatchToken (Token.ELSE)) {
                    decompiler.AddToken (Token.RC);
                    decompiler.AddToken (Token.ELSE);
                    decompiler.AddEOL (Token.LC);
                    if_false = Statement (parent);
                }
                decompiler.AddEOL (Token.RC);
                pn = new If (parent, cond, if_true, if_false, new Location (ts.SourceName, ts.LineNumber));
            } else if (tt == Token.SWITCH) {
                skip_semi = true;

                decompiler.AddToken (Token.SWITCH);

                pn = new Switch (parent, new Location (ts.SourceName, ts.LineNumber));
                Clause cur_case;
                MustMatchToken (Token.LP, "msg.no.paren.switch");

                decompiler.AddToken (Token.LP);

                ((Switch) pn).exp = Expr (parent, false);
                MustMatchToken (Token.RP, "msg.no.paren.after.switch");

                decompiler.AddToken (Token.RP);

                MustMatchToken (Token.LC, "msg.no.brace.switch");

                decompiler.AddEOL (Token.LC);

                ClauseType clause_type = ClauseType.Case;

                while ((tt = ts.GetToken ()) != Token.RC && tt != Token.EOF) {
                    if (tt == Token.CASE) {
                        decompiler.AddToken (Token.CASE);
                        cur_case = new Clause (pn, new Location (ts.SourceName, ts.LineNumber));
                        cur_case.exp = Expr (pn, false);
                        decompiler.AddEOL (Token.COLON);
                        if (clause_type == ClauseType.Default)
                            clause_type = ClauseType.CaseAfterDefault;
                    } else if (tt == Token.DEFAULT) {
                        cur_case = null;
                        clause_type = ClauseType.Default;
                        decompiler.AddToken (Token.DEFAULT);
                        decompiler.AddEOL (Token.COLON);
                    } else {
                        cur_case = null;
                        ReportError ("msg.bad.switch");
                    }
                    MustMatchToken (Token.COLON, "msg.no.colon.case");

                    while ((tt = ts.PeekToken ()) != Token.RC && tt != Token.CASE && tt != Token.DEFAULT && tt != Token.EOF) {
                        if (clause_type == ClauseType.Case || clause_type == ClauseType.CaseAfterDefault)
                            cur_case.AddStm (Statement (pn));
                        else if (clause_type == ClauseType.Default)
                            ((Switch) pn).default_clauses.Add (Statement (pn));
                    }
                    ((Switch) pn).AddClause (cur_case, clause_type);
                }
                decompiler.AddEOL (Token.RC);
            } else if (tt == Token.WHILE) {
                skip_semi = true;
                decompiler.AddToken (Token.WHILE);
                While w = new While (new Location (ts.SourceName, ts.LineNumber));
                AST cond = Condition (w);
                decompiler.AddEOL (Token.LC);
                AST body = Statement (w);
                decompiler.AddEOL (Token.RC);
                w.Init (parent, cond, body);
                pn = w;
            } else if (tt == Token.DO) {
                decompiler.AddToken (Token.DO);
                decompiler.AddEOL (Token.LC);
                int line_number = ts.LineNumber;
                DoWhile do_while = new DoWhile (new Location (ts.SourceName, line_number));
                AST body = Statement (do_while);
                decompiler.AddToken (Token.RC);
                MustMatchToken (Token.WHILE, "msg.no.while.do");
                decompiler.AddToken (Token.WHILE);
                AST cond = Condition (do_while);
                do_while.Init (parent, body, cond);
                pn  = do_while;
            } else if (tt == Token.FOR) {
                skip_semi = true;
                decompiler.AddToken (Token.FOR);
                AST init, cond, incr = null, body;

                MustMatchToken (Token.LP, "msg.no.paren.for");
                decompiler.AddToken (Token.LP);
                tt = ts.PeekToken ();

                if (tt == Token.SEMI)
                    init = new EmptyAST ();
                else {
                    if (tt == Token.VAR) {
                        // set init to a var list or initial
                        ts.GetToken (); // throw away the 'var' token
                        init = Variables (parent, true);
                    } else
                        init = Expr (parent, true);
                }

                if (ts.MatchToken (Token.IN)) {
                    decompiler.AddToken (Token.IN);
                    cond = Expr (parent, false); // 'cond' is the object over which we're iterating
                } else {
                    // ordinary for loop
                    MustMatchToken (Token.SEMI, "msg.no.semi.for");
                    decompiler.AddToken (Token.SEMI);

                    if (ts.PeekToken () == Token.SEMI)
                        cond = new EmptyAST (); // no loop condition
                    else
                        cond = Expr (parent, false);

                    MustMatchToken (Token.SEMI, "msg.no.semi.for.cond");
                    decompiler.AddToken (Token.SEMI);

                    if (ts.PeekToken () == Token.RP)
                        incr = new EmptyAST ();
                    else
                        incr = Expr (parent, false);
                }

                MustMatchToken (Token.RP, "msg.no.paren.for.ctrl");
                decompiler.AddToken (Token.RP);
                decompiler.AddEOL (Token.LC);
                body = Statement (pn);
                decompiler.AddEOL (Token.RC);

                if (incr == null) // cond could be null if 'in obj' got eaten by the init node.
                    pn = new ForIn (parent, init, cond, body, new Location (ts.SourceName, ts.LineNumber));
                else
                    pn = new For (parent, init, cond, incr, body, new Location (ts.SourceName, ts.LineNumber));
                body.PropagateParent (pn);
            } else if (tt == Token.TRY) {
                int line_number = ts.LineNumber;
                AST try_block;
                ArrayList catch_blocks = null;
                AST finally_block = null;

                skip_semi = true;
                decompiler.AddToken (Token.TRY);
                decompiler.AddEOL (Token.LC);

                try_block = Statement (parent);
                decompiler.AddEOL (Token.RC);
                catch_blocks = new ArrayList ();

                bool saw_default_catch = false;
                int peek = ts.PeekToken ();

                if (peek == Token.CATCH) {
                    while (ts.MatchToken (Token.CATCH)) {
                        if (saw_default_catch)
                            ReportError ("msg.catch.unreachable");
                        decompiler.AddToken (Token.CATCH);
                        MustMatchToken (Token.LP, "msg.no.paren.catch");
                        decompiler.AddToken (Token.LP);
                        MustMatchToken (Token.NAME, "msg.bad.catchcond");
                        string var_name = ts.GetString;
                        decompiler.AddName (var_name);
                        AST catch_cond = null;

                        if (ts.MatchToken (Token.IF)) {
                            decompiler.AddToken (Token.IF);
                            catch_cond = Expr (parent, false);
                        } else
                            saw_default_catch = true;

                        MustMatchToken (Token.RP, "msg.bad.catchcond");
                        decompiler.AddToken (Token.RP);
                        MustMatchToken (Token.LC, "msg.no.brace.catchblock");
                        decompiler.AddEOL (Token.LC);

                        catch_blocks.Add (new Catch (var_name, catch_cond,
                                         Statements (null), parent, new Location (ts.SourceName, line_number)));
                        MustMatchToken (Token.RC, "msg.no.brace.after.body");
                        decompiler.AddEOL (Token.RC);
                    }
                } else if (peek != Token.FINALLY)
                    MustMatchToken (Token.FINALLY, "msg.try.no.catchfinally");

                if (ts.MatchToken (Token.FINALLY)) {
                    decompiler.AddToken (Token.FINALLY);
                    decompiler.AddEOL (Token.LC);
                    finally_block = Statement (parent);
                    decompiler.AddEOL (Token.RC);
                }
                pn = new Try (try_block, catch_blocks, finally_block, parent, new Location (ts.SourceName, ts.LineNumber));
            } else if (tt == Token.THROW) {
                int line_number = ts.LineNumber;
                decompiler.AddToken (Token.THROW);
                pn = new Throw (Expr (parent, false), new Location (ts.SourceName, ts.LineNumber));

                if (line_number == ts.LineNumber)
                    CheckWellTerminated ();
            } else if (tt == Token.BREAK) {
                decompiler.AddToken (Token.BREAK);

                // MatchLabel only matches if there is one
                string label = MatchLabel ();

                if (label != null)
                    decompiler.AddName (label);

                pn = new Break (parent, label, new Location (ts.SourceName, ts.LineNumber));
            } else if (tt == Token.CONTINUE) {
                decompiler.AddToken (Token.CONTINUE);

                // MatchLabel only matches if there is one
                string label = MatchLabel ();

                if (label != null)
                    decompiler.AddName (label);

                pn = new Continue (parent, label, new Location (ts.SourceName, ts.LineNumber));
            } else if (tt == Token.WITH) {
                skip_semi = true;
                decompiler.AddToken (Token.WITH);
                MustMatchToken (Token.LP, "msg.no.paren.with");
                decompiler.AddToken (Token.LP);
                AST obj = Expr (parent, false);
                MustMatchToken (Token.RP, "msg.no.paren.after.with");
                decompiler.AddToken (Token.RP);
                decompiler.AddToken (Token.LC);
                ++nesting_of_with;
                AST body;
                try {
                    body = Statement (parent);
                } finally {
                    --nesting_of_with;
                }
                decompiler.AddEOL (Token.RC);
                pn = new With (parent, obj, body, new Location (ts.SourceName, ts.LineNumber));
            } else if (tt == Token.VAR) {
                int line_number = ts.LineNumber;
                pn = Variables (parent, false);
                if (ts.LineNumber == line_number)
                    CheckWellTerminated ();
            } else if (tt == Token.RETURN) {
                AST ret_expr = null;
                decompiler.AddToken (Token.RETURN);
                pn = new Return (new Location (ts.SourceName, ts.LineNumber));

                if (!InsideFunction)
                    ReportError ("msg.bad.return");

                /* This is ugly, but we don't want to require a semicolon. */
                ts.allow_reg_exp = true;
                tt = ts.PeekTokenSameLine ();
                ts.allow_reg_exp = false;

                int line_number = ts.LineNumber;
                if (tt != Token.EOF && tt != Token.EOL && tt != Token.SEMI && tt != Token.RC) {
                    ret_expr = Expr (pn, false);
                    if (ts.LineNumber == line_number)
                        CheckWellTerminated ();
                }
                ((Return) pn).Init (parent, ret_expr);
            } else if (tt == Token.LC) {
                skip_semi = true;
                pn = Statements (parent);
                MustMatchToken (Token.RC, "msg.no.brace.block");
            } else if (tt == Token.ERROR || tt == Token.EOL || tt == Token.SEMI) {
             				pn = new EmptyAST ();
                skip_semi = true;
            } else if (tt == Token.FUNCTION) {
                pn = Function (parent, FunctionType.ExpressionStatement);
            } else if (tt == Token.IMPORT) {
                decompiler.AddToken (Token.IMPORT);
                pn = Import (parent);
            } else {
                int last_expr_type = tt;
                int token_number = ts.TokenNumber;
                ts.UnGetToken (tt);
                int line_number = ts.LineNumber;

                pn = Expr (parent, false);

                if (ts.PeekToken () == Token.COLON) {
                    /* check that the last thing the tokenizer returned was a
                     * NAME and that only one token was consumed.
                     */
                    if (last_expr_type != Token.NAME || (ts.TokenNumber != token_number))
                        ReportError ("msg.bad.label");

                    ts.GetToken (); // eat the colon

                    string name = ts.GetString;

                    // bind 'Statement (pn)' to the label
                    Labelled labelled = new Labelled (parent, new Location (ts.SourceName, ts.LineNumber));
                    labelled.Init (parent, name, Statement (labelled), new Location (ts.SourceName, ts.LineNumber));
                    pn = labelled;
                    // depend on decompiling lookahead to guess that that
                    // last name was a label.
                    decompiler.AddEOL (Token.COLON);
                    return pn;
                }
                // FIXME:
                // pn = nf.createExprStatement(pn, lineno);
                if (ts.LineNumber == line_number)
                    CheckWellTerminated ();
            }
            ts.MatchToken (Token.SEMI);

            if (!skip_semi)
                decompiler.AddEOL (Token.SEMI);

            return pn;
        }
 private AST ParseTryStatement()
 {
     Context context = this.currentToken.Clone();
     Context closingBraceContext = null;
     AST body = null;
     AST identifier = null;
     AST handler = null;
     AST ast4 = null;
     RecoveryTokenException exception = null;
     TypeExpression type = null;
     this.blockType.Add(BlockType.Block);
     try
     {
         bool flag = false;
         bool flag2 = false;
         this.GetNextToken();
         if (JSToken.LeftCurly != this.currentToken.token)
         {
             this.ReportError(JSError.NoLeftCurly);
         }
         this.noSkipTokenSet.Add(NoSkipTokenSet.s_NoTrySkipTokenSet);
         try
         {
             try
             {
                 body = this.ParseBlock(out closingBraceContext);
             }
             catch (RecoveryTokenException exception2)
             {
                 if (this.IndexOfToken(NoSkipTokenSet.s_NoTrySkipTokenSet, exception2) == -1)
                 {
                     throw exception2;
                 }
                 body = exception2._partiallyComputedNode;
             }
             goto Label_02E5;
         }
         finally
         {
             this.noSkipTokenSet.Remove(NoSkipTokenSet.s_NoTrySkipTokenSet);
         }
     Label_00A6:
         this.noSkipTokenSet.Add(NoSkipTokenSet.s_NoTrySkipTokenSet);
         try
         {
             if (handler != null)
             {
                 body = new Try(context, body, identifier, type, handler, null, false, closingBraceContext);
                 identifier = null;
                 type = null;
                 handler = null;
             }
             flag = true;
             this.GetNextToken();
             if (JSToken.LeftParen != this.currentToken.token)
             {
                 this.ReportError(JSError.NoLeftParen);
             }
             this.GetNextToken();
             if (JSToken.Identifier != this.currentToken.token)
             {
                 string name = JSKeyword.CanBeIdentifier(this.currentToken.token);
                 if (name != null)
                 {
                     this.ForceReportInfo(JSError.KeywordUsedAsIdentifier);
                     identifier = new Lookup(name, this.currentToken.Clone());
                 }
                 else
                 {
                     this.ReportError(JSError.NoIdentifier);
                     identifier = new Lookup("##Exc##" + s_cDummyName++, this.CurrentPositionContext());
                 }
             }
             else
             {
                 identifier = new Lookup(this.scanner.GetIdentifier(), this.currentToken.Clone());
             }
             this.GetNextToken();
             this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
             try
             {
                 if (JSToken.Colon == this.currentToken.token)
                 {
                     type = this.ParseTypeExpression();
                 }
                 else
                 {
                     if (flag2)
                     {
                         this.ForceReportInfo(identifier.context, JSError.UnreachableCatch);
                     }
                     flag2 = true;
                 }
                 if (JSToken.RightParen != this.currentToken.token)
                 {
                     this.ReportError(JSError.NoRightParen);
                 }
                 this.GetNextToken();
             }
             catch (RecoveryTokenException exception3)
             {
                 if (this.IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exception3) == -1)
                 {
                     exception3._partiallyComputedNode = null;
                     throw exception3;
                 }
                 type = (TypeExpression) exception3._partiallyComputedNode;
                 if (this.currentToken.token == JSToken.RightParen)
                 {
                     this.GetNextToken();
                 }
             }
             finally
             {
                 this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
             }
             if (JSToken.LeftCurly != this.currentToken.token)
             {
                 this.ReportError(JSError.NoLeftCurly);
             }
             handler = this.ParseBlock();
             context.UpdateWith(handler.context);
         }
         catch (RecoveryTokenException exception4)
         {
             if (exception4._partiallyComputedNode == null)
             {
                 handler = new Block(this.CurrentPositionContext());
             }
             else
             {
                 handler = exception4._partiallyComputedNode;
             }
             if (this.IndexOfToken(NoSkipTokenSet.s_NoTrySkipTokenSet, exception4) == -1)
             {
                 if (type != null)
                 {
                     exception4._partiallyComputedNode = new Try(context, body, identifier, type, handler, null, false, closingBraceContext);
                 }
                 throw exception4;
             }
         }
         finally
         {
             this.noSkipTokenSet.Remove(NoSkipTokenSet.s_NoTrySkipTokenSet);
         }
     Label_02E5:
         if (JSToken.Catch == this.currentToken.token)
         {
             goto Label_00A6;
         }
         try
         {
             if (JSToken.Finally == this.currentToken.token)
             {
                 this.GetNextToken();
                 this.blockType.Add(BlockType.Finally);
                 try
                 {
                     ast4 = this.ParseBlock();
                     flag = true;
                 }
                 finally
                 {
                     this.blockType.RemoveAt(this.blockType.Count - 1);
                 }
                 context.UpdateWith(ast4.context);
             }
         }
         catch (RecoveryTokenException exception5)
         {
             exception = exception5;
         }
         if (!flag)
         {
             this.ReportError(JSError.NoCatch, true);
             ast4 = new Block(this.CurrentPositionContext());
         }
     }
     finally
     {
         this.blockType.RemoveAt(this.blockType.Count - 1);
     }
     bool finallyHasControlFlowOutOfIt = false;
     if (this.finallyEscaped > 0)
     {
         this.finallyEscaped--;
         finallyHasControlFlowOutOfIt = true;
     }
     if (exception != null)
     {
         exception._partiallyComputedNode = new Try(context, body, identifier, type, handler, ast4, finallyHasControlFlowOutOfIt, closingBraceContext);
         throw exception;
     }
     return new Try(context, body, identifier, type, handler, ast4, finallyHasControlFlowOutOfIt, closingBraceContext);
 }