67 define(
'TOKEN_END', 1);
68 define(
'TOKEN_NUMBER', 2);
69 define(
'TOKEN_IDENTIFIER', 3);
70 define(
'TOKEN_STRING', 4);
71 define(
'TOKEN_REGEXP', 5);
72 define(
'TOKEN_NEWLINE', 6);
73 define(
'TOKEN_CONDCOMMENT_START', 7);
74 define(
'TOKEN_CONDCOMMENT_END', 8);
76 define(
'JS_SCRIPT', 100);
77 define(
'JS_BLOCK', 101);
78 define(
'JS_LABEL', 102);
79 define(
'JS_FOR_IN', 103);
80 define(
'JS_CALL', 104);
81 define(
'JS_NEW_WITH_ARGS', 105);
82 define(
'JS_INDEX', 106);
83 define(
'JS_ARRAY_INIT', 107);
84 define(
'JS_OBJECT_INIT', 108);
85 define(
'JS_PROPERTY_INIT', 109);
86 define(
'JS_GETTER', 110);
87 define(
'JS_SETTER', 111);
88 define(
'JS_GROUP', 112);
89 define(
'JS_LIST', 113);
91 define(
'JS_MINIFIED', 999);
93 define(
'DECLARED_FORM', 0);
94 define(
'EXPRESSED_FORM', 1);
95 define(
'STATEMENT_FORM', 2);
98 define(
'OP_SEMICOLON',
';');
99 define(
'OP_COMMA',
',');
100 define(
'OP_HOOK',
'?');
101 define(
'OP_COLON',
':');
102 define(
'OP_OR',
'||');
103 define(
'OP_AND',
'&&');
104 define(
'OP_BITWISE_OR',
'|');
105 define(
'OP_BITWISE_XOR',
'^');
106 define(
'OP_BITWISE_AND',
'&');
107 define(
'OP_STRICT_EQ',
'===');
108 define(
'OP_EQ',
'==');
109 define(
'OP_ASSIGN',
'=');
110 define(
'OP_STRICT_NE',
'!==');
111 define(
'OP_NE',
'!=');
112 define(
'OP_LSH',
'<<');
113 define(
'OP_LE',
'<=');
114 define(
'OP_LT',
'<');
115 define(
'OP_URSH',
'>>>');
116 define(
'OP_RSH',
'>>');
117 define(
'OP_GE',
'>=');
118 define(
'OP_GT',
'>');
119 define(
'OP_INCREMENT',
'++');
120 define(
'OP_DECREMENT',
'--');
121 define(
'OP_PLUS',
'+');
122 define(
'OP_MINUS',
'-');
123 define(
'OP_MUL',
'*');
124 define(
'OP_DIV',
'/');
125 define(
'OP_MOD',
'%');
126 define(
'OP_NOT',
'!');
127 define(
'OP_BITWISE_NOT',
'~');
128 define(
'OP_DOT',
'.');
129 define(
'OP_LEFT_BRACKET',
'[');
130 define(
'OP_RIGHT_BRACKET',
']');
131 define(
'OP_LEFT_CURLY',
'{');
132 define(
'OP_RIGHT_CURLY',
'}');
133 define(
'OP_LEFT_PAREN',
'(');
134 define(
'OP_RIGHT_PAREN',
')');
135 define(
'OP_CONDCOMMENT_END',
'@*/');
137 define(
'OP_UNARY_PLUS',
'U+');
138 define(
'OP_UNARY_MINUS',
'U-');
141 define(
'KEYWORD_BREAK',
'break');
142 define(
'KEYWORD_CASE',
'case');
143 define(
'KEYWORD_CATCH',
'catch');
144 define(
'KEYWORD_CONST',
'const');
145 define(
'KEYWORD_CONTINUE',
'continue');
146 define(
'KEYWORD_DEBUGGER',
'debugger');
147 define(
'KEYWORD_DEFAULT',
'default');
148 define(
'KEYWORD_DELETE',
'delete');
149 define(
'KEYWORD_DO',
'do');
150 define(
'KEYWORD_ELSE',
'else');
151 define(
'KEYWORD_ENUM',
'enum');
152 define(
'KEYWORD_FALSE',
'false');
153 define(
'KEYWORD_FINALLY',
'finally');
154 define(
'KEYWORD_FOR',
'for');
155 define(
'KEYWORD_FUNCTION',
'function');
156 define(
'KEYWORD_IF',
'if');
157 define(
'KEYWORD_IN',
'in');
158 define(
'KEYWORD_INSTANCEOF',
'instanceof');
159 define(
'KEYWORD_NEW',
'new');
160 define(
'KEYWORD_NULL',
'null');
161 define(
'KEYWORD_RETURN',
'return');
162 define(
'KEYWORD_SWITCH',
'switch');
163 define(
'KEYWORD_THIS',
'this');
164 define(
'KEYWORD_THROW',
'throw');
165 define(
'KEYWORD_TRUE',
'true');
166 define(
'KEYWORD_TRY',
'try');
167 define(
'KEYWORD_TYPEOF',
'typeof');
168 define(
'KEYWORD_VAR',
'var');
169 define(
'KEYWORD_VOID',
'void');
170 define(
'KEYWORD_WHILE',
'while');
171 define(
'KEYWORD_WITH',
'with');
178 'break',
'case',
'catch',
'continue',
'default',
'delete',
'do',
179 'else',
'finally',
'for',
'function',
'if',
'in',
'instanceof',
180 'new',
'return',
'switch',
'this',
'throw',
'try',
'typeof',
'var',
181 'void',
'while',
'with',
183 'abstract',
'boolean',
'byte',
'char',
'class',
'const',
'debugger',
184 'double',
'enum',
'export',
'extends',
'final',
'float',
'goto',
185 'implements',
'import',
'int',
'interface',
'long',
'native',
186 'package',
'private',
'protected',
'public',
'short',
'static',
187 'super',
'synchronized',
'throws',
'transient',
'volatile',
190 'arguments',
'eval',
'true',
'false',
'Infinity',
'NaN',
'null',
'undefined'
195 $this->parser =
new JSParser($this);
198 public static function minify($js, $filename=
'')
206 return $instance->min($js, $filename);
209 private function min($js, $filename)
213 $n = $this->parser->parse($js, $filename, 1);
218 echo
$e->getMessage() .
"\n";
236 $noBlockGrouping =
true;
240 $childs =
$n->treeNodes;
242 for ($c = 0, $i = 0, $j = count($childs); $i < $j; $i++)
244 $type = $childs[$i]->type;
260 $t =
',' . substr(
$t, 4);
276 if ($c > 1 && !$noBlockGrouping)
283 $s .=
'function' . (
$n->name ?
' ' .
$n->name :
'') .
'(';
285 for ($i = 0, $j = count(
$params); $i < $j; $i++)
293 $elsePart =
$n->elsePart ? $this->
parseTree(
$n->elsePart) :
null;
302 if ($thenPart !=
';' && $thenPart[0] !=
'{')
303 $thenPart =
'{' . $thenPart .
'}';
305 $s .= $thenPart .
'else';
308 if ($elsePart[0] !=
'{')
322 for ($i = 0, $j = count($cases); $i < $j; $i++)
330 $statement = $this->
parseTree($case->statements,
true);
344 .
';' . (
$n->condition ? $this->parseTree(
$n->condition) :
'')
345 .
';' . (
$n->update ? $this->parseTree(
$n->update) :
'') .
')';
380 $s =
$n->value . (
$n->label ?
' ' .
$n->label :
'');
385 $catchClauses =
$n->catchClauses;
386 for ($i = 0, $j = count($catchClauses); $i < $j; $i++)
388 $t = $catchClauses[$i];
389 $s .=
'catch(' .
$t->varName . (
$t->guard ?
' if ' . $this->
parseTree(
$t->guard) :
'') .
'){' . $this->
parseTree(
$t->block,
true) .
'}';
391 if (
$n->finallyBlock)
392 $s .=
'finally{' . $this->
parseTree(
$n->finallyBlock,
true) .
'}';
417 $s =
$n->value .
' ';
418 $childs =
$n->treeNodes;
419 for ($i = 0, $j = count($childs); $i < $j; $i++)
422 $s .= ($i ?
',' :
'') .
$t->name;
423 $u =
$t->initializer;
464 throw new Exception(
'NOT IMPLEMENTED: DEBUGGER');
470 $childs =
$n->treeNodes;
471 for ($i = 0, $j = count($childs); $i < $j; $i++)
476 if ($expression =
$n->expression)
485 $childs =
$n->treeNodes;
486 for ($i = 0, $j = count($childs); $i < $j; $i++)
487 $s .= ($i ?
',' :
'') . $this->
parseTree($childs[$i]);
512 switch (
$n->treeNodes[1]->type)
527 $s = substr($left, 0, -1) . substr(
$right, 1);
561 $this->isValidIdentifier(substr(
$n->treeNodes[1]->value, 1, -1))
563 $s .=
'.' . substr(
$n->treeNodes[1]->value, 1, -1);
569 $childs =
$n->treeNodes;
570 for ($i = 0, $j = count($childs); $i < $j; $i++)
571 $s .= ($i ?
',' :
'') . $this->
parseTree($childs[$i]);
585 $childs =
$n->treeNodes;
586 for ($i = 0, $j = count($childs); $i < $j; $i++)
588 $s .= ($i ?
',' :
'') . $this->
parseTree($childs[$i]);
595 $childs =
$n->treeNodes;
596 for ($i = 0, $j = count($childs); $i < $j; $i++)
605 $this->isValidIdentifier(substr(
$t->treeNodes[0]->value, 1, -1))
607 $s .= substr(
$t->treeNodes[0]->value, 1, -1);
609 $s .=
$t->treeNodes[0]->value;
616 $s .=
' ' .
$t->name .
'(';
618 for ($i = 0, $j = count(
$params); $i < $j; $i++)
628 if (preg_match(
'/^([1-9]+)(0{3,})$/',
$s, $m))
629 $s = $m[1] .
'e' . strlen($m[2]);
639 $n->treeNodes[0]->type,
656 throw new Exception(
'UNKNOWN TOKEN TYPE: ' .
$n->type);
664 return preg_match(
'/^[a-zA-Z_][a-zA-Z0-9_]*$/', $string) && !in_array($string, $this->reserved);
669 return $char ==
'_' || $char ==
'$' || ctype_alnum($char);
681 '=' => 2,
'?' => 2,
':' => 2,
688 '==' => 9,
'!=' => 9,
'===' => 9,
'!==' => 9,
689 '<' => 10,
'<=' => 10,
'>=' => 10,
'>' => 10,
'in' => 10,
'instanceof' => 10,
690 '<<' => 11,
'>>' => 11,
'>>>' => 11,
691 '+' => 12,
'-' => 12,
692 '*' => 13,
'/' => 13,
'%' => 13,
693 'delete' => 14,
'void' => 14,
'typeof' => 14,
694 '!' => 14,
'~' => 14,
'U+' => 14,
'U-' => 14,
695 '++' => 15,
'--' => 15,
711 '==' => 2,
'!=' => 2,
'===' => 2,
'!==' => 2,
712 '<' => 2,
'<=' => 2,
'>=' => 2,
'>' => 2,
'in' => 2,
'instanceof' => 2,
713 '<<' => 2,
'>>' => 2,
'>>>' => 2,
715 '*' => 2,
'/' => 2,
'%' => 2,
716 'delete' => 1,
'void' => 1,
'typeof' => 1,
717 '!' => 1,
'~' => 1,
'U+' => 1,
'U-' => 1,
718 '++' => 1,
'--' => 1,
735 $this->t->init(
$s,
$f, $l);
739 if (!$this->t->isDone())
740 throw $this->t->newSyntaxError(
'Syntax error');
749 $n->funDecls = $x->funDecls;
750 $n->varDecls = $x->varDecls;
755 $n->value = $this->minifier->parseTree(
$n);
758 $n->treeNodes =
null;
771 array_push($x->stmtStack,
$n);
774 $n->addNode($this->Statement($x));
776 array_pop($x->stmtStack);
792 $tt = $this->t->get();
815 array_push($x->stmtStack,
$n);
818 array_pop($x->stmtStack);
827 $n->defaultIndex = -1;
829 array_push($x->stmtStack,
$n);
838 if (
$n->defaultIndex >= 0)
839 throw $this->t->newSyntaxError(
'More than one switch default');
842 $n2 =
new JSNode($this->t);
844 $n->defaultIndex = count(
$n->cases);
849 throw $this->t->newSyntaxError(
'Invalid switch case');
855 $n2->statements->addNode($this->
Statement($x));
857 array_push(
$n->cases, $n2);
860 array_pop($x->stmtStack);
870 $x->inForLoopInit =
true;
880 $x->inForLoopInit =
false;
888 if (count($n2->treeNodes) != 1)
890 throw $this->t->SyntaxError(
891 'Invalid for..in left-hand side',
898 $n->iterator = $n2->treeNodes[0];
911 $n->setup = $n2 ? $n2 :
null;
934 if (!$x->ecmaStrictMode)
951 $n->label = $this->t->currentToken()->value;
962 throw $this->t->newSyntaxError(
'Label not found');
964 while ($ss[$i]->label != $label);
971 throw $this->t->newSyntaxError(
'Invalid ' . $tt);
976 $n->target = $ss[$i];
981 $n->tryBlock = $this->
Block($x);
986 $n2 =
new JSNode($this->t);
992 if ($x->ecmaStrictMode)
993 throw $this->t->newSyntaxError(
'Illegal catch guard');
995 if (count(
$n->catchClauses) && !end(
$n->catchClauses)->guard)
996 throw $this->t->newSyntaxError(
'Guarded catch after unguarded');
1006 $n2->block = $this->
Block($x);
1007 array_push(
$n->catchClauses, $n2);
1011 $n->finallyBlock = $this->Block($x);
1013 if (!count(
$n->catchClauses) && !
$n->finallyBlock)
1014 throw $this->t->newSyntaxError(
'Invalid try statement');
1019 throw $this->t->newSyntaxError($tt +
' without preceding try');
1027 if (!$x->inFunction)
1028 throw $this->t->newSyntaxError(
'Invalid return');
1031 $tt = $this->t->peekOnSameLine();
1061 $n->expression =
null;
1067 $this->t->scanOperand =
false;
1068 $tt = $this->t->peek();
1069 $this->t->scanOperand =
true;
1072 $label = $this->t->currentToken()->value;
1073 $ss = $x->stmtStack;
1074 for ($i = count($ss) - 1; $i >= 0; --$i)
1076 if ($ss[$i]->label == $label)
1077 throw $this->t->newSyntaxError(
'Duplicate label');
1083 $n->statement = $this->
nest($x,
$n);
1092 $n->end =
$n->expression->end;
1096 if ($this->t->lineno == $this->t->currentToken()->lineno)
1098 $tt = $this->t->peekOnSameLine();
1100 throw $this->t->newSyntaxError(
'Missing ; before statement');
1116 $f->name = $this->t->currentToken()->value;
1117 elseif ($requireName)
1118 throw $this->t->newSyntaxError(
'Missing function identifier');
1126 throw $this->t->newSyntaxError(
'Missing formal parameter');
1128 array_push(
$f->params, $this->t->currentToken()->value);
1140 $f->end = $this->t->currentToken()->end;
1142 $f->functionForm = $functionForm;
1144 array_push($x->funDecls,
$f);
1157 $n2 =
new JSNode($this->t);
1158 $n2->name = $n2->value;
1162 if ($this->t->currentToken()->assignOp)
1163 throw $this->t->newSyntaxError(
'Invalid variable initialization');
1171 array_push($x->varDecls, $n2);
1180 $operators =
array();
1181 $operands =
array();
1184 $bl = $x->bracketLevel;
1185 $cl = $x->curlyLevel;
1186 $pl = $x->parenLevel;
1187 $hl = $x->hookLevel;
1189 while (($tt = $this->t->get()) !=
TOKEN_END)
1192 $x->bracketLevel == $bl &&
1193 $x->curlyLevel == $cl &&
1194 $x->parenLevel == $pl &&
1195 $x->hookLevel == $hl
1210 if ($this->t->scanOperand)
1213 while ( !empty($operators) &&
1214 $this->opPrecedence[end($operators)->type] > $this->opPrecedence[$tt]
1216 $this->
reduce($operators, $operands);
1218 array_push($operators,
new JSNode($this->t));
1221 $this->t->scanOperand =
true;
1228 array_push($operands,
$n);
1235 throw $this->t->newSyntaxError(
'Invalid label');
1239 if ($this->t->scanOperand)
1243 while ( !empty($operators) &&
1244 $this->opPrecedence[end($operators)->
type] > $this->opPrecedence[$tt]
1246 $this->
reduce($operators, $operands);
1248 array_push($operators,
new JSNode($this->t));
1249 end($operands)->assignOp = $this->t->currentToken()->assignOp;
1250 $this->t->scanOperand =
true;
1257 if ($x->inForLoopInit && !$x->hookLevel &&
1258 !$x->bracketLevel && !$x->curlyLevel &&
1266 if ($tt ==
OP_COMMA && $x->hookLevel &&
1267 !$x->bracketLevel && !$x->curlyLevel &&
1286 if ($this->t->scanOperand)
1289 while ( !empty($operators) &&
1290 $this->opPrecedence[end($operators)->
type] >= $this->opPrecedence[$tt]
1292 $this->
reduce($operators, $operands);
1297 array_push($operands,
new JSNode($this->t,
OP_DOT, array_pop($operands),
new JSNode($this->t)));
1301 array_push($operators,
new JSNode($this->t));
1302 $this->t->scanOperand =
true;
1309 if (!$this->t->scanOperand)
1312 array_push($operators,
new JSNode($this->t));
1316 if ($this->t->scanOperand)
1318 array_push($operators,
new JSNode($this->t));
1323 $t = $this->t->tokens[($this->t->tokenIndex + $this->t->lookahead - 1) & 3];
1324 if (
$t &&
$t->lineno != $this->t->lineno)
1327 if (!empty($operators))
1330 while ($this->opPrecedence[end($operators)->type] > $this->opPrecedence[$tt])
1331 $this->
reduce($operators, $operands);
1334 $n =
new JSNode($this->t, $tt, array_pop($operands));
1336 array_push($operands,
$n);
1341 if (!$this->t->scanOperand)
1345 $this->t->scanOperand =
false;
1350 if (!$this->t->scanOperand)
1353 array_push($operands,
new JSNode($this->t));
1354 $this->t->scanOperand =
false;
1359 if ($this->t->scanOperand)
1360 array_push($operators,
new JSNode($this->t));
1362 array_push($operands,
new JSNode($this->t));
1366 if ($this->t->scanOperand)
1386 array_push($operands,
$n);
1387 $this->t->scanOperand =
false;
1393 $this->t->scanOperand =
true;
1399 if ($this->t->scanOperand || $x->bracketLevel == $bl)
1409 if (!$this->t->scanOperand)
1420 $tt = $this->t->get();
1421 $tv = $this->t->currentToken()->value;
1422 if (($tv ==
'get' || $tv ==
'set') && $this->t->peek() ==
TOKEN_IDENTIFIER)
1424 if ($x->ecmaStrictMode)
1425 throw $this->t->newSyntaxError(
'Illegal property accessor');
1436 $id =
new JSNode($this->t);
1440 if ($x->ecmaStrictMode)
1441 throw $this->t->newSyntaxError(
'Illegal trailing ,');
1445 throw $this->t->newSyntaxError(
'Invalid property name');
1458 array_push($operands,
$n);
1459 $this->t->scanOperand =
false;
1464 if (!$this->t->scanOperand && $x->curlyLevel != $cl)
1465 throw new Exception(
'PANIC: right curly botch');
1469 if ($this->t->scanOperand)
1475 while ( !empty($operators) &&
1476 $this->opPrecedence[end($operators)->
type] > $this->opPrecedence[
KEYWORD_NEW]
1478 $this->
reduce($operators, $operands);
1483 $n = end($operators);
1484 $this->t->scanOperand =
true;
1489 array_pop($operators);
1490 $n->addNode(array_pop($operands));
1497 array_push($operands,
$n);
1498 $this->t->scanOperand =
false;
1512 if ($this->t->scanOperand || $x->parenLevel == $pl)
1524 $n = end($operands);
1542 if ($x->hookLevel != $hl)
1543 throw $this->t->newSyntaxError(
'Missing : in conditional expression');
1545 if ($x->parenLevel != $pl)
1546 throw $this->t->newSyntaxError(
'Missing ) in parenthetical');
1548 if ($x->bracketLevel != $bl)
1549 throw $this->t->newSyntaxError(
'Missing ] in index expression');
1551 if ($this->t->scanOperand)
1552 throw $this->t->newSyntaxError(
'Missing operand');
1555 $this->t->scanOperand =
true;
1558 while (count($operators))
1559 $this->
reduce($operators, $operands);
1561 return array_pop($operands);
1574 private function nest($x, $node, $end =
false)
1576 array_push($x->stmtStack, $node);
1577 $n = $this->statement($x);
1578 array_pop($x->stmtStack);
1581 $this->t->mustMatch($end);
1586 private function reduce(&$operators, &$operands)
1588 $n = array_pop($operators);
1590 $arity = $this->opArity[$op];
1591 $c = count($operands);
1597 $left = $operands[$c - 2];
1598 if ($left->type == $op)
1600 $right = array_pop($operands);
1609 $a = array_splice($operands, $c - $arity);
1610 for ($i = 0; $i < $arity; $i++)
1611 $n->addNode($a[$i]);
1614 $te = $this->t->currentToken()->end;
1618 array_push($operands,
$n);
1658 if ($token =
$t->currentToken())
1661 $this->value = $token->value;
1662 $this->lineno = $token->lineno;
1663 $this->
start = $token->start;
1664 $this->end = $token->end;
1669 $this->lineno =
$t->lineno;
1672 if (($numargs = func_num_args()) > 2)
1674 $args = func_get_args();
1675 for ($i = 2; $i < $numargs; $i++)
1688 if (isset($this->
$name))
1689 return $this->$name;
1698 if ($node->start < $this->start)
1699 $this->
start = $node->start;
1700 if ($this->end < $node->end)
1701 $this->end = $node->end;
1704 $this->treeNodes[] = $node;
1724 'case',
'catch',
'const',
'continue',
1725 'debugger',
'default',
'delete',
'do',
1727 'false',
'finally',
'for',
'function',
1728 'if',
'in',
'instanceof',
1732 'this',
'throw',
'true',
'try',
'typeof',
1738 ';',
',',
'?',
':',
'||',
'&&',
'|',
'^',
1739 '&',
'===',
'==',
'=',
'!==',
'!=',
'<<',
'<=',
1740 '<',
'>>>',
'>>',
'>=',
'>',
'++',
'--',
'+',
1741 '-',
'*',
'/',
'%',
'!',
'~',
'.',
'[',
1742 ']',
'{',
'}',
'(',
')',
'@*/'
1745 private $assignOps =
array(
'|',
'^',
'&',
'<<',
'>>',
'>>>',
'+',
'-',
'*',
'/',
'%');
1750 $this->opRegExp =
'#^(' . implode(
'|', array_map(
'preg_quote', $this->opTypeNames)) .
')#';
1760 $this->tokens =
array();
1761 $this->tokenIndex = 0;
1762 $this->lookahead = 0;
1763 $this->scanNewlines =
false;
1764 $this->scanOperand =
true;
1770 return substr($this->
source, $this->cursor, $chunksize);
1772 return substr($this->
source, $this->cursor);
1782 return $this->
get() == $tt || $this->
unget();
1787 if (!$this->
match($tt))
1788 throw $this->
newSyntaxError(
'Unexpected token; token ' . $tt .
' expected');
1795 if ($this->lookahead)
1798 if ($this->scanNewlines && $next->lineno != $this->lineno)
1814 $this->scanNewlines =
true;
1815 $tt = $this->
peek();
1816 $this->scanNewlines =
false;
1823 if (!empty($this->tokens))
1827 public function get($chunksize = 1000)
1829 while($this->lookahead)
1832 $this->tokenIndex = ($this->tokenIndex + 1) & 3;
1835 return $token->type;
1838 $conditional_comment =
false;
1843 $input = $this->
getInput($chunksize);
1846 $re = $this->scanNewlines ?
'/^[ \r\t]+/' :
'/^\s+/';
1847 if (preg_match($re, $input, $match))
1849 $spaces = $match[0];
1850 $spacelen = strlen($spaces);
1851 $this->cursor += $spacelen;
1852 if (!$this->scanNewlines)
1853 $this->lineno += substr_count($spaces,
"\n");
1855 if ($spacelen == $chunksize)
1858 $input = $this->
getInput($chunksize);
1859 if ($input ==
'' || $input[0] !=
'/')
1864 if (!preg_match(
'/^\/(?:\*(@(?:cc_on|if|elif|else|end))?.*?\*\/|\/[^\n]*)/s', $input, $match))
1875 if (!empty($match[1]))
1877 $match[0] =
'/*' . $match[1];
1878 $conditional_comment =
true;
1883 $this->cursor += strlen($match[0]);
1884 $this->lineno += substr_count($match[0],
"\n");
1893 elseif ($conditional_comment)
1903 if (($input[1] ==
'x' || $input[1] ==
'X') && preg_match(
'/^0x[0-9a-f]+/i', $input, $match))
1910 case '1':
case '2':
case '3':
case '4':
case '5':
1911 case '6':
case '7':
case '8':
case '9':
1913 preg_match(
'/^\d+(?:\.\d*)?(?:[eE][-+]?\d+)?/', $input, $match);
1918 if (preg_match(
'/^\'(?:[^\\\\\'\r\n]++|\\\\(?:.|\r?\n))*\'/', $input, $match))
1925 return $this->
get(
null);
1932 if (preg_match(
'/^"(?:[^\\\\"\r\n]++|\\\\(?:.|\r?\n))*"/', $input, $match))
1939 return $this->
get(
null);
1946 if ($this->scanOperand && preg_match(
'/^\/((?:\\\\.|\[(?:\\\\.|[^\]])*\]|[^\/])+)\/([gimy]*)/', $input, $match))
1965 preg_match($this->opRegExp, $input, $match);
1967 if (in_array($op, $this->assignOps) && $input[strlen($op)] ==
'=')
1975 if ($this->scanOperand)
1987 if (preg_match(
'/^\.\d+(?:[eE][-+]?\d+)?/', $input, $match))
2006 $match =
array($input[0]);
2012 if (substr($input, 0, 3) ==
'@*/')
2014 $match =
array(
'@*/');
2022 if ($this->scanNewlines)
2024 $match =
array(
"\n");
2035 if (!preg_match(
'/^[$\w]+(?=[\s\/\|\^\&<>\+\-\*%=!.;,\?:~\[\]\{\}\(\)@])/', $input, $match))
2040 $identifierStartChars =
"\\p{L}\\p{Nl}" . # UnicodeLetter
2043 $identifierPartChars = $identifierStartChars .
2044 "\\p{Mn}\\p{Mc}" . # UnicodeCombiningMark
2045 "\\p{Nd}" . # UnicodeDigit
2046 "\\p{Pc}"; # UnicodeConnectorPunctuation
2047 $unicodeEscape =
"\\\\u[0-9A-F-a-f]{4}";
2048 $identifierRegex =
"/^" .
2049 "(?:[$identifierStartChars]|$unicodeEscape)" .
2050 "(?:[$identifierPartChars]|$unicodeEscape)*" .
2052 if (preg_match($identifierRegex, $input, $match))
2054 if (strpos($match[0],
'\\') !==
false) {
2057 $decoded = preg_replace_callback(
'/\\\\u([0-9A-Fa-f]{4})/',
2058 array(__CLASS__,
'unicodeEscapeCallback'),
2063 if (!preg_match(
"/^[$identifierStartChars][$identifierPartChars]*$/u", $decoded)) {
2070 if (in_array($decoded, $this->keywords)) {
2084 $this->tokenIndex = ($this->tokenIndex + 1) & 3;
2086 if (!isset($this->tokens[$this->tokenIndex]))
2087 $this->tokens[$this->tokenIndex] =
new JSToken();
2093 $token->assignOp = $op;
2097 $token->value = $match[0];
2098 $this->cursor += strlen($match[0]);
2108 if (++$this->lookahead == 4)
2111 $this->tokenIndex = ($this->tokenIndex - 1) & 3;
2116 return new Exception(
'Parse error: ' . $m .
' in file \'' . $this->filename .
'\' on line ' . $this->lineno);
2119 public static function unicodeEscapeCallback($m)
2121 return html_entity_decode('&#x
' . $m[1]. ';
', ENT_QUOTES, 'UTF-8
');