JSParser::Statement PHP Méthode

Statement() private méthode

private Statement ( $x )
    private function Statement($x)
    {
        $tt = $this->t->get();
        $n2 = null;
        // Cases for statements ending in a right curly return early, avoiding the
        // common semicolon insertion magic after this switch.
        switch ($tt) {
            case KEYWORD_FUNCTION:
                return $this->FunctionDefinition($x, true, count($x->stmtStack) > 1 ? STATEMENT_FORM : DECLARED_FORM);
                break;
            case OP_LEFT_CURLY:
                $n = $this->Statements($x);
                $this->t->mustMatch(OP_RIGHT_CURLY);
                return $n;
            case KEYWORD_IF:
                $n = new JSNode($this->t);
                $n->condition = $this->ParenExpression($x);
                array_push($x->stmtStack, $n);
                $n->thenPart = $this->Statement($x);
                $n->elsePart = $this->t->match(KEYWORD_ELSE) ? $this->Statement($x) : null;
                array_pop($x->stmtStack);
                return $n;
            case KEYWORD_SWITCH:
                $n = new JSNode($this->t);
                $this->t->mustMatch(OP_LEFT_PAREN);
                $n->discriminant = $this->Expression($x);
                $this->t->mustMatch(OP_RIGHT_PAREN);
                $n->cases = array();
                $n->defaultIndex = -1;
                array_push($x->stmtStack, $n);
                $this->t->mustMatch(OP_LEFT_CURLY);
                while (($tt = $this->t->get()) != OP_RIGHT_CURLY) {
                    switch ($tt) {
                        case KEYWORD_DEFAULT:
                            if ($n->defaultIndex >= 0) {
                                throw $this->t->newSyntaxError('More than one switch default');
                            }
                            // FALL THROUGH
                        // FALL THROUGH
                        case KEYWORD_CASE:
                            $n2 = new JSNode($this->t);
                            if ($tt == KEYWORD_DEFAULT) {
                                $n->defaultIndex = count($n->cases);
                            } else {
                                $n2->caseLabel = $this->Expression($x, OP_COLON);
                            }
                            break;
                        default:
                            throw $this->t->newSyntaxError('Invalid switch case');
                    }
                    $this->t->mustMatch(OP_COLON);
                    $n2->statements = new JSNode($this->t, JS_BLOCK);
                    while (($tt = $this->t->peek()) != KEYWORD_CASE && $tt != KEYWORD_DEFAULT && $tt != OP_RIGHT_CURLY) {
                        $n2->statements->addNode($this->Statement($x));
                    }
                    array_push($n->cases, $n2);
                }
                array_pop($x->stmtStack);
                return $n;
            case KEYWORD_FOR:
                $n = new JSNode($this->t);
                $n->isLoop = true;
                $this->t->mustMatch(OP_LEFT_PAREN);
                if (($tt = $this->t->peek()) != OP_SEMICOLON) {
                    $x->inForLoopInit = true;
                    if ($tt == KEYWORD_VAR || $tt == KEYWORD_CONST) {
                        $this->t->get();
                        $n2 = $this->Variables($x);
                    } else {
                        $n2 = $this->Expression($x);
                    }
                    $x->inForLoopInit = false;
                }
                if ($n2 && $this->t->match(KEYWORD_IN)) {
                    $n->type = JS_FOR_IN;
                    if ($n2->type == KEYWORD_VAR) {
                        if (count($n2->treeNodes) != 1) {
                            throw $this->t->newSyntaxError('Invalid for..in left-hand side', $this->t->filename, $n2->lineno);
                        }
                        // NB: n2[0].type == IDENTIFIER and n2[0].value == n2[0].name.
                        $n->iterator = $n2->treeNodes[0];
                        $n->varDecl = $n2;
                    } else {
                        $n->iterator = $n2;
                        $n->varDecl = null;
                    }
                    $n->object = $this->Expression($x);
                } else {
                    $n->setup = $n2 ? $n2 : null;
                    $this->t->mustMatch(OP_SEMICOLON);
                    $n->condition = $this->t->peek() == OP_SEMICOLON ? null : $this->Expression($x);
                    $this->t->mustMatch(OP_SEMICOLON);
                    $n->update = $this->t->peek() == OP_RIGHT_PAREN ? null : $this->Expression($x);
                }
                $this->t->mustMatch(OP_RIGHT_PAREN);
                $n->body = $this->nest($x, $n);
                return $n;
            case KEYWORD_WHILE:
                $n = new JSNode($this->t);
                $n->isLoop = true;
                $n->condition = $this->ParenExpression($x);
                $n->body = $this->nest($x, $n);
                return $n;
            case KEYWORD_DO:
                $n = new JSNode($this->t);
                $n->isLoop = true;
                $n->body = $this->nest($x, $n, KEYWORD_WHILE);
                $n->condition = $this->ParenExpression($x);
                if (!$x->ecmaStrictMode) {
                    // <script language="JavaScript"> (without version hints) may need
                    // automatic semicolon insertion without a newline after do-while.
                    // See http://bugzilla.mozilla.org/show_bug.cgi?id=238945.
                    $this->t->match(OP_SEMICOLON);
                    return $n;
                }
                break;
            case KEYWORD_BREAK:
            case KEYWORD_CONTINUE:
                $n = new JSNode($this->t);
                if ($this->t->peekOnSameLine() == TOKEN_IDENTIFIER) {
                    $this->t->get();
                    $n->label = $this->t->currentToken()->value;
                }
                $ss = $x->stmtStack;
                $i = count($ss);
                $label = $n->label;
                if ($label) {
                    do {
                        if (--$i < 0) {
                            throw $this->t->newSyntaxError('Label not found');
                        }
                    } while ($ss[$i]->label != $label);
                } else {
                    do {
                        if (--$i < 0) {
                            throw $this->t->newSyntaxError('Invalid ' . $tt);
                        }
                    } while (!$ss[$i]->isLoop && ($tt != KEYWORD_BREAK || $ss[$i]->type != KEYWORD_SWITCH));
                }
                $n->target = $ss[$i];
                break;
            case KEYWORD_TRY:
                $n = new JSNode($this->t);
                $n->tryBlock = $this->Block($x);
                $n->catchClauses = array();
                while ($this->t->match(KEYWORD_CATCH)) {
                    $n2 = new JSNode($this->t);
                    $this->t->mustMatch(OP_LEFT_PAREN);
                    $n2->varName = $this->t->mustMatch(TOKEN_IDENTIFIER)->value;
                    if ($this->t->match(KEYWORD_IF)) {
                        if ($x->ecmaStrictMode) {
                            throw $this->t->newSyntaxError('Illegal catch guard');
                        }
                        if (count($n->catchClauses) && !end($n->catchClauses)->guard) {
                            throw $this->t->newSyntaxError('Guarded catch after unguarded');
                        }
                        $n2->guard = $this->Expression($x);
                    } else {
                        $n2->guard = null;
                    }
                    $this->t->mustMatch(OP_RIGHT_PAREN);
                    $n2->block = $this->Block($x);
                    array_push($n->catchClauses, $n2);
                }
                if ($this->t->match(KEYWORD_FINALLY)) {
                    $n->finallyBlock = $this->Block($x);
                }
                if (!count($n->catchClauses) && !$n->finallyBlock) {
                    throw $this->t->newSyntaxError('Invalid try statement');
                }
                return $n;
            case KEYWORD_CATCH:
            case KEYWORD_FINALLY:
                throw $this->t->newSyntaxError($tt + ' without preceding try');
            case KEYWORD_THROW:
                $n = new JSNode($this->t);
                $n->value = $this->Expression($x);
                break;
            case KEYWORD_RETURN:
                if (!$x->inFunction) {
                    throw $this->t->newSyntaxError('Invalid return');
                }
                $n = new JSNode($this->t);
                $tt = $this->t->peekOnSameLine();
                if ($tt != TOKEN_END && $tt != TOKEN_NEWLINE && $tt != OP_SEMICOLON && $tt != OP_RIGHT_CURLY) {
                    $n->value = $this->Expression($x);
                } else {
                    $n->value = null;
                }
                break;
            case KEYWORD_WITH:
                $n = new JSNode($this->t);
                $n->object = $this->ParenExpression($x);
                $n->body = $this->nest($x, $n);
                return $n;
            case KEYWORD_VAR:
            case KEYWORD_CONST:
                $n = $this->Variables($x);
                break;
            case TOKEN_CONDCOMMENT_START:
            case TOKEN_CONDCOMMENT_END:
                $n = new JSNode($this->t);
                return $n;
            case KEYWORD_DEBUGGER:
                $n = new JSNode($this->t);
                break;
            case TOKEN_NEWLINE:
            case OP_SEMICOLON:
                $n = new JSNode($this->t, OP_SEMICOLON);
                $n->expression = null;
                return $n;
            default:
                if ($tt == TOKEN_IDENTIFIER) {
                    $this->t->scanOperand = false;
                    $tt = $this->t->peek();
                    $this->t->scanOperand = true;
                    if ($tt == OP_COLON) {
                        $label = $this->t->currentToken()->value;
                        $ss = $x->stmtStack;
                        for ($i = count($ss) - 1; $i >= 0; --$i) {
                            if ($ss[$i]->label == $label) {
                                throw $this->t->newSyntaxError('Duplicate label');
                            }
                        }
                        $this->t->get();
                        $n = new JSNode($this->t, JS_LABEL);
                        $n->label = $label;
                        $n->statement = $this->nest($x, $n);
                        return $n;
                    }
                }
                $n = new JSNode($this->t, OP_SEMICOLON);
                $this->t->unget();
                $n->expression = $this->Expression($x);
                $n->end = $n->expression->end;
                break;
        }
        if ($this->t->lineno == $this->t->currentToken()->lineno) {
            $tt = $this->t->peekOnSameLine();
            if ($tt != TOKEN_END && $tt != TOKEN_NEWLINE && $tt != OP_SEMICOLON && $tt != OP_RIGHT_CURLY) {
                throw $this->t->newSyntaxError('Missing ; before statement');
            }
        }
        $this->t->match(OP_SEMICOLON);
        return $n;
    }