Compare commits

..

24 Commits

Author SHA1 Message Date
Nikita Popov
e612609022 Release PHP-Parser 4.2.3 2019-08-12 22:17:41 +02:00
Nikita Popov
4fd36b9946 Fix compatibility with T_BAD_CHARACTER in PHP 7.4 2019-08-12 22:10:02 +02:00
Tyson Andre
a1f72690ef Fix harmless typos in documentation 2019-07-23 12:32:37 +02:00
Tyson Andre
2e2954ccdf Avoid notices in php 7.4 with hexdec/base_convert (#619)
This is made to avoid notices caused by
https://wiki.php.net/rfc/base_convert_improvements

(seen with `php -d error_reporting=E_ALL vendor/bin/phpunit`)
2019-07-14 10:56:13 +02:00
Tomáš Votruba
3f718ee2c3 [PHP 7.4] Add support for numeric literal separators (#615)
Implements RFC https://wiki.php.net/rfc/numeric_literal_separator.

Closes #614.
2019-06-30 12:13:28 +02:00
Nikita Popov
b9b45dd2bc Insert T_BAD_CHARACTER tokens for missing characters
The token stream should cover all characters in the original code,
insert a dummy token for missing illegal characters. We should
really be doing this in token_get_all() as well.
2019-06-30 11:43:48 +02:00
Chris Hewitt
a4b43edb03 Fix one-character inconsistency 2019-06-30 09:25:26 +02:00
Nikita Popov
3cf61fdd26 Only ignore-platform-reqs on nightly 2019-06-23 15:11:05 +02:00
Nikita Popov
9484baf8f8 Make compatible with PhpUnit 8 2019-06-23 15:03:40 +02:00
Nikita Popov
aad0e2896f Remove token registration from TokenEmulator interface 2019-06-23 14:50:14 +02:00
hoels
624f71fa6f Resolve return type of arrow functions (#613) 2019-06-04 16:25:12 +02:00
Nikita Popov
1bd73cc04c Release PHP-Parser 4.2.2 2019-05-25 22:07:01 +02:00
Nikita Popov
94d93f27a5 Revert "Recover from error inside alternative array deref syntax"
This reverts commit 9d44edf85d.
2019-05-24 22:58:13 +02:00
Nikita Popov
a167aa2061 Optimize attribue checks in the lexer 2019-05-12 15:26:26 +02:00
Nikita Popov
993f29906b Avoid parent constructor call during node construction
Instead explicitly assign the attributes. This is a minor
performance improvement.
2019-05-12 14:55:21 +02:00
Nikita Popov
9d44edf85d Recover from error inside alternative array deref syntax
This is to improve error recovery for cases like #545.
2019-05-12 11:38:15 +02:00
Nikita Popov
aa97a9bb69 Add changelog entries 2019-05-11 23:08:31 +02:00
Nikita Popov
aa72c5d674 FPPP: Support inserting into empty lists 2019-05-11 22:49:32 +02:00
Nikita Popov
60d025a914 Fix attributes for zero-length nop nodes
Previously zero-length nop nodes used the lookahead start attributes
and current end attributes. This choice ends up being somewhat weird,
because the end attributes will be the at the last non-whitespace,
non-comment token, which might be quite far back. More problematically,
we may not have encountered any non-discarded token if we're at the
start of the file, in which case we will have no end attributes to
assign.

Change things to use a canonical "zero-length" node representation,
where the end position (token & file) will be exactly one before the
start position.

Fixes #589.
2019-05-11 20:01:25 +02:00
Nikita Popov
b2cecec6bc Remove bogus exprStmt mode test
We're always generating expression statements nowadays, this flag
hasn't existed for a long while now...
2019-05-11 18:51:37 +02:00
Tomas Votruba
8012faea54 [PHP 7.4] Add array spread 2019-05-09 19:15:35 +02:00
Tomáš Votruba
f3b19c19ef [PHP 7.4] Add support for arrow functions (#602)
Per RFC https://wiki.php.net/rfc/arrow_functions_v2.
2019-05-09 14:17:28 +02:00
Andrea Cardaci
78d9985d11 Print messages to stderr in bin/php-parse and fix exit status
Close #605.
2019-04-28 22:06:06 +02:00
Nikita Popov
57b8673ea7 Use --ignore-platform-reqs on Travis
Allows testing on nightly, which is PHP 8.
2019-02-16 21:58:22 +01:00
159 changed files with 4603 additions and 2966 deletions

View File

@@ -16,7 +16,12 @@ php:
install: install:
- if [ $TRAVIS_PHP_VERSION = '7.0' ]; then composer require satooshi/php-coveralls '~1.0'; fi - if [ $TRAVIS_PHP_VERSION = '7.0' ]; then composer require satooshi/php-coveralls '~1.0'; fi
- composer install --prefer-dist - |
if [ $TRAVIS_PHP_VERSION = 'nightly' ]; then
composer install --prefer-dist --ignore-platform-reqs;
else
composer install --prefer-dist;
fi
matrix: matrix:
allow_failures: allow_failures:

View File

@@ -1,8 +1,39 @@
Version 4.2.2-dev Version 4.2.4-dev
----------------- -----------------
Nothing yet. Nothing yet.
Version 4.2.3 (2019-08-12)
--------------------------
### Added
* [PHP 7.4] Add support for numeric literal separators. (#615)
### Fixed
* Fixed resolution of return types for arrow functions. (#613)
* Fixed compatibility with PHP 7.4.
Version 4.2.2 (2019-05-25)
--------------------------
### Added
* [PHP 7.4] Add support for arrow functions using a new `Expr\ArrowFunction` node. (#602)
* [PHP 7.4] Add support for array spreads, using a new `unpack` subnode on `ArrayItem`. (#609)
* Added support for inserting into empty list nodes in the formatting preserving pretty printer.
### Changed
* `php-parse` will now print messages to stderr, so that stdout only contains the actual result of
the operation (such as a JSON dump). (#605)
### Fixed
* Fixed attribute assignment for zero-length nop statements, and a related assertion failure in
the formatting-preserving pretty printer. (#589)
Version 4.2.1 (2019-02-16) Version 4.2.1 (2019-02-16)
-------------------------- --------------------------

View File

@@ -3,10 +3,10 @@ PHP Parser
[![Build Status](https://travis-ci.org/nikic/PHP-Parser.svg?branch=master)](https://travis-ci.org/nikic/PHP-Parser) [![Coverage Status](https://coveralls.io/repos/github/nikic/PHP-Parser/badge.svg?branch=master)](https://coveralls.io/github/nikic/PHP-Parser?branch=master) [![Build Status](https://travis-ci.org/nikic/PHP-Parser.svg?branch=master)](https://travis-ci.org/nikic/PHP-Parser) [![Coverage Status](https://coveralls.io/repos/github/nikic/PHP-Parser/badge.svg?branch=master)](https://coveralls.io/github/nikic/PHP-Parser?branch=master)
This is a PHP 5.2 to PHP 7.3 parser written in PHP. Its purpose is to simplify static code analysis and This is a PHP 5.2 to PHP 7.4 parser written in PHP. Its purpose is to simplify static code analysis and
manipulation. manipulation.
[**Documentation for version 4.x**][doc_master] (stable; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 7.3). [**Documentation for version 4.x**][doc_master] (stable; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 7.4).
[Documentation for version 3.x][doc_3_x] (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2). [Documentation for version 3.x][doc_3_x] (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2).

View File

@@ -45,14 +45,15 @@ $traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver);
foreach ($files as $file) { foreach ($files as $file) {
if (strpos($file, '<?php') === 0) { if (strpos($file, '<?php') === 0) {
$code = $file; $code = $file;
echo "====> Code $code\n"; fwrite(STDERR, "====> Code $code\n");
} else { } else {
if (!file_exists($file)) { if (!file_exists($file)) {
die("File $file does not exist.\n"); fwrite(STDERR, "File $file does not exist.\n");
exit(1);
} }
$code = file_get_contents($file); $code = file_get_contents($file);
echo "====> File $file:\n"; fwrite(STDERR, "====> File $file:\n");
} }
if ($attributes['with-recovery']) { if ($attributes['with-recovery']) {
@@ -60,7 +61,7 @@ foreach ($files as $file) {
$stmts = $parser->parse($code, $errorHandler); $stmts = $parser->parse($code, $errorHandler);
foreach ($errorHandler->getErrors() as $error) { foreach ($errorHandler->getErrors() as $error) {
$message = formatErrorMessage($error, $code, $attributes['with-column-info']); $message = formatErrorMessage($error, $code, $attributes['with-column-info']);
echo $message . "\n"; fwrite(STDERR, $message . "\n");
} }
if (null === $stmts) { if (null === $stmts) {
continue; continue;
@@ -70,25 +71,26 @@ foreach ($files as $file) {
$stmts = $parser->parse($code); $stmts = $parser->parse($code);
} catch (PhpParser\Error $error) { } catch (PhpParser\Error $error) {
$message = formatErrorMessage($error, $code, $attributes['with-column-info']); $message = formatErrorMessage($error, $code, $attributes['with-column-info']);
die($message . "\n"); fwrite(STDERR, $message . "\n");
exit(1);
} }
} }
foreach ($operations as $operation) { foreach ($operations as $operation) {
if ('dump' === $operation) { if ('dump' === $operation) {
echo "==> Node dump:\n"; fwrite(STDERR, "==> Node dump:\n");
echo $dumper->dump($stmts, $code), "\n"; echo $dumper->dump($stmts, $code), "\n";
} elseif ('pretty-print' === $operation) { } elseif ('pretty-print' === $operation) {
echo "==> Pretty print:\n"; fwrite(STDERR, "==> Pretty print:\n");
echo $prettyPrinter->prettyPrintFile($stmts), "\n"; echo $prettyPrinter->prettyPrintFile($stmts), "\n";
} elseif ('json-dump' === $operation) { } elseif ('json-dump' === $operation) {
echo "==> JSON dump:\n"; fwrite(STDERR, "==> JSON dump:\n");
echo json_encode($stmts, JSON_PRETTY_PRINT), "\n"; echo json_encode($stmts, JSON_PRETTY_PRINT), "\n";
} elseif ('var-dump' === $operation) { } elseif ('var-dump' === $operation) {
echo "==> var_dump():\n"; fwrite(STDERR, "==> var_dump():\n");
var_dump($stmts); var_dump($stmts);
} elseif ('resolve-names' === $operation) { } elseif ('resolve-names' === $operation) {
echo "==> Resolved names.\n"; fwrite(STDERR, "==> Resolved names.\n");
$stmts = $traverser->traverse($stmts); $stmts = $traverser->traverse($stmts);
} }
} }
@@ -104,9 +106,9 @@ function formatErrorMessage(PhpParser\Error $e, $code, $withColumnInfo) {
function showHelp($error = '') { function showHelp($error = '') {
if ($error) { if ($error) {
echo $error . "\n\n"; fwrite(STDERR, $error . "\n\n");
} }
die(<<<OUTPUT fwrite($error ? STDERR : STDOUT, <<<OUTPUT
Usage: php-parse [operations] file1.php [file2.php ...] Usage: php-parse [operations] file1.php [file2.php ...]
or: php-parse [operations] "<?php code" or: php-parse [operations] "<?php code"
Turn PHP source code into an abstract syntax tree. Turn PHP source code into an abstract syntax tree.
@@ -131,6 +133,7 @@ Example:
OUTPUT OUTPUT
); );
exit($error ? 1 : 0);
} }
function parseArgs($args) { function parseArgs($args) {

View File

@@ -17,7 +17,7 @@
"ext-tokenizer": "*" "ext-tokenizer": "*"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.5 || ^7.0" "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0"
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {

View File

@@ -1,7 +1,7 @@
Introduction Introduction
============ ============
This project is a PHP 5.2 to PHP 7.3 parser **written in PHP itself**. This project is a PHP 5.2 to PHP 7.4 parser **written in PHP itself**.
What is this for? What is this for?
----------------- -----------------
@@ -26,11 +26,11 @@ programmatic PHP code analysis are incidentally PHP developers, not C developers
What can it parse? What can it parse?
------------------ ------------------
The parser supports parsing PHP 5.2-7.3. The parser supports parsing PHP 5.2-7.4.
As the parser is based on the tokens returned by `token_get_all` (which is only able to lex the PHP As the parser is based on the tokens returned by `token_get_all` (which is only able to lex the PHP
version it runs on), additionally a wrapper for emulating tokens from newer versions is provided. version it runs on), additionally a wrapper for emulating tokens from newer versions is provided.
This allows to parse PHP 7.3 source code running on PHP 7.0, for example. This emulation is somewhat This allows to parse PHP 7.4 source code running on PHP 7.0, for example. This emulation is somewhat
hacky and not perfect, but it should work well on any sane code. hacky and not perfect, but it should work well on any sane code.
What output does it produce? What output does it produce?
@@ -56,7 +56,7 @@ array(
``` ```
This matches the structure of the code: An echo statement, which takes two strings as expressions, This matches the structure of the code: An echo statement, which takes two strings as expressions,
with the values `Hi` and `World!`. with the values `Hi` and `World`.
You can also see that the AST does not contain any whitespace information (but most comments are saved). You can also see that the AST does not contain any whitespace information (but most comments are saved).
So using it for formatting analysis is not possible. So using it for formatting analysis is not possible.

View File

@@ -77,7 +77,7 @@ A parser instance can be reused to parse multiple files.
Node dumping Node dumping
------------ ------------
To dump the abstact syntax tree in human readable form, a `NodeDumper` can be used: To dump the abstract syntax tree in human readable form, a `NodeDumper` can be used:
```php ```php
<?php <?php

View File

@@ -312,7 +312,7 @@ $extendingClasses = $nodeFinder->find($stmts, function(Node $node) {
&& $node->extends !== null; && $node->extends !== null;
}); });
// Find first class occuring in the AST. Returns null if no class exists. // Find first class occurring in the AST. Returns null if no class exists.
$class = $nodeFinder->findFirstInstanceOf($stmts, Node\Stmt\Class_::class); $class = $nodeFinder->findFirstInstanceOf($stmts, Node\Stmt\Class_::class);
// Find first class that has name $name // Find first class that has name $name

View File

@@ -16,7 +16,7 @@ top_statement_list_ex:
top_statement_list: top_statement_list:
top_statement_list_ex top_statement_list_ex
{ makeNop($nop, $this->lookaheadStartAttributes, $this->endAttributes); { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
if ($nop !== null) { $1[] = $nop; } $$ = $1; } if ($nop !== null) { $1[] = $nop; } $$ = $1; }
; ;
@@ -27,7 +27,7 @@ reserved_non_modifiers:
| T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO
| T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT
| T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS
| T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN
; ;
semi_reserved: semi_reserved:
@@ -160,7 +160,7 @@ inner_statement_list_ex:
inner_statement_list: inner_statement_list:
inner_statement_list_ex inner_statement_list_ex
{ makeNop($nop, $this->lookaheadStartAttributes, $this->endAttributes); { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
if ($nop !== null) { $1[] = $nop; } $$ = $1; } if ($nop !== null) { $1[] = $nop; } $$ = $1; }
; ;
@@ -461,7 +461,7 @@ class_statement_list_ex:
class_statement_list: class_statement_list:
class_statement_list_ex class_statement_list_ex
{ makeNop($nop, $this->lookaheadStartAttributes, $this->endAttributes); { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
if ($nop !== null) { $1[] = $nop; } $$ = $1; } if ($nop !== null) { $1[] = $nop; } $$ = $1; }
; ;
@@ -988,6 +988,7 @@ array_pair:
| expr { $$ = Expr\ArrayItem[$1, null, false]; } | expr { $$ = Expr\ArrayItem[$1, null, false]; }
| expr T_DOUBLE_ARROW '&' variable { $$ = Expr\ArrayItem[$4, $1, true]; } | expr T_DOUBLE_ARROW '&' variable { $$ = Expr\ArrayItem[$4, $1, true]; }
| '&' variable { $$ = Expr\ArrayItem[$2, null, true]; } | '&' variable { $$ = Expr\ArrayItem[$2, null, true]; }
| T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; }
; ;
encaps_list: encaps_list:

View File

@@ -16,7 +16,7 @@ top_statement_list_ex:
top_statement_list: top_statement_list:
top_statement_list_ex top_statement_list_ex
{ makeNop($nop, $this->lookaheadStartAttributes, $this->endAttributes); { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
if ($nop !== null) { $1[] = $nop; } $$ = $1; } if ($nop !== null) { $1[] = $nop; } $$ = $1; }
; ;
@@ -27,7 +27,7 @@ reserved_non_modifiers:
| T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO
| T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT
| T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS
| T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN
; ;
semi_reserved: semi_reserved:
@@ -196,7 +196,7 @@ inner_statement_list_ex:
inner_statement_list: inner_statement_list:
inner_statement_list_ex inner_statement_list_ex
{ makeNop($nop, $this->lookaheadStartAttributes, $this->endAttributes); { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
if ($nop !== null) { $1[] = $nop; } $$ = $1; } if ($nop !== null) { $1[] = $nop; } $$ = $1; }
; ;
@@ -530,7 +530,7 @@ class_statement_list_ex:
class_statement_list: class_statement_list:
class_statement_list_ex class_statement_list_ex
{ makeNop($nop, $this->lookaheadStartAttributes, $this->endAttributes); { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
if ($nop !== null) { $1[] = $nop; } $$ = $1; } if ($nop !== null) { $1[] = $nop; } $$ = $1; }
; ;
@@ -729,6 +729,12 @@ expr:
| T_YIELD expr { $$ = Expr\Yield_[$2, null]; } | T_YIELD expr { $$ = Expr\Yield_[$2, null]; }
| T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; }
| T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; }
| T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr
{ $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $2, 'params' => $4, 'returnType' => $6, 'expr' => $8]]; }
| T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr
{ $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9]]; }
| T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type
block_or_error block_or_error
{ $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $8]]; } { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $8]]; }
@@ -977,6 +983,7 @@ array_pair:
| expr { $$ = Expr\ArrayItem[$1, null, false]; } | expr { $$ = Expr\ArrayItem[$1, null, false]; }
| expr T_DOUBLE_ARROW '&' variable { $$ = Expr\ArrayItem[$4, $1, true]; } | expr T_DOUBLE_ARROW '&' variable { $$ = Expr\ArrayItem[$4, $1, true]; }
| '&' variable { $$ = Expr\ArrayItem[$2, null, true]; } | '&' variable { $$ = Expr\ArrayItem[$2, null, true]; }
| T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; }
| /* empty */ { $$ = null; } | /* empty */ { $$ = null; }
; ;

View File

@@ -13,9 +13,12 @@ $tmpResultFile = __DIR__ . '/tmp_parser.php';
$resultDir = __DIR__ . '/../lib/PhpParser/Parser'; $resultDir = __DIR__ . '/../lib/PhpParser/Parser';
$tokensResultsFile = $resultDir . '/Tokens.php'; $tokensResultsFile = $resultDir . '/Tokens.php';
// check for kmyacc.exe binary in this directory, otherwise fall back to global name // check for kmyacc binary in this directory, otherwise fall back to global name
if (file_exists(__DIR__ . '/kmyacc.exe')) {
$kmyacc = __DIR__ . '/kmyacc.exe'; $kmyacc = __DIR__ . '/kmyacc.exe';
if (!file_exists($kmyacc)) { } else if (file_exists(__DIR__ . '/kmyacc')) {
$kmyacc = __DIR__ . '/kmyacc';
} else {
$kmyacc = 'kmyacc'; $kmyacc = 'kmyacc';
} }
@@ -175,6 +178,15 @@ function resolveMacros($code) {
. ' else { ' . $args[0] . ' = null; }'; . ' else { ' . $args[0] . ' = null; }';
} }
if ('makeZeroLengthNop' == $name) {
assertArgs(2, $args, $name);
return '$startAttributes = ' . $args[1] . ';'
. ' if (isset($startAttributes[\'comments\']))'
. ' { ' . $args[0] . ' = new Stmt\Nop($this->createZeroLengthAttributes($startAttributes)); }'
. ' else { ' . $args[0] . ' = null; }';
}
if ('strKind' == $name) { if ('strKind' == $name) {
assertArgs(1, $args, $name); assertArgs(1, $args, $name);

View File

@@ -64,6 +64,7 @@
%token T_CONTINUE %token T_CONTINUE
%token T_GOTO %token T_GOTO
%token T_FUNCTION %token T_FUNCTION
%token T_FN
%token T_CONST %token T_CONST
%token T_RETURN %token T_RETURN
%token T_TRY %token T_TRY

View File

@@ -16,7 +16,13 @@ class Lexer
protected $tokenMap; protected $tokenMap;
protected $dropTokens; protected $dropTokens;
protected $usedAttributes; private $attributeStartLineUsed;
private $attributeEndLineUsed;
private $attributeStartTokenPosUsed;
private $attributeEndTokenPosUsed;
private $attributeStartFilePosUsed;
private $attributeEndFilePosUsed;
private $attributeCommentsUsed;
/** /**
* Creates a Lexer. * Creates a Lexer.
@@ -31,18 +37,28 @@ class Lexer
// map from internal tokens to PhpParser tokens // map from internal tokens to PhpParser tokens
$this->tokenMap = $this->createTokenMap(); $this->tokenMap = $this->createTokenMap();
// Compatibility define for PHP < 7.4
if (!defined('T_BAD_CHARACTER')) {
\define('T_BAD_CHARACTER', -1);
}
// map of tokens to drop while lexing (the map is only used for isset lookup, // map of tokens to drop while lexing (the map is only used for isset lookup,
// that's why the value is simply set to 1; the value is never actually used.) // that's why the value is simply set to 1; the value is never actually used.)
$this->dropTokens = array_fill_keys( $this->dropTokens = array_fill_keys(
[\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT], 1 [\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT, \T_BAD_CHARACTER], 1
); );
// the usedAttributes member is a map of the used attribute names to a dummy $defaultAttributes = ['comments', 'startLine', 'endLine'];
// value (here "true") $usedAttributes = array_fill_keys($options['usedAttributes'] ?? $defaultAttributes, true);
$options += [
'usedAttributes' => ['comments', 'startLine', 'endLine'], // Create individual boolean properties to make these checks faster.
]; $this->attributeStartLineUsed = isset($usedAttributes['startLine']);
$this->usedAttributes = array_fill_keys($options['usedAttributes'], true); $this->attributeEndLineUsed = isset($usedAttributes['endLine']);
$this->attributeStartTokenPosUsed = isset($usedAttributes['startTokenPos']);
$this->attributeEndTokenPosUsed = isset($usedAttributes['endTokenPos']);
$this->attributeStartFilePosUsed = isset($usedAttributes['startFilePos']);
$this->attributeEndFilePosUsed = isset($usedAttributes['endFilePos']);
$this->attributeCommentsUsed = isset($usedAttributes['comments']);
} }
/** /**
@@ -81,13 +97,9 @@ class Lexer
} }
private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler) { private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler) {
$tokens = [];
for ($i = $start; $i < $end; $i++) { for ($i = $start; $i < $end; $i++) {
$chr = $this->code[$i]; $chr = $this->code[$i];
if ($chr === 'b' || $chr === 'B') {
// HHVM does not treat b" tokens correctly, so ignore these
continue;
}
if ($chr === "\0") { if ($chr === "\0") {
// PHP cuts error message after null byte, so need special case // PHP cuts error message after null byte, so need special case
$errorMsg = 'Unexpected null byte'; $errorMsg = 'Unexpected null byte';
@@ -97,6 +109,7 @@ class Lexer
); );
} }
$tokens[] = [\T_BAD_CHARACTER, $chr, $line];
$errorHandler->handleError(new Error($errorMsg, [ $errorHandler->handleError(new Error($errorMsg, [
'startLine' => $line, 'startLine' => $line,
'endLine' => $line, 'endLine' => $line,
@@ -104,6 +117,7 @@ class Lexer
'endFilePos' => $i, 'endFilePos' => $i,
])); ]));
} }
return $tokens;
} }
/** /**
@@ -144,16 +158,29 @@ class Lexer
$filePos = 0; $filePos = 0;
$line = 1; $line = 1;
foreach ($this->tokens as $token) { $numTokens = \count($this->tokens);
for ($i = 0; $i < $numTokens; $i++) {
$token = $this->tokens[$i];
// Since PHP 7.4 invalid characters are represented by a T_BAD_CHARACTER token.
// In this case we only need to emit an error.
if ($token[0] === \T_BAD_CHARACTER) {
$this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler);
}
$tokenValue = \is_string($token) ? $token : $token[1]; $tokenValue = \is_string($token) ? $token : $token[1];
$tokenLen = \strlen($tokenValue); $tokenLen = \strlen($tokenValue);
if (substr($this->code, $filePos, $tokenLen) !== $tokenValue) { if (substr($this->code, $filePos, $tokenLen) !== $tokenValue) {
// Something is missing, must be an invalid character // Something is missing, must be an invalid character
$nextFilePos = strpos($this->code, $tokenValue, $filePos); $nextFilePos = strpos($this->code, $tokenValue, $filePos);
$this->handleInvalidCharacterRange( $badCharTokens = $this->handleInvalidCharacterRange(
$filePos, $nextFilePos, $line, $errorHandler); $filePos, $nextFilePos, $line, $errorHandler);
$filePos = (int) $nextFilePos; $filePos = (int) $nextFilePos;
array_splice($this->tokens, $i, 0, $badCharTokens);
$numTokens += \count($badCharTokens);
$i += \count($badCharTokens);
} }
$filePos += $tokenLen; $filePos += $tokenLen;
@@ -176,8 +203,9 @@ class Lexer
$this->tokens[] = [$isDocComment ? \T_DOC_COMMENT : \T_COMMENT, $comment, $line]; $this->tokens[] = [$isDocComment ? \T_DOC_COMMENT : \T_COMMENT, $comment, $line];
} else { } else {
// Invalid characters at the end of the input // Invalid characters at the end of the input
$this->handleInvalidCharacterRange( $badCharTokens = $this->handleInvalidCharacterRange(
$filePos, \strlen($this->code), $line, $errorHandler); $filePos, \strlen($this->code), $line, $errorHandler);
$this->tokens = array_merge($this->tokens, $badCharTokens);
} }
return; return;
} }
@@ -230,13 +258,13 @@ class Lexer
$token = "\0"; $token = "\0";
} }
if (isset($this->usedAttributes['startLine'])) { if ($this->attributeStartLineUsed) {
$startAttributes['startLine'] = $this->line; $startAttributes['startLine'] = $this->line;
} }
if (isset($this->usedAttributes['startTokenPos'])) { if ($this->attributeStartTokenPosUsed) {
$startAttributes['startTokenPos'] = $this->pos; $startAttributes['startTokenPos'] = $this->pos;
} }
if (isset($this->usedAttributes['startFilePos'])) { if ($this->attributeStartFilePosUsed) {
$startAttributes['startFilePos'] = $this->filePos; $startAttributes['startFilePos'] = $this->filePos;
} }
@@ -263,7 +291,7 @@ class Lexer
$this->filePos += \strlen($value); $this->filePos += \strlen($value);
} else { } else {
if (\T_COMMENT === $token[0] || \T_DOC_COMMENT === $token[0]) { if (\T_COMMENT === $token[0] || \T_DOC_COMMENT === $token[0]) {
if (isset($this->usedAttributes['comments'])) { if ($this->attributeCommentsUsed) {
$comment = \T_DOC_COMMENT === $token[0] $comment = \T_DOC_COMMENT === $token[0]
? new Comment\Doc($token[1], $this->line, $this->filePos, $this->pos) ? new Comment\Doc($token[1], $this->line, $this->filePos, $this->pos)
: new Comment($token[1], $this->line, $this->filePos, $this->pos); : new Comment($token[1], $this->line, $this->filePos, $this->pos);
@@ -276,13 +304,13 @@ class Lexer
continue; continue;
} }
if (isset($this->usedAttributes['endLine'])) { if ($this->attributeEndLineUsed) {
$endAttributes['endLine'] = $this->line; $endAttributes['endLine'] = $this->line;
} }
if (isset($this->usedAttributes['endTokenPos'])) { if ($this->attributeEndTokenPosUsed) {
$endAttributes['endTokenPos'] = $this->pos; $endAttributes['endTokenPos'] = $this->pos;
} }
if (isset($this->usedAttributes['endFilePos'])) { if ($this->attributeEndFilePosUsed) {
$endAttributes['endFilePos'] = $this->filePos - 1; $endAttributes['endFilePos'] = $this->filePos - 1;
} }

View File

@@ -4,26 +4,33 @@ namespace PhpParser\Lexer;
use PhpParser\Error; use PhpParser\Error;
use PhpParser\ErrorHandler; use PhpParser\ErrorHandler;
use PhpParser\Parser; use PhpParser\Lexer;
use PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator;
use PhpParser\Lexer\TokenEmulator\FnTokenEmulator;
use PhpParser\Lexer\TokenEmulator\NumericLiteralSeparatorEmulator;
use PhpParser\Lexer\TokenEmulator\TokenEmulatorInterface;
use PhpParser\Parser\Tokens;
class Emulative extends \PhpParser\Lexer class Emulative extends Lexer
{ {
const PHP_7_3 = '7.3.0dev'; const PHP_7_3 = '7.3.0dev';
const PHP_7_4 = '7.4.0dev'; const PHP_7_4 = '7.4.0dev';
const T_COALESCE_EQUAL = 1007;
const T_FN = 1008;
const FLEXIBLE_DOC_STRING_REGEX = <<<'REGEX' const FLEXIBLE_DOC_STRING_REGEX = <<<'REGEX'
/<<<[ \t]*(['"]?)([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\1\r?\n /<<<[ \t]*(['"]?)([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\1\r?\n
(?:.*\r?\n)*? (?:.*\r?\n)*?
(?<indentation>\h*)\2(?![a-zA-Z_\x80-\xff])(?<separator>(?:;?[\r\n])?)/x (?<indentation>\h*)\2(?![a-zA-Z_\x80-\xff])(?<separator>(?:;?[\r\n])?)/x
REGEX; REGEX;
const T_COALESCE_EQUAL = 1007; /** @var mixed[] Patches used to reverse changes introduced in the code */
/**
* @var mixed[] Patches used to reverse changes introduced in the code
*/
private $patches = []; private $patches = [];
/** @var TokenEmulatorInterface[] */
private $tokenEmulators = [];
/** /**
* @param mixed[] $options * @param mixed[] $options
*/ */
@@ -31,8 +38,12 @@ REGEX;
{ {
parent::__construct($options); parent::__construct($options);
// add emulated tokens here $this->tokenEmulators[] = new FnTokenEmulator();
$this->tokenMap[self::T_COALESCE_EQUAL] = Parser\Tokens::T_COALESCE_EQUAL; $this->tokenEmulators[] = new CoaleseEqualTokenEmulator();
$this->tokenEmulators[] = new NumericLiteralSeparatorEmulator();
$this->tokenMap[self::T_COALESCE_EQUAL] = Tokens::T_COALESCE_EQUAL;
$this->tokenMap[self::T_FN] = Tokens::T_FN;
} }
public function startLexing(string $code, ErrorHandler $errorHandler = null) { public function startLexing(string $code, ErrorHandler $errorHandler = null) {
@@ -49,9 +60,6 @@ REGEX;
// 1. emulation of heredoc and nowdoc new syntax // 1. emulation of heredoc and nowdoc new syntax
$preparedCode = $this->processHeredocNowdoc($code); $preparedCode = $this->processHeredocNowdoc($code);
parent::startLexing($preparedCode, $collector); parent::startLexing($preparedCode, $collector);
// 2. emulation of ??= token
$this->processCoaleseEqual($code);
$this->fixupTokens(); $this->fixupTokens();
$errors = $collector->getErrors(); $errors = $collector->getErrors();
@@ -61,39 +69,11 @@ REGEX;
$errorHandler->handleError($error); $errorHandler->handleError($error);
} }
} }
}
private function isCoalesceEqualEmulationNeeded(string $code): bool // add token emulation
{ foreach ($this->tokenEmulators as $emulativeToken) {
// skip version where this works without emulation if ($emulativeToken->isEmulationNeeded($code)) {
if (version_compare(\PHP_VERSION, self::PHP_7_4, '>=')) { $this->tokens = $emulativeToken->emulate($code, $this->tokens);
return false;
}
return strpos($code, '??=') !== false;
}
private function processCoaleseEqual(string $code)
{
if ($this->isCoalesceEqualEmulationNeeded($code) === false) {
return;
}
// We need to manually iterate and manage a count because we'll change
// the tokens array on the way
$line = 1;
for ($i = 0, $c = count($this->tokens); $i < $c; ++$i) {
if (isset($this->tokens[$i + 1])) {
if ($this->tokens[$i][0] === T_COALESCE && $this->tokens[$i + 1] === '=') {
array_splice($this->tokens, $i, 2, [
[self::T_COALESCE_EQUAL, '??=', $line]
]);
$c--;
continue;
}
}
if (\is_array($this->tokens[$i])) {
$line += substr_count($this->tokens[$i][1], "\n");
} }
} }
} }
@@ -155,15 +135,13 @@ REGEX;
private function isEmulationNeeded(string $code): bool private function isEmulationNeeded(string $code): bool
{ {
if ($this->isHeredocNowdocEmulationNeeded($code)) { foreach ($this->tokenEmulators as $emulativeToken) {
if ($emulativeToken->isEmulationNeeded($code)) {
return true; return true;
} }
if ($this->isCoalesceEqualEmulationNeeded($code)) {
return true;
} }
return false; return $this->isHeredocNowdocEmulationNeeded($code);
} }
private function fixupTokens() private function fixupTokens()

View File

@@ -0,0 +1,41 @@
<?php declare(strict_types=1);
namespace PhpParser\Lexer\TokenEmulator;
use PhpParser\Lexer\Emulative;
final class CoaleseEqualTokenEmulator implements TokenEmulatorInterface
{
public function isEmulationNeeded(string $code) : bool
{
// skip version where this is supported
if (version_compare(\PHP_VERSION, Emulative::PHP_7_4, '>=')) {
return false;
}
return strpos($code, '??=') !== false;
}
public function emulate(string $code, array $tokens): array
{
// We need to manually iterate and manage a count because we'll change
// the tokens array on the way
$line = 1;
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
if (isset($tokens[$i + 1])) {
if ($tokens[$i][0] === T_COALESCE && $tokens[$i + 1] === '=') {
array_splice($tokens, $i, 2, [
[Emulative::T_COALESCE_EQUAL, '??=', $line]
]);
$c--;
continue;
}
}
if (\is_array($tokens[$i])) {
$line += substr_count($tokens[$i][1], "\n");
}
}
return $tokens;
}
}

View File

@@ -0,0 +1,53 @@
<?php declare(strict_types=1);
namespace PhpParser\Lexer\TokenEmulator;
use PhpParser\Lexer\Emulative;
final class FnTokenEmulator implements TokenEmulatorInterface
{
public function isEmulationNeeded(string $code) : bool
{
// skip version where this is supported
if (version_compare(\PHP_VERSION, Emulative::PHP_7_4, '>=')) {
return false;
}
return strpos($code, 'fn') !== false;
}
public function emulate(string $code, array $tokens): array
{
// We need to manually iterate and manage a count because we'll change
// the tokens array on the way
foreach ($tokens as $i => $token) {
if ($token[0] === T_STRING && $token[1] === 'fn') {
$previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $i);
if ($previousNonSpaceToken !== null && $previousNonSpaceToken[0] === T_OBJECT_OPERATOR) {
continue;
}
$tokens[$i][0] = Emulative::T_FN;
}
}
return $tokens;
}
/**
* @param mixed[] $tokens
* @return mixed[]|null
*/
private function getPreviousNonSpaceToken(array $tokens, int $start)
{
for ($i = $start - 1; $i >= 0; --$i) {
if ($tokens[$i][0] === T_WHITESPACE) {
continue;
}
return $tokens[$i];
}
return null;
}
}

