Inheritance: AST
示例#1
0
        private void ParseAst(JS.AST ast, string sp)
        {
            if (ast == null)
            {
                return;
            }
            if (CheckWorker())
            {
                return;
            }

            //_logView.LogStr("JSM->" + sp + ast.ToString() + "\t\t" + ast.GetType().Name);

            if (ast is JS.FunctionDeclaration)
            {
                JS.Function func = ast as JS.Function;
                ParseAstList(func.func_obj.body.elems, sp + "  ");
            }
            else if (ast is JS.Assign)
            {
                JS.Assign ass = ast as JS.Assign;

                ParseAst(ass.left, sp + "l ");
                ParseAst(ass.right, sp + "r ");
            }
            else if (ast is JS.Binary)
            {
                JS.Binary bin = ast as JS.Binary;

                string[] parts = bin.ToString().Split('.');
                if (parts.Length > 1)
                {
                    if (parts[parts.Length - 2] == "This")
                    {
                        string calledId = parts[parts.Length - 1] + "()";

                        //dup
                        // If we have a method of this name in this file/class
                        if (_addedNodes.ContainsKey(calledId))
                        {
                            // Create an edge.
                            // A definite functional assignment link.
                            AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Aqua);
                        }
                        else
                        {
                            // It's a call to a method outside this class/file.
                            //
                            //_logView.LogStr("skipped assign ref -->" + _methodNodeId + " --------> " + calledId);
                            //
                        }
                    }
                    else if (parts[parts.Length - 2] == "self")
                    {
                        string calledId = parts[parts.Length - 1] + "()";

                        //dup
                        // If we have a method of this name in this file/class
                        if (_addedNodes.ContainsKey(calledId))
                        {
                            // Get the graph node that we're linking to.
                            //Node calledNode = _addedNodes[calledId];

                            // Create an edge.
                            // A definite functional assignment link.
                            AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Aqua);
                        }
                        else
                        {
                            // It's a call to a method outside this class/file.
                            _logView.LogStr("skipped assign ref -->" + _methodNodeId + " --------> " + calledId);
                        }
                    }
                }
            }
            else if (ast is JS.Expression)
            {
                JS.Expression expr = ast as JS.Expression;
                ParseAstList(expr.exprs, sp + "  ");
            }
            else if (ast is JS.FunctionExpression)
            {
                JS.FunctionExpression expr = ast as JS.FunctionExpression;
                ParseAstList(expr.func_obj.body.elems, sp + "  ");
            }
            else if (ast is JS.For)
            {
                JS.For fr = ast as JS.For;
                ParseAst(fr.stms, sp + "  ");
            }
            else if (ast is JS.If)
            {
                JS.If iff = ast as JS.If;
                ParseAst(iff.false_stm, sp + "f  ");
                ParseAst(iff.true_stm, sp + "t  ");
            }
            else if (ast is JS.Block)
            {
                JS.Block block = ast as JS.Block;
                ParseAstList(block.elems, sp + "  ");
            }
            else if (ast is JS.VariableStatement)
            {
                JS.VariableStatement var = ast as JS.VariableStatement;
                //var.
                ParseAstList(var.var_decls, sp + "  ");
            }
            else if (ast is JS.Return)
            {
                JS.Return ret = ast as JS.Return;

                ParseAst(ret.expression, sp + "  ");
            }
            else if (ast is JS.VariableDeclaration)
            {
                JS.VariableDeclaration var = ast as JS.VariableDeclaration;

                Microsoft.JScript.New newval = var.val as Microsoft.JScript.New;

                if (newval != null && newval.exp != null)
                {
                    //_logView.LogStr("new:" + newval.exp.ToString());
                    string[] parts = newval.exp.ToString().Split('.');
                    if (parts.Length > 0)
                    {
                        string calledId = parts[parts.Length - 1] + "()";

                        // If we have a method of this name in this file/class, then
                        // we have a possible constructor link.
                        if (_addedNodes.ContainsKey(calledId))
                        {
                            // Create an edge.
                            AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Green);
                        }
                    }
                }
                else
                {
                    if (var.val != null)
                    {
                        string   valStr = var.val.ToString();
                        string[] parts  = valStr.Split('.');

                        if (parts.Length > 1 && parts[0] == "self")
                        {
                            // dup..

                            string calledId = parts[parts.Length - 1] + "()";

                            // If we have a method of this name in this file/class, then
                            // we have a possible constructor link.
                            if (_addedNodes.ContainsKey(calledId))
                            {
                                // Create an edge.
                                AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Green);
                            }
                        }
                    }
                }

                //ParseAstList(var.var_decls, sp + "  ");
            }
            else if (ast is JS.Call)
            {
                JS.Call  call     = ast as JS.Call;
                string[] parts    = call.ToString().Split(' ');
                string[] bits     = parts[0].Split('.');
                string   calledId = bits[bits.Length - 1] + "()";

                bool methodInThisClass = true;
                if (bits.Length > 1)
                {
                    if ((bits[bits.Length - 2] != "This") &&
                        (bits[bits.Length - 2] != "self"))
                    {
                        methodInThisClass = false;
                    }
                }

                // If we have a method of this name in this file/class
                if (_addedNodes.ContainsKey(calledId))
                {
                    // Create an edge.
                    if (methodInThisClass)
                    {
                        // A definite link.
                        AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Black);
                    }
                    else
                    {
                        // A tentative link.
                        AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Gray);
                    }
                }
                else
                {
                    // It's a call to a method outside this class/file.
                    //
                    //_logView.LogStr("skipped -------->" + _methodNodeId + " --------> " + parts[0]);
                    //
                }
            }
        }
示例#2
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;
      }
示例#3
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 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;
 }