private function JSParser::Statement in Javascript Aggregator 6
1 call to JSParser::Statement()
File
- ./
jsminplus.php, line 790
Class
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;
}