View File

@@ -0,0 +1,98 @@
<?php declare(strict_types=1);
namespace PhpParser\Lexer\TokenEmulator;
use PhpParser\Lexer\Emulative;
final class NumericLiteralSeparatorEmulator implements TokenEmulatorInterface
{
const BIN = '(?:0b[01]+(?:_[01]+)*)';
const HEX = '(?:0x[0-9a-f]+(?:_[0-9a-f]+)*)';
const DEC = '(?:[0-9]+(?:_[0-9]+)*)';
const SIMPLE_FLOAT = '(?:' . self::DEC . '\.' . self::DEC . '?|\.' . self::DEC . ')';
const EXP = '(?:e[+-]?' . self::DEC . ')';
const FLOAT = '(?:' . self::SIMPLE_FLOAT . self::EXP . '?|' . self::DEC . self::EXP . ')';
const NUMBER = '~' . self::FLOAT . '|' . self::BIN . '|' . self::HEX . '|' . self::DEC . '~iA';
public function isEmulationNeeded(string $code) : bool
{
// skip version where this is supported
if (version_compare(\PHP_VERSION, Emulative::PHP_7_4, '>=')) {
return false;
}
return preg_match('~[0-9a-f]_[0-9a-f]~i', $code) !== false;
}
public function emulate(string $code, array $tokens): array
{
// We need to manually iterate and manage a count because we'll change
// the tokens array on the way
$codeOffset = 0;
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
$token = $tokens[$i];
$tokenLen = \strlen(\is_array($token) ? $token[1] : $token);
if ($token[0] !== T_LNUMBER && $token[0] !== T_DNUMBER) {
$codeOffset += $tokenLen;
continue;
}
$res = preg_match(self::NUMBER, $code, $matches, 0, $codeOffset);
assert($res, "No number at number token position");
$match = $matches[0];
$matchLen = \strlen($match);
if ($matchLen === $tokenLen) {
// Original token already holds the full number.
$codeOffset += $tokenLen;
continue;
}
$tokenKind = $this->resolveIntegerOrFloatToken($match);
$newTokens = [[$tokenKind, $match, $token[2]]];
$numTokens = 1;
$len = $tokenLen;
while ($matchLen > $len) {
$nextToken = $tokens[$i + $numTokens];
$nextTokenText = \is_array($nextToken) ? $nextToken[1] : $nextToken;
$nextTokenLen = \strlen($nextTokenText);
$numTokens++;
if ($matchLen < $len + $nextTokenLen) {
// Split trailing characters into a partial token.
assert(is_array($nextToken), "Partial token should be an array token");
$partialText = substr($nextTokenText, $matchLen - $len);
$newTokens[] = [$nextToken[0], $partialText, $nextToken[2]];
break;
}
$len += $nextTokenLen;
}
array_splice($tokens, $i, $numTokens, $newTokens);
$c -= $numTokens - \count($newTokens);
$codeOffset += $matchLen;
}
return $tokens;
}
private function resolveIntegerOrFloatToken(string $str): int
{
$str = str_replace('_', '', $str);
if (stripos($str, '0b') === 0) {
$num = bindec($str);
} elseif (stripos($str, '0x') === 0) {
$num = hexdec($str);
} elseif (stripos($str, '0') === 0 && ctype_digit($str)) {
$num = octdec($str);
} else {
$num = +$str;
}
return is_float($num) ? T_DNUMBER : T_LNUMBER;
}
}

