793 $tt = $this->t->get();
814 $n =
new JSNode($this->t);
816 array_push($x->stmtStack, $n);
819 array_pop($x->stmtStack);
823 $n =
new JSNode($this->t);
828 $n->defaultIndex = -1;
830 array_push($x->stmtStack, $n);
839 if ($n->defaultIndex >= 0)
840 throw $this->t->newSyntaxError(
'More than one switch default');
843 $n2 =
new JSNode($this->t);
845 $n->defaultIndex = count($n->cases);
850 throw $this->t->newSyntaxError(
'Invalid switch case');
856 $n2->statements->addNode($this->
Statement($x));
858 array_push($n->cases, $n2);
861 array_pop($x->stmtStack);
865 $n =
new JSNode($this->t);
871 $x->inForLoopInit =
true;
881 $x->inForLoopInit =
false;
889 if (count($n2->treeNodes) != 1)
891 throw $this->t->SyntaxError(
892 'Invalid for..in left-hand side',
899 $n->iterator = $n2->treeNodes[0];
912 $n->setup = $n2 ? $n2 :
null;
920 $n->body = $this->
nest($x, $n);
924 $n =
new JSNode($this->t);
927 $n->body = $this->
nest($x, $n);
931 $n =
new JSNode($this->t);
935 if (!$x->ecmaStrictMode)
947 $n =
new JSNode($this->t);
952 $n->label = $this->t->currentToken()->value;
963 throw $this->t->newSyntaxError(
'Label not found');
965 while ($ss[$i]->label != $label);
972 throw $this->t->newSyntaxError(
'Invalid ' . $tt);
977 $n->target = $ss[$i];
981 $n =
new JSNode($this->t);
982 $n->tryBlock = $this->
Block($x);
983 $n->catchClauses =
array();
987 $n2 =
new JSNode($this->t);
993 if ($x->ecmaStrictMode)
994 throw $this->t->newSyntaxError(
'Illegal catch guard');
996 if (count($n->catchClauses) && !end($n->catchClauses)->guard)
997 throw $this->t->newSyntaxError(
'Guarded catch after unguarded');
1007 $n2->block = $this->
Block($x);
1008 array_push($n->catchClauses, $n2);
1012 $n->finallyBlock = $this->
Block($x);
1014 if (!count($n->catchClauses) && !$n->finallyBlock)
1015 throw $this->t->newSyntaxError(
'Invalid try statement');
1020 throw $this->t->newSyntaxError($tt .
' without preceding try');
1023 $n =
new JSNode($this->t);
1028 if (!$x->inFunction)
1029 throw $this->t->newSyntaxError(
'Invalid return');
1031 $n =
new JSNode($this->t);
1032 $tt = $this->t->peekOnSameLine();
1040 $n =
new JSNode($this->t);
1042 $n->body = $this->
nest($x, $n);
1052 $n =
new JSNode($this->t);
1056 $n =
new JSNode($this->t);
1062 $n->expression =
null;
1068 $this->t->scanOperand =
false;
1069 $tt = $this->t->peek();
1070 $this->t->scanOperand =
true;
1073 $label = $this->t->currentToken()->value;
1074 $ss = $x->stmtStack;
1075 for ($i = count($ss) - 1; $i >= 0; --$i)
1077 if ($ss[$i]->label == $label)
1078 throw $this->t->newSyntaxError(
'Duplicate label');
1084 $n->statement = $this->
nest($x, $n);
1093 $n->end = $n->expression->end;
1097 if ($this->t->lineno == $this->t->currentToken()->lineno)
1099 $tt = $this->t->peekOnSameLine();
1101 throw $this->t->newSyntaxError(
'Missing ; before statement');
1111 $f =
new JSNode($this->t);
1117 $f->name = $this->t->currentToken()->value;
1118 elseif ($requireName)
1119 throw $this->t->newSyntaxError(
'Missing function identifier');
1122 $f->params =
array();
1127 throw $this->t->newSyntaxError(
'Missing formal parameter');
1129 array_push($f->params, $this->t->currentToken()->value);
1138 $f->body = $this->
Script($x2);
1141 $f->end = $this->t->currentToken()->end;
1143 $f->functionForm = $functionForm;
1145 array_push($x->funDecls, $f);
1181 $operators =
array();
1182 $operands =
array();
1185 $bl = $x->bracketLevel;
1186 $cl = $x->curlyLevel;
1187 $pl = $x->parenLevel;
1188 $hl = $x->hookLevel;
1190 while (($tt = $this->t->get()) !=
TOKEN_END)
1193 $x->bracketLevel == $bl &&
1194 $x->curlyLevel == $cl &&
1195 $x->parenLevel == $pl &&
1196 $x->hookLevel == $hl
1211 if ($this->t->scanOperand)
1214 while ( !empty($operators) &&
1215 $this->opPrecedence[end($operators)->
type] > $this->opPrecedence[$tt]
1217 $this->
reduce($operators, $operands);
1219 array_push($operators,
new JSNode($this->t));
1222 $this->t->scanOperand =
true;
1229 array_push($operands, $n);
1236 throw $this->t->newSyntaxError(
'Invalid label');
1240 if ($this->t->scanOperand)
1244 while ( !empty($operators) &&
1245 $this->opPrecedence[end($operators)->
type] > $this->opPrecedence[$tt]
1247 $this->
reduce($operators, $operands);
1249 array_push($operators,
new JSNode($this->t));
1250 end($operands)->assignOp = $this->t->currentToken()->assignOp;
1251 $this->t->scanOperand =
true;
1258 if ($x->inForLoopInit && !$x->hookLevel &&
1259 !$x->bracketLevel && !$x->curlyLevel &&
1267 if ($tt ==
OP_COMMA && $x->hookLevel &&
1268 !$x->bracketLevel && !$x->curlyLevel &&
1287 if ($this->t->scanOperand)
1290 while ( !empty($operators) &&
1291 $this->opPrecedence[end($operators)->
type] >= $this->opPrecedence[$tt]
1293 $this->
reduce($operators, $operands);
1298 array_push($operands,
new JSNode($this->t,
OP_DOT, array_pop($operands),
new JSNode($this->t)));
1302 array_push($operators,
new JSNode($this->t));
1303 $this->t->scanOperand =
true;
1310 if (!$this->t->scanOperand)
1313 array_push($operators,
new JSNode($this->t));
1317 if ($this->t->scanOperand)
1319 array_push($operators,
new JSNode($this->t));
1324 $t = $this->t->tokens[($this->t->tokenIndex + $this->t->lookahead - 1) & 3];
1325 if (
$t &&
$t->lineno != $this->t->lineno)
1328 if (!empty($operators))
1331 while ($this->opPrecedence[end($operators)->type] > $this->opPrecedence[$tt])
1332 $this->
reduce($operators, $operands);
1335 $n =
new JSNode($this->t, $tt, array_pop($operands));
1337 array_push($operands, $n);
1342 if (!$this->t->scanOperand)
1346 $this->t->scanOperand =
false;
1351 if (!$this->t->scanOperand)
1354 array_push($operands,
new JSNode($this->t));
1355 $this->t->scanOperand =
false;
1360 if ($this->t->scanOperand)
1361 array_push($operators,
new JSNode($this->t));
1363 array_push($operands,
new JSNode($this->t));
1367 if ($this->t->scanOperand)
1387 array_push($operands, $n);
1388 $this->t->scanOperand =
false;
1394 $this->t->scanOperand =
true;
1400 if ($this->t->scanOperand || $x->bracketLevel == $bl)
1410 if (!$this->t->scanOperand)
1421 $tt = $this->t->get();
1422 $tv = $this->t->currentToken()->value;
1423 if (($tv ==
'get' || $tv ==
'set') && $this->t->peek() ==
TOKEN_IDENTIFIER)
1425 if ($x->ecmaStrictMode)
1426 throw $this->t->newSyntaxError(
'Illegal property accessor');
1437 $id =
new JSNode($this->t);
1441 if ($x->ecmaStrictMode)
1442 throw $this->t->newSyntaxError(
'Illegal trailing ,');
1446 throw $this->t->newSyntaxError(
'Invalid property name');
1459 array_push($operands, $n);
1460 $this->t->scanOperand =
false;
1465 if (!$this->t->scanOperand && $x->curlyLevel != $cl)
1466 throw new Exception(
'PANIC: right curly botch');
1470 if ($this->t->scanOperand)
1476 while ( !empty($operators) &&
1477 $this->opPrecedence[end($operators)->
type] > $this->opPrecedence[
KEYWORD_NEW]
1479 $this->
reduce($operators, $operands);
1484 $n = end($operators);
1485 $this->t->scanOperand =
true;
1490 array_pop($operators);
1491 $n->addNode(array_pop($operands));
1498 array_push($operands, $n);
1499 $this->t->scanOperand =
false;
1513 if ($this->t->scanOperand || $x->parenLevel == $pl)
1525 $n = end($operands);
1526 if ($n->treeNodes[1]->type !=
OP_COMMA)
1527 $n->treeNodes[1] =
new JSNode($this->t,
JS_LIST, $n->treeNodes[1]);
1529 $n->treeNodes[1]->type =
JS_LIST;
1543 if ($x->hookLevel != $hl)
1544 throw $this->t->newSyntaxError(
'Missing : in conditional expression');
1546 if ($x->parenLevel != $pl)
1547 throw $this->t->newSyntaxError(
'Missing ) in parenthetical');
1549 if ($x->bracketLevel != $bl)
1550 throw $this->t->newSyntaxError(
'Missing ] in index expression');
1552 if ($this->t->scanOperand)
1553 throw $this->t->newSyntaxError(
'Missing operand');
1556 $this->t->scanOperand =
true;
1559 while (count($operators))
1560 $this->
reduce($operators, $operands);
1562 return array_pop($operands);
1587 private function reduce(&$operators, &$operands)
1589 $n = array_pop($operators);
1591 $arity = $this->opArity[$op];
1592 $c = count($operands);
1598 $left = $operands[$c - 2];
1599 if ($left->type == $op)
1601 $right = array_pop($operands);
1602 $left->addNode($right);
1610 $a = array_splice($operands, $c - $arity);
1611 for ($i = 0; $i < $arity; $i++)
1612 $n->addNode($a[$i]);
1615 $te = $this->t->currentToken()->end;
1619 array_push($operands, $n);