203 self::PROPERTY_ASSIGNMENT => [
207 self::EXPRESSION => [
214 self::EXPRESSION_NO_NL => [
221 self::EXPRESSION_OP => [
230 self::EXPRESSION_FUNC => [
233 self::EXPRESSION_TERNARY => [
239 self::EXPRESSION_TERNARY_OP => [
246 self::EXPRESSION_TERNARY_FUNC => [
249 self::PAREN_EXPRESSION => [
255 self::PAREN_EXPRESSION_OP => [
264 self::PAREN_EXPRESSION_FUNC => [
267 self::PROPERTY_EXPRESSION => [
273 self::PROPERTY_EXPRESSION_OP => [
280 self::PROPERTY_EXPRESSION_FUNC => [
296 self::PROPERTY_ASSIGNMENT => [
299 self::EXPRESSION => [
303 self::EXPRESSION_NO_NL => [
307 self::EXPRESSION_OP => [
311 self::EXPRESSION_FUNC => [
314 self::EXPRESSION_TERNARY => [
318 self::EXPRESSION_TERNARY_OP => [
322 self::EXPRESSION_TERNARY_FUNC => [
325 self::PAREN_EXPRESSION => [
329 self::PAREN_EXPRESSION_OP => [
332 self::PAREN_EXPRESSION_FUNC => [
335 self::PROPERTY_EXPRESSION => [
339 self::PROPERTY_EXPRESSION_OP => [
342 self::PROPERTY_EXPRESSION_FUNC => [
349 self::STATEMENT => [ self::TYPE_BRACE_CLOSE =>
true ],
350 self::PROPERTY_ASSIGNMENT => [ self::TYPE_BRACE_CLOSE =>
true ],
351 self::EXPRESSION => [ self::TYPE_BRACE_CLOSE =>
true ],
352 self::EXPRESSION_NO_NL => [ self::TYPE_BRACE_CLOSE =>
true ],
353 self::EXPRESSION_OP => [ self::TYPE_BRACE_CLOSE =>
true ],
354 self::EXPRESSION_TERNARY_OP => [ self::TYPE_COLON =>
true ],
355 self::PAREN_EXPRESSION => [ self::TYPE_PAREN_CLOSE =>
true ],
356 self::PAREN_EXPRESSION_OP => [ self::TYPE_PAREN_CLOSE =>
true ],
357 self::PROPERTY_EXPRESSION => [ self::TYPE_BRACE_CLOSE =>
true ],
358 self::PROPERTY_EXPRESSION_OP => [ self::TYPE_BRACE_CLOSE =>
true ]
363 self::EXPRESSION_NO_NL => [
364 self::TYPE_UN_OP =>
true,
365 self::TYPE_INCR_OP =>
true,
366 self::TYPE_ADD_OP =>
true,
367 self::TYPE_BRACE_OPEN =>
true,
368 self::TYPE_PAREN_OPEN =>
true,
369 self::TYPE_RETURN =>
true,
370 self::TYPE_IF =>
true,
371 self::TYPE_DO =>
true,
372 self::TYPE_FUNC =>
true,
373 self::TYPE_LITERAL =>
true
375 self::EXPRESSION_OP => [
376 self::TYPE_UN_OP =>
true,
377 self::TYPE_INCR_OP =>
true,
378 self::TYPE_BRACE_OPEN =>
true,
379 self::TYPE_RETURN =>
true,
380 self::TYPE_IF =>
true,
381 self::TYPE_DO =>
true,
382 self::TYPE_FUNC =>
true,
383 self::TYPE_LITERAL =>
true
389 self::EXPRESSION_OP =>
true,
390 self::EXPRESSION_TERNARY_OP =>
true,
391 self::PAREN_EXPRESSION_OP =>
true,
392 self::PROPERTY_EXPRESSION_OP =>
true
399 $length = strlen(
$s );
401 $newlineFound =
true;
405 while ( $pos < $length ) {
408 $skip = strspn(
$s,
" \t\n\r\xb\xc", $pos );
411 if ( $ch ===
'/' && substr(
$s, $pos, 2 ) ===
'/*' ) {
413 $end = strpos(
$s,
'*/', $pos + 2 );
414 $skip = $end ===
false ? $length - $pos : $end - $pos + 2;
420 if ( !$newlineFound && strcspn(
$s,
"\r\n", $pos, $skip ) !== $skip ) {
421 $newlineFound =
true;
429 if ( ( $ch ===
'/' && substr(
$s, $pos, 2 ) ===
'//' )
430 || ( $ch ===
'<' && substr(
$s, $pos, 4 ) ===
'<!--' )
431 || ( $ch ===
'-' && $newlineFound && substr(
$s, $pos, 3 ) ===
'-->' )
433 $pos += strcspn(
$s,
"\r\n", $pos );
445 if ( $ch ===
"'" || $ch ===
'"' ) {
447 $search = $ch .
'\\';
453 $end += strcspn(
$s, $search, $end ) + 2;
456 }
while ( $end - 2 < $length &&
$s[$end - 2] ===
'\\' );
459 if ( $end > $length ) {
467 } elseif ( $ch ===
'/' && !isset( $divStates[$state] ) ) {
476 $end += strcspn(
$s,
'/[\\', $end ) + 2;
478 }
while ( $end - 2 < $length &&
$s[$end - 2] ===
'\\' );
481 if ( $end > $length ) {
488 if (
$s[$end - 1] ===
'/' ) {
496 $end += strcspn(
$s,
']\\', $end ) + 2;
498 }
while ( $end - 2 < $length &&
$s[$end - 2] ===
'\\' );
501 if ( $end > $length ) {
510 while ( $end < $length && ctype_alpha(
$s[$end] ) ) {
515 && ( $pos + 1 < $length ) && (
$s[$pos + 1] ===
'x' ||
$s[$pos + 1] ===
'X' )
519 $len = strspn(
$s,
'0123456789ABCDEFabcdef', $end );
524 'Expected a hexadecimal number but found ' . substr(
$s, $pos, 5 ) .
'...'
530 || ( $ch ===
'.' && $pos + 1 < $length && ctype_digit(
$s[$pos + 1] ) )
532 $end += strspn(
$s,
'0123456789', $end );
533 $decimal = strspn(
$s,
'.', $end );
535 if ( $decimal > 2 ) {
538 $end += strspn(
$s,
'0123456789', $end + 1 ) + $decimal;
540 $exponent = strspn(
$s,
'eE', $end );
542 if ( $exponent > 1 ) {
548 $end += strspn(
$s,
'-+', $end );
549 $len = strspn(
$s,
'0123456789', $end );
554 'No decimal digits after e, how many zeroes should be added?'
559 } elseif ( isset( $opChars[$ch] ) ) {
563 && isset( $tokenTypes[substr(
$s, $pos, $end - $pos + 1 )] )
570 $end += strcspn(
$s,
" \t\n.;,=<>+-{}()[]?:*/%'\"!&|^~\xb\xc\r", $end );
574 $token = substr(
$s, $pos, $end - $pos );
577 if ( $newlineFound && isset( $semicolon[$state][
$type] ) ) {
583 } elseif ( $lineLength + $end - $pos > self::MAX_LINE_LENGTH &&
584 !isset( $semicolon[$state][
$type] ) &&
$type !== self::TYPE_INCR_OP ) {
591 } elseif ( !isset( $opChars[
$last] ) && !isset( $opChars[$ch] ) ) {
595 } elseif (
$last === $ch && ( $ch ===
'+' || $ch ===
'-' || $ch ===
'/' ) ) {
600 $type === self::TYPE_LITERAL
601 && ( $token ===
'true' || $token ===
'false' )
602 && ( $state === self::EXPRESSION || $state === self::PROPERTY_EXPRESSION )
605 $token = ( $token ===
'true' ) ?
'!0' :
'!1';
609 $lineLength += $end - $pos;
612 $newlineFound =
false;
615 if ( isset( $push[$state][
$type] ) && count( $stack ) < self::STACK_LIMIT ) {
616 $stack[] = $push[$state][
$type];
618 if ( $stack && isset( $pop[$state][
$type] ) ) {
619 $state = array_pop( $stack );
620 } elseif ( isset( $goto[$state][
$type] ) ) {
621 $state = $goto[$state][
$type];