Same name in other branches
  1. 5.0.x advagg_js_minify/jsminplus.inc \JSParser::Statement()
  2. 6.0.x advagg_js_minify/jsminplus.inc \JSParser::Statement()
  3. 7.x-2.x advagg_js_compress/jsminplus.inc \JSParser::Statement()
  4. 8.x-2.x advagg_js_minify/jsminplus.inc \JSParser::Statement()
  5. 8.x-3.x advagg_js_minify/jsminplus.inc \JSParser::Statement()
  6. 8.x-4.x advagg_js_minify/jsminplus.inc \JSParser::Statement()
2 calls to JSParser::Statement()
JSParser::nest in advagg_js_compress/jsminplus.inc
JSParser::Statements in advagg_js_compress/jsminplus.inc

File

advagg_js_compress/jsminplus.inc, line 911

Class

JSParser

Code

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
                    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
                            ->SyntaxError('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;
}