View File

@@ -0,0 +1,14 @@
<?php declare(strict_types=1);
namespace PhpParser\Lexer\TokenEmulator;
/** @internal */
interface TokenEmulatorInterface
{
public function isEmulationNeeded(string $code): bool;
/**
* @return array Modified Tokens
*/
public function emulate(string $code, array $tokens): array;
}

View File

@@ -22,7 +22,7 @@ class Arg extends NodeAbstract
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $value, bool $byRef = false, bool $unpack = false, array $attributes = []) { public function __construct(Expr $value, bool $byRef = false, bool $unpack = false, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->value = $value; $this->value = $value;
$this->byRef = $byRef; $this->byRef = $byRef;
$this->unpack = $unpack; $this->unpack = $unpack;

View File

@@ -22,7 +22,7 @@ class Const_ extends NodeAbstract
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($name, Expr $value, array $attributes = []) { public function __construct($name, Expr $value, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->name = \is_string($name) ? new Identifier($name) : $name; $this->name = \is_string($name) ? new Identifier($name) : $name;
$this->value = $value; $this->value = $value;
} }

View File

@@ -19,7 +19,7 @@ class ArrayDimFetch extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $var, Expr $dim = null, array $attributes = []) { public function __construct(Expr $var, Expr $dim = null, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->var = $var; $this->var = $var;
$this->dim = $dim; $this->dim = $dim;
} }

View File

@@ -12,6 +12,8 @@ class ArrayItem extends Expr
public $value; public $value;
/** @var bool Whether to assign by reference */ /** @var bool Whether to assign by reference */
public $byRef; public $byRef;
/** @var bool Whether to unpack the argument */
public $unpack;
/** /**
* Constructs an array item node. * Constructs an array item node.
@@ -21,15 +23,16 @@ class ArrayItem extends Expr
* @param bool $byRef Whether to assign by reference * @param bool $byRef Whether to assign by reference
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $value, Expr $key = null, bool $byRef = false, array $attributes = []) { public function __construct(Expr $value, Expr $key = null, bool $byRef = false, array $attributes = [], bool $unpack = false) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->key = $key; $this->key = $key;
$this->value = $value; $this->value = $value;
$this->byRef = $byRef; $this->byRef = $byRef;
$this->unpack = $unpack;
} }
public function getSubNodeNames() : array { public function getSubNodeNames() : array {
return ['key', 'value', 'byRef']; return ['key', 'value', 'byRef', 'unpack'];
} }
public function getType() : string { public function getType() : string {

View File

@@ -20,7 +20,7 @@ class Array_ extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $items = [], array $attributes = []) { public function __construct(array $items = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->items = $items; $this->items = $items;
} }

View File

@@ -0,0 +1,71 @@
<?php declare(strict_types=1);
namespace PhpParser\Node\Expr;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\FunctionLike;
class ArrowFunction extends Expr implements FunctionLike
{
/** @var bool */
public $static;
/** @var bool */
public $byRef;
/** @var Node\Param[] */
public $params = [];
/** @var null|Node\Identifier|Node\Name|Node\NullableType */
public $returnType;
/** @var Expr */
public $expr;
/**
* @param array $subNodes Array of the following optional subnodes:
* 'static' => false : Whether the closure is static
* 'byRef' => false : Whether to return by reference
* 'params' => array() : Parameters
* 'returnType' => null : Return type
* 'expr' => Expr : Expression body
* @param array $attributes Additional attributes
*/
public function __construct(array $subNodes = [], array $attributes = []) {
$this->attributes = $attributes;
$this->static = $subNodes['static'] ?? false;
$this->byRef = $subNodes['byRef'] ?? false;
$this->params = $subNodes['params'] ?? [];
$returnType = $subNodes['returnType'] ?? null;
$this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
$this->expr = $subNodes['expr'] ?? null;
}
public function getSubNodeNames() : array {
return ['static', 'byRef', 'params', 'returnType', 'expr'];
}
public function returnsByRef() : bool {
return $this->byRef;
}
public function getParams() : array {
return $this->params;
}
public function getReturnType() {
return $this->returnType;
}
/**
* @return Node\Stmt\Return_[]
*/
public function getStmts() : array {
return [new Node\Stmt\Return_($this->expr)];
}
public function getType() : string {
return 'Expr_ArrowFunction';
}
}

