コード例 #1
0
ファイル: jsobject.cs プロジェクト: ydunk/masters
 IEnumerator IEnumerable.GetEnumerator()
 {
     return(ForIn.JScriptGetEnumerator(this));
 }
コード例 #2
0
ファイル: Parser.cs プロジェクト: mayatforest/Refractor
        /**
         * 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;
        }
コード例 #3
0
ファイル: jsparser.cs プロジェクト: ArildF/masters
      //---------------------------------------------------------------------------------------
      // 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;
      }