View File

@@ -19,7 +19,7 @@ class Assign extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $var, Expr $expr, array $attributes = []) { public function __construct(Expr $var, Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->var = $var; $this->var = $var;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -19,7 +19,7 @@ abstract class AssignOp extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $var, Expr $expr, array $attributes = []) { public function __construct(Expr $var, Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->var = $var; $this->var = $var;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -19,7 +19,7 @@ class AssignRef extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $var, Expr $expr, array $attributes = []) { public function __construct(Expr $var, Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->var = $var; $this->var = $var;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -19,7 +19,7 @@ abstract class BinaryOp extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $left, Expr $right, array $attributes = []) { public function __construct(Expr $left, Expr $right, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->left = $left; $this->left = $left;
$this->right = $right; $this->right = $right;
} }

View File

@@ -16,7 +16,7 @@ class BitwiseNot extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr, array $attributes = []) { public function __construct(Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -16,7 +16,7 @@ class BooleanNot extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr, array $attributes = []) { public function __construct(Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -16,7 +16,7 @@ abstract class Cast extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr, array $attributes = []) { public function __construct(Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -21,7 +21,7 @@ class ClassConstFetch extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($class, $name, array $attributes = []) { public function __construct($class, $name, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->class = $class; $this->class = $class;
$this->name = \is_string($name) ? new Identifier($name) : $name; $this->name = \is_string($name) ? new Identifier($name) : $name;
} }

View File

@@ -16,7 +16,7 @@ class Clone_ extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr, array $attributes = []) { public function __construct(Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -34,7 +34,7 @@ class Closure extends Expr implements FunctionLike
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $subNodes = [], array $attributes = []) { public function __construct(array $subNodes = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->static = $subNodes['static'] ?? false; $this->static = $subNodes['static'] ?? false;
$this->byRef = $subNodes['byRef'] ?? false; $this->byRef = $subNodes['byRef'] ?? false;
$this->params = $subNodes['params'] ?? []; $this->params = $subNodes['params'] ?? [];

View File

@@ -19,7 +19,7 @@ class ClosureUse extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr\Variable $var, bool $byRef = false, array $attributes = []) { public function __construct(Expr\Variable $var, bool $byRef = false, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->var = $var; $this->var = $var;
$this->byRef = $byRef; $this->byRef = $byRef;
} }

View File

@@ -17,7 +17,7 @@ class ConstFetch extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Name $name, array $attributes = []) { public function __construct(Name $name, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->name = $name; $this->name = $name;
} }

View File

@@ -16,7 +16,7 @@ class Empty_ extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr, array $attributes = []) { public function __construct(Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -18,7 +18,7 @@ class Error extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $attributes = []) { public function __construct(array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
} }
public function getSubNodeNames() : array { public function getSubNodeNames() : array {

View File

@@ -16,7 +16,7 @@ class ErrorSuppress extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr, array $attributes = []) { public function __construct(Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -16,7 +16,7 @@ class Eval_ extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr, array $attributes = []) { public function __construct(Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -20,7 +20,7 @@ class Exit_ extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr = null, array $attributes = []) { public function __construct(Expr $expr = null, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -20,7 +20,7 @@ class FuncCall extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($name, array $args = [], array $attributes = []) { public function __construct($name, array $args = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->name = $name; $this->name = $name;
$this->args = $args; $this->args = $args;
} }

View File

@@ -24,7 +24,7 @@ class Include_ extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr, int $type, array $attributes = []) { public function __construct(Expr $expr, int $type, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
$this->type = $type; $this->type = $type;
} }

View File

@@ -20,7 +20,7 @@ class Instanceof_ extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr, $class, array $attributes = []) { public function __construct(Expr $expr, $class, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
$this->class = $class; $this->class = $class;
} }

View File

@@ -16,7 +16,7 @@ class Isset_ extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $vars, array $attributes = []) { public function __construct(array $vars, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->vars = $vars; $this->vars = $vars;
} }

View File

@@ -16,7 +16,7 @@ class List_ extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $items, array $attributes = []) { public function __construct(array $items, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->items = $items; $this->items = $items;
} }

View File

@@ -24,7 +24,7 @@ class MethodCall extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $var, $name, array $args = [], array $attributes = []) { public function __construct(Expr $var, $name, array $args = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->var = $var; $this->var = $var;
$this->name = \is_string($name) ? new Identifier($name) : $name; $this->name = \is_string($name) ? new Identifier($name) : $name;
$this->args = $args; $this->args = $args;

View File

@@ -20,7 +20,7 @@ class New_ extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($class, array $args = [], array $attributes = []) { public function __construct($class, array $args = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->class = $class; $this->class = $class;
$this->args = $args; $this->args = $args;
} }

View File

@@ -16,7 +16,7 @@ class PostDec extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $var, array $attributes = []) { public function __construct(Expr $var, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->var = $var; $this->var = $var;
} }

View File

@@ -16,7 +16,7 @@ class PostInc extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $var, array $attributes = []) { public function __construct(Expr $var, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->var = $var; $this->var = $var;
} }

View File

@@ -16,7 +16,7 @@ class PreDec extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $var, array $attributes = []) { public function __construct(Expr $var, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->var = $var; $this->var = $var;
} }

View File

@@ -16,7 +16,7 @@ class PreInc extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $var, array $attributes = []) { public function __construct(Expr $var, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->var = $var; $this->var = $var;
} }

View File

@@ -16,7 +16,7 @@ class Print_ extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr, array $attributes = []) { public function __construct(Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -20,7 +20,7 @@ class PropertyFetch extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $var, $name, array $attributes = []) { public function __construct(Expr $var, $name, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->var = $var; $this->var = $var;
$this->name = \is_string($name) ? new Identifier($name) : $name; $this->name = \is_string($name) ? new Identifier($name) : $name;
} }

View File

@@ -16,7 +16,7 @@ class ShellExec extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $parts, array $attributes = []) { public function __construct(array $parts, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->parts = $parts; $this->parts = $parts;
} }

View File

@@ -24,7 +24,7 @@ class StaticCall extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($class, $name, array $args = [], array $attributes = []) { public function __construct($class, $name, array $args = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->class = $class; $this->class = $class;
$this->name = \is_string($name) ? new Identifier($name) : $name; $this->name = \is_string($name) ? new Identifier($name) : $name;
$this->args = $args; $this->args = $args;

View File

@@ -21,7 +21,7 @@ class StaticPropertyFetch extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($class, $name, array $attributes = []) { public function __construct($class, $name, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->class = $class; $this->class = $class;
$this->name = \is_string($name) ? new VarLikeIdentifier($name) : $name; $this->name = \is_string($name) ? new VarLikeIdentifier($name) : $name;
} }

View File

@@ -22,7 +22,7 @@ class Ternary extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $cond, $if, Expr $else, array $attributes = []) { public function __construct(Expr $cond, $if, Expr $else, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->cond = $cond; $this->cond = $cond;
$this->if = $if; $this->if = $if;
$this->else = $else; $this->else = $else;

View File

@@ -16,7 +16,7 @@ class UnaryMinus extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr, array $attributes = []) { public function __construct(Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -16,7 +16,7 @@ class UnaryPlus extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr, array $attributes = []) { public function __construct(Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -16,7 +16,7 @@ class Variable extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($name, array $attributes = []) { public function __construct($name, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->name = $name; $this->name = $name;
} }

View File

@@ -16,7 +16,7 @@ class YieldFrom extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $expr, array $attributes = []) { public function __construct(Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -19,7 +19,7 @@ class Yield_ extends Expr
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Expr $value = null, Expr $key = null, array $attributes = []) { public function __construct(Expr $value = null, Expr $key = null, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->key = $key; $this->key = $key;
$this->value = $value; $this->value = $value;
} }

View File

@@ -25,7 +25,7 @@ class Identifier extends NodeAbstract
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(string $name, array $attributes = []) { public function __construct(string $name, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->name = $name; $this->name = $name;
} }

View File

@@ -6,9 +6,7 @@ use PhpParser\NodeAbstract;
class Name extends NodeAbstract class Name extends NodeAbstract
{ {
/** /** @var string[] Parts of the name */
* @var string[] Parts of the name
*/
public $parts; public $parts;
private static $specialClassNames = [ private static $specialClassNames = [
@@ -24,7 +22,7 @@ class Name extends NodeAbstract
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($name, array $attributes = []) { public function __construct($name, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->parts = self::prepareName($name); $this->parts = self::prepareName($name);
} }

View File

@@ -16,7 +16,7 @@ class NullableType extends NodeAbstract
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($type, array $attributes = []) { public function __construct($type, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->type = \is_string($type) ? new Identifier($type) : $type; $this->type = \is_string($type) ? new Identifier($type) : $type;
} }

View File

@@ -31,7 +31,7 @@ class Param extends NodeAbstract
$var, Expr $default = null, $type = null, $var, Expr $default = null, $type = null,
bool $byRef = false, bool $variadic = false, array $attributes = [] bool $byRef = false, bool $variadic = false, array $attributes = []
) { ) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->type = \is_string($type) ? new Identifier($type) : $type; $this->type = \is_string($type) ? new Identifier($type) : $type;
$this->byRef = $byRef; $this->byRef = $byRef;
$this->variadic = $variadic; $this->variadic = $variadic;

View File

@@ -16,7 +16,7 @@ class DNumber extends Scalar
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(float $value, array $attributes = []) { public function __construct(float $value, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->value = $value; $this->value = $value;
} }
@@ -34,6 +34,8 @@ class DNumber extends Scalar
* @return float The parsed number * @return float The parsed number
*/ */
public static function parse(string $str) : float { public static function parse(string $str) : float {
$str = str_replace('_', '', $str);
// if string contains any of .eE just cast it to float // if string contains any of .eE just cast it to float
if (false !== strpbrk($str, '.eE')) { if (false !== strpbrk($str, '.eE')) {
return (float) $str; return (float) $str;

View File

@@ -17,7 +17,7 @@ class Encapsed extends Scalar
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $parts, array $attributes = []) { public function __construct(array $parts, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->parts = $parts; $this->parts = $parts;
} }

View File

@@ -16,7 +16,7 @@ class EncapsedStringPart extends Scalar
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(string $value, array $attributes = []) { public function __construct(string $value, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->value = $value; $this->value = $value;
} }

View File

@@ -23,7 +23,7 @@ class LNumber extends Scalar
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(int $value, array $attributes = []) { public function __construct(int $value, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->value = $value; $this->value = $value;
} }
@@ -41,6 +41,8 @@ class LNumber extends Scalar
* @return LNumber The constructed LNumber, including kind attribute * @return LNumber The constructed LNumber, including kind attribute
*/ */
public static function fromString(string $str, array $attributes = [], bool $allowInvalidOctal = false) : LNumber { public static function fromString(string $str, array $attributes = [], bool $allowInvalidOctal = false) : LNumber {
$str = str_replace('_', '', $str);
if ('0' !== $str[0] || '0' === $str) { if ('0' !== $str[0] || '0' === $str) {
$attributes['kind'] = LNumber::KIND_DEC; $attributes['kind'] = LNumber::KIND_DEC;
return new LNumber((int) $str, $attributes); return new LNumber((int) $str, $attributes);

View File

@@ -12,7 +12,7 @@ abstract class MagicConst extends Scalar
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $attributes = []) { public function __construct(array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
} }
public function getSubNodeNames() : array { public function getSubNodeNames() : array {

View File

@@ -34,7 +34,7 @@ class String_ extends Scalar
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(string $value, array $attributes = []) { public function __construct(string $value, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->value = $value; $this->value = $value;
} }
@@ -100,7 +100,7 @@ class String_ extends Scalar
if (isset(self::$replacements[$str])) { if (isset(self::$replacements[$str])) {
return self::$replacements[$str]; return self::$replacements[$str];
} elseif ('x' === $str[0] || 'X' === $str[0]) { } elseif ('x' === $str[0] || 'X' === $str[0]) {
return chr(hexdec($str)); return chr(hexdec(substr($str, 1)));
} elseif ('u' === $str[0]) { } elseif ('u' === $str[0]) {
return self::codePointToUtf8(hexdec($matches[2])); return self::codePointToUtf8(hexdec($matches[2]));
} else { } else {

View File

@@ -16,7 +16,7 @@ class Break_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Node\Expr $num = null, array $attributes = []) { public function __construct(Node\Expr $num = null, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->num = $num; $this->num = $num;
} }

View File

@@ -19,7 +19,7 @@ class Case_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($cond, array $stmts = [], array $attributes = []) { public function __construct($cond, array $stmts = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->cond = $cond; $this->cond = $cond;
$this->stmts = $stmts; $this->stmts = $stmts;
} }

View File

@@ -25,7 +25,7 @@ class Catch_ extends Node\Stmt
public function __construct( public function __construct(
array $types, Expr\Variable $var, array $stmts = [], array $attributes = [] array $types, Expr\Variable $var, array $stmts = [], array $attributes = []
) { ) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->types = $types; $this->types = $types;
$this->var = $var; $this->var = $var;
$this->stmts = $stmts; $this->stmts = $stmts;

View File

@@ -19,7 +19,7 @@ class ClassConst extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $consts, int $flags = 0, array $attributes = []) { public function __construct(array $consts, int $flags = 0, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->flags = $flags; $this->flags = $flags;
$this->consts = $consts; $this->consts = $consts;
} }

View File

@@ -51,7 +51,7 @@ class ClassMethod extends Node\Stmt implements FunctionLike
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($name, array $subNodes = [], array $attributes = []) { public function __construct($name, array $subNodes = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0;
$this->byRef = $subNodes['byRef'] ?? false; $this->byRef = $subNodes['byRef'] ?? false;
$this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->name = \is_string($name) ? new Node\Identifier($name) : $name;

View File

@@ -35,7 +35,7 @@ class Class_ extends ClassLike
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($name, array $subNodes = [], array $attributes = []) { public function __construct($name, array $subNodes = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0;
$this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
$this->extends = $subNodes['extends'] ?? null; $this->extends = $subNodes['extends'] ?? null;

View File

@@ -16,7 +16,7 @@ class Const_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $consts, array $attributes = []) { public function __construct(array $consts, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->consts = $consts; $this->consts = $consts;
} }

View File

@@ -16,7 +16,7 @@ class Continue_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Node\Expr $num = null, array $attributes = []) { public function __construct(Node\Expr $num = null, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->num = $num; $this->num = $num;
} }

View File

@@ -19,7 +19,7 @@ class DeclareDeclare extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($key, Node\Expr $value, array $attributes = []) { public function __construct($key, Node\Expr $value, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->key = \is_string($key) ? new Node\Identifier($key) : $key; $this->key = \is_string($key) ? new Node\Identifier($key) : $key;
$this->value = $value; $this->value = $value;
} }

View File

@@ -19,7 +19,7 @@ class Declare_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $declares, array $stmts = null, array $attributes = []) { public function __construct(array $declares, array $stmts = null, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->declares = $declares; $this->declares = $declares;
$this->stmts = $stmts; $this->stmts = $stmts;
} }

View File

@@ -19,7 +19,7 @@ class Do_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) { public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->cond = $cond; $this->cond = $cond;
$this->stmts = $stmts; $this->stmts = $stmts;
} }

View File

@@ -16,7 +16,7 @@ class Echo_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $exprs, array $attributes = []) { public function __construct(array $exprs, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->exprs = $exprs; $this->exprs = $exprs;
} }

View File

@@ -19,7 +19,7 @@ class ElseIf_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) { public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->cond = $cond; $this->cond = $cond;
$this->stmts = $stmts; $this->stmts = $stmts;
} }

View File

@@ -16,7 +16,7 @@ class Else_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $stmts = [], array $attributes = []) { public function __construct(array $stmts = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->stmts = $stmts; $this->stmts = $stmts;
} }

View File

@@ -19,7 +19,7 @@ class Expression extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Node\Expr $expr, array $attributes = []) { public function __construct(Node\Expr $expr, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
} }

View File

@@ -16,7 +16,7 @@ class Finally_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $stmts = [], array $attributes = []) { public function __construct(array $stmts = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->stmts = $stmts; $this->stmts = $stmts;
} }

View File

@@ -26,7 +26,7 @@ class For_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $subNodes = [], array $attributes = []) { public function __construct(array $subNodes = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->init = $subNodes['init'] ?? []; $this->init = $subNodes['init'] ?? [];
$this->cond = $subNodes['cond'] ?? []; $this->cond = $subNodes['cond'] ?? [];
$this->loop = $subNodes['loop'] ?? []; $this->loop = $subNodes['loop'] ?? [];

View File

@@ -29,7 +29,7 @@ class Foreach_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Node\Expr $expr, Node\Expr $valueVar, array $subNodes = [], array $attributes = []) { public function __construct(Node\Expr $expr, Node\Expr $valueVar, array $subNodes = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->expr = $expr; $this->expr = $expr;
$this->keyVar = $subNodes['keyVar'] ?? null; $this->keyVar = $subNodes['keyVar'] ?? null;
$this->byRef = $subNodes['byRef'] ?? false; $this->byRef = $subNodes['byRef'] ?? false;

View File

@@ -33,7 +33,7 @@ class Function_ extends Node\Stmt implements FunctionLike
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($name, array $subNodes = [], array $attributes = []) { public function __construct($name, array $subNodes = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->byRef = $subNodes['byRef'] ?? false; $this->byRef = $subNodes['byRef'] ?? false;
$this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
$this->params = $subNodes['params'] ?? []; $this->params = $subNodes['params'] ?? [];

View File

@@ -16,7 +16,7 @@ class Global_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(array $vars, array $attributes = []) { public function __construct(array $vars, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->vars = $vars; $this->vars = $vars;
} }

View File

@@ -17,7 +17,7 @@ class Goto_ extends Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($name, array $attributes = []) { public function __construct($name, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->name = \is_string($name) ? new Identifier($name) : $name; $this->name = \is_string($name) ? new Identifier($name) : $name;
} }

View File

@@ -23,7 +23,7 @@ class GroupUse extends Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Name $prefix, array $uses, int $type = Use_::TYPE_NORMAL, array $attributes = []) { public function __construct(Name $prefix, array $uses, int $type = Use_::TYPE_NORMAL, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->type = $type; $this->type = $type;
$this->prefix = $prefix; $this->prefix = $prefix;
$this->uses = $uses; $this->uses = $uses;

View File

@@ -16,7 +16,7 @@ class HaltCompiler extends Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(string $remaining, array $attributes = []) { public function __construct(string $remaining, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->remaining = $remaining; $this->remaining = $remaining;
} }

View File

@@ -26,7 +26,7 @@ class If_ extends Node\Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Node\Expr $cond, array $subNodes = [], array $attributes = []) { public function __construct(Node\Expr $cond, array $subNodes = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->cond = $cond; $this->cond = $cond;
$this->stmts = $subNodes['stmts'] ?? []; $this->stmts = $subNodes['stmts'] ?? [];
$this->elseifs = $subNodes['elseifs'] ?? []; $this->elseifs = $subNodes['elseifs'] ?? [];

View File

@@ -16,7 +16,7 @@ class InlineHTML extends Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(string $value, array $attributes = []) { public function __construct(string $value, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->value = $value; $this->value = $value;
} }

View File

@@ -19,7 +19,7 @@ class Interface_ extends ClassLike
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($name, array $subNodes = [], array $attributes = []) { public function __construct($name, array $subNodes = [], array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
$this->extends = $subNodes['extends'] ?? []; $this->extends = $subNodes['extends'] ?? [];
$this->stmts = $subNodes['stmts'] ?? []; $this->stmts = $subNodes['stmts'] ?? [];

View File

@@ -17,7 +17,7 @@ class Label extends Stmt
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct($name, array $attributes = []) { public function __construct($name, array $attributes = []) {
parent::__construct($attributes); $this->attributes = $attributes;
$this->name = \is_string($name) ? new Identifier($name) : $name; $this->name = \is_string($name) ? new Identifier($name) : $name;
} }

Some files were not shown because too many files have changed in this diff Show More