Compare commits

...

55 Commits

Author SHA1 Message Date
579f4ce846 Release PHP-Parser 3.1.3 2017-12-26 15:43:21 +01:00
94ca9a7ab9 Use Tokens::class in lexer
Ref #441.
2017-11-13 01:14:55 +01:00
bac91b426e Correctly determine Type of Node when PHP-Parser's namespaces are prefixed
Hi there,

I'm working on mutation testing framework ([Infection](https://github.com/infection/infection/)) that is distributed as a PHAR. One of this goal is to run target project's test suite against mutated code. Since we use reflection and load project's autoloader, we want to avoid potential conflicts between vendor files of Infection itself and the target project.

To avoid this issue, there is a project calld [PHP-Scoper](https://github.com/humbug/php-scoper). What it does is it prefixes all the namespaces of the library (including vendor folder) with some character(s), for example namespace `Infection\Mutator\PublicVisibility` is transformed to `ScoperAbc123\Infection\Mutant\PublicVisibility`.

But since it also prefixes vendor folder, PHP-Parser's classes are prefixed as well and `NodeAbstract::getType()` after this prefixing works incorrectly.

There is a hardcoded number `15` which means to remove `'PhpParser\Node'` (length=15) substring from the FQCN.

Code:

```php
// PHPParser\Node\Stmt\Declare_ -> Stmt_Declare

return strtr(substr(rtrim(get_class($this), '_'), 15), '\\', '_');
```

What I suggest is a little be more dynamic solution, to correctly extract class name (type) from the ***prefixed*** FQCL:

`ScoperAbc123\PHPParser\Node\Stmt\Declare_` -> `Stmt_Declare`
2017-11-12 21:11:41 +01:00
08131e7ff2 Release PHP-Parser 3.1.2 2017-11-04 12:48:34 +01:00
0ba710affa Add setDocComment() to namespace build (#437) 2017-11-04 12:43:02 +01:00
72231abe6d ClassMethod stmts property can be null (#435)
Conflicts:
	lib/PhpParser/Node/Stmt/ClassMethod.php
2017-11-04 12:38:45 +01:00
d418bf3951 Preserve comments on empty blocks (#382) 2017-10-01 16:54:43 +02:00
5a9fbca54a Add attribute for namespace kinds (#417)
One of KIND_SEMICOLON or KIND_BRACED.
2017-09-26 18:45:05 +02:00
a1e8e1a30e Release PHP-Parser 3.1.1 2017-09-02 19:10:46 +02:00
d77e6cd6e9 Allow TraitUse statements in trait builder
Fixes #413.
2017-08-29 23:18:59 +02:00
a10780ca0d Handle Nop statement after brace-style namespace
Fixes #412.
2017-08-29 23:14:27 +02:00
4d4896e553 Release PHP-Parser 3.1.0 2017-07-28 16:45:09 +02:00
6fa073879e Remove deprecation of Name::$parts
It doesn't look like this is going away for now, and we currently
don't have the APIs to cover all existing usages elegantly.
2017-07-19 17:13:10 +02:00
5a3a1ec25c Handle LC_NUMERIC with comma decimal separator
Closes #399.
2017-07-19 17:10:55 +02:00
4a7d011317 Add support for object type 2017-06-28 23:12:13 +02:00
7f862ac21c Add support for trailing comma in group use 2017-06-28 23:05:28 +02:00
0808939f81 Release PHP-Parser 3.0.6 2017-06-28 22:53:48 +02:00
7bfc320bda Switch to dist: trusty, so HHVM runs 2017-06-03 15:25:50 +02:00
bc0bff3f87 Fix method name in tests 2017-06-03 15:18:23 +02:00
c28b8556f5 Fix Lexer errorHandling when there is no tokens
I encounter an issue when no tokens exist. An error `Undefined offset -1` is triggered.
2017-06-03 15:17:45 +02:00
3da86df48f Deprecate Node::setLine() 2017-04-29 12:58:35 +02:00
901b895c02 Fix spelling of VISIBILITY_MODIFIER_MASK 2017-04-19 11:20:05 +02:00
c877c1a64f Add Builder\Param::makeVariadic() 2017-04-19 11:16:29 +02:00
c3cbf07946 Pretty printer: Preserve comments in arrays and calls
If call arguments or array contains comments, print it in multiline
form, so that comments may be preserved.
2017-04-09 19:49:47 +02:00
2b9e2f71b7 Release PHP-Parser 3.0.5 2017-03-05 19:23:57 +01:00
d5873b177b Adjust the end attributes on the stack as well 2017-02-26 23:45:14 +01:00
48ec654d0c Make Expr\Error nodes empty
Resolves issue #359.
2017-02-26 23:38:32 +01:00
c12a4c8239 Fix start attribute assignment for Error in ClassConstFetch 2017-02-26 23:00:38 +01:00
86ea6fe8c4 Remove leftover code 2017-02-26 22:53:08 +01:00
1b59e918f7 Perform NullableType resolution earlier
This makes sure function signatures are already fully resolved in
enterNode(). Resolves issue #360.
2017-02-26 22:50:31 +01:00
0bf561dfe7 Release PHP-Parser 3.0.4 2017-02-10 21:20:03 +01:00
df98b0417b Handle "extends static" etc more gracefully
Use class_name production and emit the same error as for
"extends self" and "extends parent". It's weird that "extends
static" gives a different result than those two.
2017-02-09 18:43:09 +01:00
a8eb2fc675 Support recovery from invalid trailing commas 2017-02-09 00:35:12 +01:00
d18ccfeec7 Use p() in pPrec() for easier extensibility 2017-02-09 00:03:00 +01:00
4e55897059 Change one function to protected 2017-02-08 23:55:02 +01:00
41facc02ef Fix typo with-posititions => with-positions 2017-02-08 23:54:08 +01:00
62877b5d14 Recover from missing semicolons on statements 2017-02-05 17:47:56 +01:00
5b8182cc0a Release PHP-Parser 3.0.3 2017-02-03 22:57:31 +01:00
af8b17bd75 Update changelog 2017-02-03 22:56:55 +01:00
42f046ec19 Deprecate XML serializer 2017-02-03 22:52:16 +01:00
d287c167bc Pretty print: Handle Error in ClassConstFetch 2017-02-03 21:53:02 +01:00
58e7881e98 Implement NodeTraverser::STOP_TRAVERSAL
Conflicts:
	lib/PhpParser/NodeVisitor.php
2017-01-29 22:35:40 +01:00
fd7ac25108 Throw if pretty-printing Error node 2017-01-29 21:56:21 +01:00
ba57202ed7 Fixed method name casing (#336)
Make it match the parent class.
2017-01-14 12:01:25 +01:00
3e8c8d248d Add originalName attribute in NameResolver
For now gated behind a preserveOriginalNames option.
2016-12-22 20:25:02 +01:00
301c34373d Update run-php-src to use 7.1.0 2016-12-11 16:47:47 +01:00
58970e2a37 Improve LNumber/DNumber pretty printing
* Support PHP_INT_MIN
* Support negative binary/octal/hex numbers
* Support INF/-INF/NAN in namespaces
2016-12-11 16:31:59 +01:00
c1e0bab4f8 Add support for negative interpolated offsets
A late addition to PHP 7.1 which I missed.
2016-12-11 13:44:17 +01:00
d5eebf7214 Add php-parse --with-positions
To invoke NodeDumper in dumpPositions mode
2016-12-09 22:41:46 +01:00
70319e27ee Parse 0 in "$a[0]" as LNumber (#325) 2016-12-07 20:24:00 +01:00
8a97065e30 Add UPGRADE note about NameResolver changes 2016-12-07 20:09:23 +01:00
adf44419c0 Release PHP-Parser 3.0.2 2016-12-06 12:30:35 +01:00
5219f75719 Fix pretty-printing of nullable types 2016-12-06 12:26:21 +01:00
a485ecd7ba NameResolver - resolve Name in NullableType 2016-12-06 12:21:30 +01:00
030de805e1 Add NullableType to types of properties/args that offer it (#323) 2016-12-05 13:30:29 +01:00
64 changed files with 3543 additions and 2000 deletions

View File

@ -1,5 +1,5 @@
language: php
dist: trusty
sudo: false
cache:

View File

@ -1,8 +1,130 @@
Version 3.0.2-dev
Version 3.1.4-dev
-----------------
Nothing yet.
Version 3.1.3 (2017-12-26)
--------------------------
### Fixed
* Improve compatibility with php-scoper, by supporting prefixed namespaces in
`NodeAbstract::getType()`.
Version 3.1.2 (2017-11-04)
--------------------------
### Fixed
* Comments on empty blocks are now preserved on a `Stmt\Nop` node. (#382)
### Added
* Added `kind` attribute for `Stmt\Namespace_` node, which is one of `KIND_SEMICOLON` or
`KIND_BRACED`. (#417)
* Added `setDocComment()` method to namespace builder. (#437)
Version 3.1.1 (2017-09-02)
--------------------------
### Fixed
* Fixed syntax error on comment after brace-style namespace declaration. (#412)
* Added support for TraitUse statements in trait builder. (#413)
Version 3.1.0 (2017-07-28)
--------------------------
### Added
* [PHP 7.2] Added support for trailing comma in group use statements.
* [PHP 7.2] Added support for `object` type. This means `object` types will now be represented as a
builtin type (a simple `"object"` string), rather than a class `Name`.
### Fixed
* Floating-point numbers are now printed correctly if the LC_NUMERIC locale uses a comma as decimal
separator.
### Changed
* `Name::$parts` is no longer deprecated.
Version 3.0.6 (2017-06-28)
--------------------------
### Fixed
* Fixed the spelling of `Class_::VISIBILITY_MODIFIER_MASK`. The previous spelling of
`Class_::VISIBILITY_MODIFER_MASK` is preserved for backwards compatibility.
* The pretty printing will now preserve comments inside array literals and function calls by
printing the array items / function arguments on separate lines. Array literals and functions that
do not contain comments are not affected.
### Added
* Added `Builder\Param::makeVariadic()`.
### Deprecated
* The `Node::setLine()` method has been deprecated.
Version 3.0.5 (2017-03-05)
--------------------------
### Fixed
* Name resolution of `NullableType`s is now performed earlier, so that a fully resolved signature is
available when a function is entered. (#360)
* `Error` nodes are now considered empty, while previously they extended until the token where the
error occurred. This made some nodes larger than expected. (#359)
* Fixed notices being thrown during error recovery in some situations. (#362)
Version 3.0.4 (2017-02-10)
--------------------------
### Fixed
* Fixed some extensibility issues in pretty printer (`pUseType()` is now public and `pPrec()` calls
into `p()`, instead of directly dispatching to the type-specific printing method).
* Fixed notice in `bin/php-parse` script.
### Added
* Error recovery from missing semicolons is now supported in more cases.
* Error recovery from trailing commas in positions where PHP does not support them is now supported.
Version 3.0.3 (2017-02-03)
--------------------------
### Fixed
* In `"$foo[0]"` the `0` is now parsed as an `LNumber` rather than `String`. (#325)
* Ensure integers and floats are always pretty printed preserving semantics, even if the particular
value can only be manually constructed.
* Throw a `LogicException` when trying to pretty-print an `Error` node. Previously this resulted in
an undefined method exception or fatal error.
### Added
* [PHP 7.1] Added support for negative interpolated offsets: `"$foo[-1]"`
* Added `preserveOriginalNames` option to `NameResolver`. If this option is enabled, an
`originalName` attribute, containing the unresolved name, will be added to each resolved name.
* Added `php-parse --with-positions` option, which dumps nodes with position information.
### Deprecated
* The XML serializer has been deprecated. In particular, the classes `Serializer\XML`,
`Unserializer\XML`, as well as the interfaces `Serializer` and `Unserializer` are deprecated.
Version 3.0.2 (2016-12-06)
--------------------------
### Fixed
* Fixed name resolution of nullable types. (#324)
* Fixed pretty-printing of nullable types.
Version 3.0.1 (2016-12-01)
--------------------------
@ -10,7 +132,7 @@ Version 3.0.1 (2016-12-01)
* Fixed handling of nested `list()`s: If the nested list was unkeyed, it was directly included in
the list items. If it was keyed, it was wrapped in `ArrayItem`. Now nested `List_` nodes are
always wrapped in `ArrayItem`s.
always wrapped in `ArrayItem`s. (#321)
Version 3.0.0 (2016-11-30)
--------------------------

View File

@ -144,6 +144,10 @@ The following methods, arguments or options have been removed:
### Miscellaneous
* The `NameResolver` will now resolve unqualified function and constant names in the global
namespace into fully qualified names. For example `foo()` in the global namespace resolves to
`\foo()`. For names where no static resolution is possible, a `namespacedName` attribute is
added now, containing the namespaced variant of the name.
* All methods on `PrettyPrinter\Standard` are now protected. Previoulsy most of them were public.
The pretty printer should only be invoked using the `prettyPrint()`, `prettyPrintFile()` and
`prettyPrintExpr()` methods.

View File

@ -33,7 +33,10 @@ $parser = (new PhpParser\ParserFactory)->create(
PhpParser\ParserFactory::PREFER_PHP7,
$lexer
);
$dumper = new PhpParser\NodeDumper(['dumpComments' => true]);
$dumper = new PhpParser\NodeDumper([
'dumpComments' => true,
'dumpPositions' => $attributes['with-positions'],
]);
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
$serializer = new PhpParser\Serializer\XML;
@ -75,7 +78,7 @@ foreach ($files as $file) {
foreach ($operations as $operation) {
if ('dump' === $operation) {
echo "==> Node dump:\n";
echo $dumper->dump($stmts), "\n";
echo $dumper->dump($stmts, $code), "\n";
} elseif ('pretty-print' === $operation) {
echo "==> Pretty print:\n";
echo $prettyPrinter->prettyPrintFile($stmts), "\n";
@ -117,6 +120,7 @@ Operations is a list of the following options (--dump by default):
--var-dump var_dump() nodes (for exact structure)
-N, --resolve-names Resolve names using NodeVisitor\NameResolver
-c, --with-column-info Show column-numbers for errors (if available)
-P, --with-positions Show positions in node dumps
-r, --with-recovery Use parsing with error recovery
-h, --help Display this page
@ -134,7 +138,8 @@ function parseArgs($args) {
$operations = array();
$files = array();
$attributes = array(
'with-column-info' => false,
'with-column-info' => false,
'with-positions' => false,
'with-recovery' => false,
);
@ -169,6 +174,10 @@ function parseArgs($args) {
case '-c';
$attributes['with-column-info'] = true;
break;
case '--with-positions':
case '-P':
$attributes['with-positions'] = true;
break;
case '--with-recovery':
case '-r':
$attributes['with-recovery'] = true;

View File

@ -56,11 +56,17 @@ top_statement:
| T_HALT_COMPILER
{ $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; }
| T_NAMESPACE namespace_name ';'
{ $$ = Stmt\Namespace_[$2, null]; $this->checkNamespace($$); }
{ $$ = Stmt\Namespace_[$2, null];
$$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON);
$this->checkNamespace($$); }
| T_NAMESPACE namespace_name '{' top_statement_list '}'
{ $$ = Stmt\Namespace_[$2, $4]; $this->checkNamespace($$); }
{ $$ = Stmt\Namespace_[$2, $4];
$$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
$this->checkNamespace($$); }
| T_NAMESPACE '{' top_statement_list '}'
{ $$ = Stmt\Namespace_[null, $3]; $this->checkNamespace($$); }
{ $$ = Stmt\Namespace_[null, $3];
$$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
$this->checkNamespace($$); }
| T_USE use_declarations ';' { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; }
| T_USE use_type use_declarations ';' { $$ = Stmt\Use_[$3, $2]; }
| group_use_declaration ';' { $$ = $1; }
@ -155,7 +161,15 @@ inner_statement:
;
non_empty_statement:
'{' inner_statement_list '}' { $$ = $2; prependLeadingComments($$); }
'{' inner_statement_list '}'
{
if ($2) {
$$ = $2; prependLeadingComments($$);
} else {
makeNop($$, $this->startAttributeStack[#1]);
if (null === $$) { $$ = array(); }
}
}
| T_IF parentheses_expr statement elseif_list else_single
{ $$ = Stmt\If_[$2, ['stmts' => toArray($3), 'elseifs' => $4, 'else' => $5]]; }
| T_IF parentheses_expr ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';'
@ -253,22 +267,22 @@ class_entry_type:
extends_from:
/* empty */ { $$ = null; }
| T_EXTENDS name { $$ = $2; }
| T_EXTENDS class_name { $$ = $2; }
;
interface_extends_list:
/* empty */ { $$ = array(); }
| T_EXTENDS name_list { $$ = $2; }
| T_EXTENDS class_name_list { $$ = $2; }
;
implements_list:
/* empty */ { $$ = array(); }
| T_IMPLEMENTS name_list { $$ = $2; }
| T_IMPLEMENTS class_name_list { $$ = $2; }
;
name_list:
name { init($1); }
| name_list ',' name { push($1, $3); }
class_name_list:
class_name { init($1); }
| class_name_list ',' class_name { push($1, $3); }
;
for_statement:
@ -440,7 +454,7 @@ class_statement:
| method_modifiers T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type method_body
{ $$ = Stmt\ClassMethod[$4, ['type' => $1, 'byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9]];
$this->checkClassMethod($$, #1); }
| T_USE name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; }
| T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; }
;
trait_adaptations:
@ -454,7 +468,7 @@ trait_adaptation_list:
;
trait_adaptation:
trait_method_reference_fully_qualified T_INSTEADOF name_list ';'
trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';'
{ $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; }
| trait_method_reference T_AS member_modifier identifier ';'
{ $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; }
@ -988,7 +1002,7 @@ encaps_var:
encaps_var_offset:
T_STRING { $$ = Scalar\String_[$1]; }
| T_NUM_STRING { $$ = Scalar\String_[$1]; }
| T_NUM_STRING { $$ = $this->parseNumString($1, attributes()); }
| T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; }
;

View File

@ -49,22 +49,42 @@ namespace_name:
namespace_name_parts { $$ = Name[$1]; }
;
semi:
';' { /* nothing */ }
| error { /* nothing */ }
;
no_comma:
/* empty */ { /* nothing */ }
| ',' { $this->emitError(new Error('A trailing comma is not allowed here', attributes())); }
;
optional_comma:
/* empty */
| ','
top_statement:
statement { $$ = $1; }
| function_declaration_statement { $$ = $1; }
| class_declaration_statement { $$ = $1; }
| T_HALT_COMPILER
{ $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; }
| T_NAMESPACE namespace_name ';'
{ $$ = Stmt\Namespace_[$2, null]; $this->checkNamespace($$); }
| T_NAMESPACE namespace_name semi
{ $$ = Stmt\Namespace_[$2, null];
$$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON);
$this->checkNamespace($$); }
| T_NAMESPACE namespace_name '{' top_statement_list '}'
{ $$ = Stmt\Namespace_[$2, $4]; $this->checkNamespace($$); }
{ $$ = Stmt\Namespace_[$2, $4];
$$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
$this->checkNamespace($$); }
| T_NAMESPACE '{' top_statement_list '}'
{ $$ = Stmt\Namespace_[null, $3]; $this->checkNamespace($$); }
| T_USE use_declarations ';' { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; }
| T_USE use_type use_declarations ';' { $$ = Stmt\Use_[$3, $2]; }
| group_use_declaration ';' { $$ = $1; }
| T_CONST constant_declaration_list ';' { $$ = Stmt\Const_[$2]; }
{ $$ = Stmt\Namespace_[null, $3];
$$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
$this->checkNamespace($$); }
| T_USE use_declarations semi { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; }
| T_USE use_type use_declarations semi { $$ = Stmt\Use_[$3, $2]; }
| group_use_declaration semi { $$ = $1; }
| T_CONST constant_declaration_list semi { $$ = Stmt\Const_[$2]; }
;
use_type:
@ -85,18 +105,31 @@ group_use_declaration:
;
unprefixed_use_declarations:
unprefixed_use_declarations ',' unprefixed_use_declaration
non_empty_unprefixed_use_declarations optional_comma { $$ = $1; }
;
non_empty_unprefixed_use_declarations:
non_empty_unprefixed_use_declarations ',' unprefixed_use_declaration
{ push($1, $3); }
| unprefixed_use_declaration { init($1); }
;
use_declarations:
use_declarations ',' use_declaration { push($1, $3); }
non_empty_use_declarations no_comma { $$ = $1; }
;
non_empty_use_declarations:
non_empty_use_declarations ',' use_declaration { push($1, $3); }
| use_declaration { init($1); }
;
inline_use_declarations:
inline_use_declarations ',' inline_use_declaration { push($1, $3); }
non_empty_inline_use_declarations optional_comma { $$ = $1; }
;
non_empty_inline_use_declarations:
non_empty_inline_use_declarations ',' inline_use_declaration
{ push($1, $3); }
| inline_use_declaration { init($1); }
;
@ -118,7 +151,12 @@ inline_use_declaration:
;
constant_declaration_list:
constant_declaration_list ',' constant_declaration { push($1, $3); }
non_empty_constant_declaration_list no_comma { $$ = $1; }
;
non_empty_constant_declaration_list:
non_empty_constant_declaration_list ',' constant_declaration
{ push($1, $3); }
| constant_declaration { init($1); }
;
@ -127,7 +165,11 @@ constant_declaration:
;
class_const_list:
class_const_list ',' class_const { push($1, $3); }
non_empty_class_const_list no_comma { $$ = $1; }
;
non_empty_class_const_list:
non_empty_class_const_list ',' class_const { push($1, $3); }
| class_const { init($1); }
;
@ -155,7 +197,15 @@ inner_statement:
;
non_empty_statement:
'{' inner_statement_list '}' { $$ = $2; prependLeadingComments($$); }
'{' inner_statement_list '}'
{
if ($2) {
$$ = $2; prependLeadingComments($$);
} else {
makeNop($$, $this->startAttributeStack[#1]);
if (null === $$) { $$ = array(); }
}
}
| T_IF '(' expr ')' statement elseif_list else_single
{ $$ = Stmt\If_[$3, ['stmts' => toArray($5), 'elseifs' => $6, 'else' => $7]]; }
| T_IF '(' expr ')' ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';'
@ -165,15 +215,15 @@ non_empty_statement:
| T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement
{ $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; }
| T_SWITCH '(' expr ')' switch_case_list { $$ = Stmt\Switch_[$3, $5]; }
| T_BREAK optional_expr ';' { $$ = Stmt\Break_[$2]; }
| T_CONTINUE optional_expr ';' { $$ = Stmt\Continue_[$2]; }
| T_RETURN optional_expr ';' { $$ = Stmt\Return_[$2]; }
| T_GLOBAL global_var_list ';' { $$ = Stmt\Global_[$2]; }
| T_STATIC static_var_list ';' { $$ = Stmt\Static_[$2]; }
| T_ECHO expr_list ';' { $$ = Stmt\Echo_[$2]; }
| T_BREAK optional_expr semi { $$ = Stmt\Break_[$2]; }
| T_CONTINUE optional_expr semi { $$ = Stmt\Continue_[$2]; }
| T_RETURN optional_expr semi { $$ = Stmt\Return_[$2]; }
| T_GLOBAL global_var_list semi { $$ = Stmt\Global_[$2]; }
| T_STATIC static_var_list semi { $$ = Stmt\Static_[$2]; }
| T_ECHO expr_list semi { $$ = Stmt\Echo_[$2]; }
| T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; }
| expr ';' { $$ = $1; }
| T_UNSET '(' variables_list ')' ';' { $$ = Stmt\Unset_[$3]; }
| expr semi { $$ = $1; }
| T_UNSET '(' variables_list ')' semi { $$ = Stmt\Unset_[$3]; }
| T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
{ $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; }
| T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement
@ -181,10 +231,9 @@ non_empty_statement:
| T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; }
| T_TRY '{' inner_statement_list '}' catches optional_finally
{ $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); }
| T_THROW expr ';' { $$ = Stmt\Throw_[$2]; }
| T_GOTO T_STRING ';' { $$ = Stmt\Goto_[$2]; }
| T_THROW expr semi { $$ = Stmt\Throw_[$2]; }
| T_GOTO T_STRING semi { $$ = Stmt\Goto_[$2]; }
| T_STRING ':' { $$ = Stmt\Label[$1]; }
| expr error { $$ = $1; }
| error { $$ = array(); /* means: no statement */ }
;
@ -216,8 +265,12 @@ optional_finally:
;
variables_list:
non_empty_variables_list no_comma { $$ = $1; }
;
non_empty_variables_list:
variable { init($1); }
| variables_list ',' variable { push($1, $3); }
| non_empty_variables_list ',' variable { push($1, $3); }
;
optional_ref:
@ -254,22 +307,26 @@ class_entry_type:
extends_from:
/* empty */ { $$ = null; }
| T_EXTENDS name { $$ = $2; }
| T_EXTENDS class_name { $$ = $2; }
;
interface_extends_list:
/* empty */ { $$ = array(); }
| T_EXTENDS name_list { $$ = $2; }
| T_EXTENDS class_name_list { $$ = $2; }
;
implements_list:
/* empty */ { $$ = array(); }
| T_IMPLEMENTS name_list { $$ = $2; }
| T_IMPLEMENTS class_name_list { $$ = $2; }
;
name_list:
name { init($1); }
| name_list ',' name { push($1, $3); }
class_name_list:
non_empty_class_name_list no_comma { $$ = $1; }
;
non_empty_class_name_list:
class_name { init($1); }
| non_empty_class_name_list ',' class_name { push($1, $3); }
;
for_statement:
@ -289,8 +346,12 @@ declare_statement:
;
declare_list:
non_empty_declare_list no_comma { $$ = $1; }
;
non_empty_declare_list:
declare_list_element { init($1); }
| declare_list ',' declare_list_element { push($1, $3); }
| non_empty_declare_list ',' declare_list_element { push($1, $3); }
;
declare_list_element:
@ -360,7 +421,7 @@ foreach_variable:
;
parameter_list:
non_empty_parameter_list { $$ = $1; }
non_empty_parameter_list no_comma { $$ = $1; }
| /* empty */ { $$ = array(); }
;
@ -399,7 +460,7 @@ optional_return_type:
argument_list:
'(' ')' { $$ = array(); }
| '(' non_empty_argument_list ')' { $$ = $2; }
| '(' non_empty_argument_list no_comma ')' { $$ = $2; }
;
non_empty_argument_list:
@ -414,7 +475,11 @@ argument:
;
global_var_list:
global_var_list ',' global_var { push($1, $3); }
non_empty_global_var_list no_comma { $$ = $1; }
;
non_empty_global_var_list:
non_empty_global_var_list ',' global_var { push($1, $3); }
| global_var { init($1); }
;
@ -423,7 +488,11 @@ global_var:
;
static_var_list:
static_var_list ',' static_var { push($1, $3); }
non_empty_static_var_list no_comma { $$ = $1; }
;
non_empty_static_var_list:
non_empty_static_var_list ',' static_var { push($1, $3); }
| static_var { init($1); }
;
@ -445,7 +514,7 @@ class_statement:
| method_modifiers T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type method_body
{ $$ = Stmt\ClassMethod[$4, ['type' => $1, 'byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9]];
$this->checkClassMethod($$, #1); }
| T_USE name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; }
| T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; }
;
trait_adaptations:
@ -459,7 +528,7 @@ trait_adaptation_list:
;
trait_adaptation:
trait_method_reference_fully_qualified T_INSTEADOF name_list ';'
trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';'
{ $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; }
| trait_method_reference T_AS member_modifier identifier ';'
{ $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; }
@ -509,8 +578,13 @@ member_modifier:
;
property_declaration_list:
non_empty_property_declaration_list no_comma { $$ = $1; }
;
non_empty_property_declaration_list:
property_declaration { init($1); }
| property_declaration_list ',' property_declaration { push($1, $3); }
| non_empty_property_declaration_list ',' property_declaration
{ push($1, $3); }
;
property_declaration:
@ -519,7 +593,11 @@ property_declaration:
;
expr_list:
expr_list ',' expr { push($1, $3); }
non_empty_expr_list no_comma { $$ = $1; }
;
non_empty_expr_list:
non_empty_expr_list ',' expr { push($1, $3); }
| expr { init($1); }
;
@ -638,8 +716,12 @@ lexical_vars:
;
lexical_var_list:
non_empty_lexical_var_list no_comma { $$ = $1; }
;
non_empty_lexical_var_list:
lexical_var { init($1); }
| lexical_var_list ',' lexical_var { push($1, $3); }
| non_empty_lexical_var_list ',' lexical_var { push($1, $3); }
;
lexical_var:
@ -699,7 +781,7 @@ constant:
/* We interpret and isolated FOO:: as an unfinished class constant fetch. It could also be
an unfinished static property fetch or unfinished scoped call. */
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM error
{ $$ = Expr\ClassConstFetch[$1, Expr\Error[]]; $this->errorState = 2; }
{ $$ = Expr\ClassConstFetch[$1, new Expr\Error(stackAttributes(#3))]; $this->errorState = 2; }
;
array_short_syntax:
@ -875,7 +957,8 @@ encaps_var:
encaps_var_offset:
T_STRING { $$ = Scalar\String_[$1]; }
| T_NUM_STRING { $$ = Scalar\String_[$1]; }
| T_NUM_STRING { $$ = $this->parseNumString($1, attributes()); }
| '-' T_NUM_STRING { $$ = $this->parseNumString('-' . $2, attributes()); }
| T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; }
;

View File

@ -205,7 +205,7 @@ function resolveMacros($code) {
assertArgs(1, $args, $name);
return '$attrs = $this->startAttributeStack[#1]; $stmts = ' . $args[0] . '; '
. 'if (!empty($attrs[\'comments\']) && isset($stmts[0])) {'
. 'if (!empty($attrs[\'comments\'])) {'
. '$stmts[0]->setAttribute(\'comments\', '
. 'array_merge($attrs[\'comments\'], $stmts[0]->getAttribute(\'comments\', []))); }';
}

View File

@ -9,6 +9,8 @@ abstract class FunctionLike extends Declaration
{
protected $returnByRef = false;
protected $params = array();
/** @var string|Node\Name|Node\NullableType|null */
protected $returnType = null;
/**
@ -59,7 +61,7 @@ abstract class FunctionLike extends Declaration
/**
* Sets the return type for PHP 7.
*
* @param string|Node\Name $type One of array, callable, string, int, float, bool, iterable,
* @param string|Node\Name|Node\NullableType $type One of array, callable, string, int, float, bool, iterable,
* or a class/interface name.
*
* @return $this The builder instance (for fluid interface)

View File

@ -10,6 +10,8 @@ class Method extends FunctionLike
{
protected $name;
protected $flags = 0;
/** @var array|null */
protected $stmts = array();
/**

View File

@ -6,7 +6,7 @@ use PhpParser;
use PhpParser\Node;
use PhpParser\Node\Stmt;
class Namespace_ extends PhpParser\BuilderAbstract
class Namespace_ extends Declaration
{
private $name;
private $stmts = array();
@ -33,27 +33,12 @@ class Namespace_ extends PhpParser\BuilderAbstract
return $this;
}
/**
* Adds multiple statements.
*
* @param array $stmts The statements to add
*
* @return $this The builder instance (for fluid interface)
*/
public function addStmts(array $stmts) {
foreach ($stmts as $stmt) {
$this->addStmt($stmt);
}
return $this;
}
/**
* Returns the built node.
*
* @return Node The built node
*/
public function getNode() {
return new Stmt\Namespace_($this->name, $this->stmts);
return new Stmt\Namespace_($this->name, $this->stmts, $this->attributes);
}
}

View File

@ -10,9 +10,14 @@ class Param extends PhpParser\BuilderAbstract
protected $name;
protected $default = null;
/** @var string|Node\Name|Node\NullableType|null */
protected $type = null;
protected $byRef = false;
protected $variadic = false;
/**
* Creates a parameter builder.
*
@ -38,7 +43,7 @@ class Param extends PhpParser\BuilderAbstract
/**
* Sets type hint for the parameter.
*
* @param string|Node\Name $type Type hint to use
* @param string|Node\Name|Node\NullableType $type Type hint to use
*
* @return $this The builder instance (for fluid interface)
*/
@ -62,6 +67,17 @@ class Param extends PhpParser\BuilderAbstract
return $this;
}
/**
* Make the parameter variadic
*
* @return $this The builder instance (for fluid interface)
*/
public function makeVariadic() {
$this->variadic = true;
return $this;
}
/**
* Returns the built parameter node.
*
@ -69,7 +85,7 @@ class Param extends PhpParser\BuilderAbstract
*/
public function getNode() {
return new Node\Param(
$this->name, $this->default, $this->type, $this->byRef
$this->name, $this->default, $this->type, $this->byRef, $this->variadic
);
}
}

View File

@ -8,6 +8,7 @@ use PhpParser\Node\Stmt;
class Trait_ extends Declaration
{
protected $name;
protected $uses = array();
protected $properties = array();
protected $methods = array();
@ -34,6 +35,8 @@ class Trait_ extends Declaration
$this->properties[] = $stmt;
} else if ($stmt instanceof Stmt\ClassMethod) {
$this->methods[] = $stmt;
} else if ($stmt instanceof Stmt\TraitUse) {
$this->uses[] = $stmt;
} else {
throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType()));
}
@ -49,7 +52,7 @@ class Trait_ extends Declaration
public function getNode() {
return new Stmt\Trait_(
$this->name, array(
'stmts' => array_merge($this->properties, $this->methods)
'stmts' => array_merge($this->uses, $this->properties, $this->methods)
), $this->attributes
);
}

View File

@ -60,9 +60,9 @@ abstract class BuilderAbstract implements Builder {
* In particular, builtin types are left as strings, custom types become Names and nullables
* are wrapped in NullableType nodes.
*
* @param Name|string $type The type to normalize
* @param Name|string|NullableType $type The type to normalize
*
* @return Name|string The normalized type
* @return Name|string|NullableType The normalized type
*/
protected function normalizeType($type) {
if (!is_string($type)) {
@ -80,7 +80,7 @@ abstract class BuilderAbstract implements Builder {
}
$builtinTypes = array(
'array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void'
'array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void', 'object'
);
$lowerType = strtolower($type);

View File

@ -185,15 +185,17 @@ class Lexer
return;
}
// Check for unterminated comment
$lastToken = $this->tokens[count($this->tokens) - 1];
if ($this->isUnterminatedComment($lastToken)) {
$errorHandler->handleError(new Error('Unterminated comment', [
'startLine' => $line - substr_count($lastToken[1], "\n"),
'endLine' => $line,
'startFilePos' => $filePos - \strlen($lastToken[1]),
'endFilePos' => $filePos,
]));
if (count($this->tokens) > 0) {
// Check for unterminated comment
$lastToken = $this->tokens[count($this->tokens) - 1];
if ($this->isUnterminatedComment($lastToken)) {
$errorHandler->handleError(new Error('Unterminated comment', [
'startLine' => $line - substr_count($lastToken[1], "\n"),
'endLine' => $line,
'startFilePos' => $filePos - \strlen($lastToken[1]),
'endFilePos' => $filePos,
]));
}
}
}
@ -358,7 +360,7 @@ class Lexer
if ('T_HASHBANG' === $name) {
// HHVM uses a special token for #! hashbang lines
$tokenMap[$i] = Tokens::T_INLINE_HTML;
} else if (defined($name = 'PhpParser\Parser\Tokens::' . $name)) {
} else if (defined($name = Tokens::class . '::' . $name)) {
// Other tokens can be mapped directly
$tokenMap[$i] = constant($name);
}

View File

@ -29,6 +29,8 @@ interface Node
* Sets line the node started in.
*
* @param int $line Line
*
* @deprecated
*/
public function setLine($line);

View File

@ -24,7 +24,7 @@ class ArrayDimFetch extends Expr
$this->dim = $dim;
}
public function getSubnodeNames() {
public function getSubNodeNames() {
return array('var', 'dim');
}
}

View File

@ -9,15 +9,15 @@ class ClassConstFetch extends Expr
{
/** @var Name|Expr Class name */
public $class;
/** @var string Constant name */
/** @var string|Error Constant name */
public $name;
/**
* Constructs a class const fetch node.
*
* @param Name|Expr $class Class name
* @param string $name Constant name
* @param array $attributes Additional attributes
* @param Name|Expr $class Class name
* @param string|Error $name Constant name
* @param array $attributes Additional attributes
*/
public function __construct($class, $name, array $attributes = array()) {
parent::__construct($attributes);

View File

@ -16,7 +16,7 @@ class Closure extends Expr implements FunctionLike
public $params;
/** @var ClosureUse[] use()s */
public $uses;
/** @var null|string|Node\Name Return type */
/** @var null|string|Node\Name|Node\NullableType Return type */
public $returnType;
/** @var Node[] Statements */
public $stmts;

View File

@ -23,7 +23,7 @@ interface FunctionLike extends Node
/**
* Get the declared return type or null
*
* @return null|string|Node\Name
* @return null|string|Node\Name|Node\NullableType
*/
public function getReturnType();

View File

@ -8,7 +8,6 @@ class Name extends NodeAbstract
{
/**
* @var string[] Parts of the name
* @deprecated Avoid directly accessing $parts, use methods instead.
*/
public $parts;

View File

@ -6,7 +6,7 @@ use PhpParser\NodeAbstract;
class Param extends NodeAbstract
{
/** @var null|string|Name Typehint */
/** @var null|string|Name|NullableType Typehint */
public $type;
/** @var bool Whether parameter is passed by reference */
public $byRef;
@ -20,12 +20,12 @@ class Param extends NodeAbstract
/**
* Constructs a parameter node.
*
* @param string $name Name
* @param null|Expr $default Default value
* @param null|string|Name $type Typehint
* @param bool $byRef Whether is passed by reference
* @param bool $variadic Whether this is a variadic argument
* @param array $attributes Additional attributes
* @param string $name Name
* @param null|Expr $default Default value
* @param null|string|Name|NullableType $type Typehint
* @param bool $byRef Whether is passed by reference
* @param bool $variadic Whether this is a variadic argument
* @param array $attributes Additional attributes
*/
public function __construct($name, Expr $default = null, $type = null, $byRef = false, $variadic = false, array $attributes = array()) {
parent::__construct($attributes);

View File

@ -30,7 +30,7 @@ class ClassConst extends Node\Stmt
public function isPublic() {
return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0
|| ($this->flags & Class_::VISIBILITY_MODIFER_MASK) === 0;
|| ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
}
public function isProtected() {

View File

@ -15,9 +15,9 @@ class ClassMethod extends Node\Stmt implements FunctionLike
public $name;
/** @var Node\Param[] Parameters */
public $params;
/** @var null|string|Node\Name Return type */
/** @var null|string|Node\Name|Node\NullableType Return type */
public $returnType;
/** @var Node[] Statements */
/** @var Node[]|null Statements */
public $stmts;
/** @deprecated Use $flags instead */
@ -69,7 +69,7 @@ class ClassMethod extends Node\Stmt implements FunctionLike
public function isPublic() {
return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0
|| ($this->flags & Class_::VISIBILITY_MODIFER_MASK) === 0;
|| ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
}
public function isProtected() {

View File

@ -14,7 +14,9 @@ class Class_ extends ClassLike
const MODIFIER_ABSTRACT = 16;
const MODIFIER_FINAL = 32;
const VISIBILITY_MODIFER_MASK = 7; // 1 | 2 | 4
const VISIBILITY_MODIFIER_MASK = 7; // 1 | 2 | 4
/** @deprecated */
const VISIBILITY_MODIFER_MASK = self::VISIBILITY_MODIFIER_MASK;
/** @var int Type */
public $flags;
@ -74,7 +76,7 @@ class Class_ extends ClassLike
* @internal
*/
public static function verifyModifier($a, $b) {
if ($a & self::VISIBILITY_MODIFER_MASK && $b & self::VISIBILITY_MODIFER_MASK) {
if ($a & self::VISIBILITY_MODIFIER_MASK && $b & self::VISIBILITY_MODIFIER_MASK) {
throw new Error('Multiple access type modifiers are not allowed');
}

View File

@ -13,7 +13,7 @@ class Function_ extends Node\Stmt implements FunctionLike
public $name;
/** @var Node\Param[] Parameters */
public $params;
/** @var null|string|Node\Name Return type */
/** @var null|string|Node\Name|Node\NullableType Return type */
public $returnType;
/** @var Node[] Statements */
public $stmts;

View File

@ -6,6 +6,10 @@ use PhpParser\Node;
class Namespace_ extends Node\Stmt
{
/* For use in the "kind" attribute */
const KIND_SEMICOLON = 1;
const KIND_BRACED = 2;
/** @var null|Node\Name Name */
public $name;
/** @var Node[] Statements */

View File

@ -34,7 +34,7 @@ class Property extends Node\Stmt
public function isPublic() {
return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0
|| ($this->flags & Class_::VISIBILITY_MODIFER_MASK) === 0;
|| ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
}
public function isProtected() {

View File

@ -21,7 +21,15 @@ abstract class NodeAbstract implements Node, \JsonSerializable
* @return string Type of the node
*/
public function getType() {
return strtr(substr(rtrim(get_class($this), '_'), 15), '\\', '_');
$className = rtrim(get_class($this), '_');
return strtr(
substr(
$className,
strpos($className, 'PhpParser\Node') + 15
),
'\\',
'_'
);
}
/**
@ -37,6 +45,8 @@ abstract class NodeAbstract implements Node, \JsonSerializable
* Sets line the node started in.
*
* @param int $line Line
*
* @deprecated
*/
public function setLine($line) {
$this->setAttribute('startLine', (int) $line);

View File

@ -13,6 +13,14 @@ class NodeTraverser implements NodeTraverserInterface
*/
const DONT_TRAVERSE_CHILDREN = 1;
/**
* If NodeVisitor::enterNode() or NodeVisitor::leaveNode() returns
* STOP_TRAVERSAL, traversal is aborted.
*
* The afterTraverse() method will still be invoked.
*/
const STOP_TRAVERSAL = 2;
/**
* If NodeVisitor::leaveNode() returns REMOVE_NODE for a node that occurs
* in an array, it will be removed from the array.
@ -25,6 +33,9 @@ class NodeTraverser implements NodeTraverserInterface
/** @var NodeVisitor[] Visitors */
protected $visitors;
/** @var bool Whether traversal should be stopped */
protected $stopTraversal;
/**
* Constructs a node traverser.
*/
@ -63,6 +74,8 @@ class NodeTraverser implements NodeTraverserInterface
* @return Node[] Traversed array of nodes
*/
public function traverse(array $nodes) {
$this->stopTraversal = false;
foreach ($this->visitors as $visitor) {
if (null !== $return = $visitor->beforeTraverse($nodes)) {
$nodes = $return;
@ -86,12 +99,18 @@ class NodeTraverser implements NodeTraverserInterface
if (is_array($subNode)) {
$subNode = $this->traverseArray($subNode);
if ($this->stopTraversal) {
break;
}
} elseif ($subNode instanceof Node) {
$traverseChildren = true;
foreach ($this->visitors as $visitor) {
$return = $visitor->enterNode($subNode);
if (self::DONT_TRAVERSE_CHILDREN === $return) {
$traverseChildren = false;
} else if (self::STOP_TRAVERSAL === $return) {
$this->stopTraversal = true;
break 2;
} else if (null !== $return) {
$subNode = $return;
}
@ -99,10 +118,17 @@ class NodeTraverser implements NodeTraverserInterface
if ($traverseChildren) {
$subNode = $this->traverseNode($subNode);
if ($this->stopTraversal) {
break;
}
}
foreach ($this->visitors as $visitor) {
if (null !== $return = $visitor->leaveNode($subNode)) {
$return = $visitor->leaveNode($subNode);
if (self::STOP_TRAVERSAL === $return) {
$this->stopTraversal = true;
break 2;
} else if (null !== $return) {
if (is_array($return)) {
throw new \LogicException(
'leaveNode() may only return an array ' .
@ -124,12 +150,18 @@ class NodeTraverser implements NodeTraverserInterface
foreach ($nodes as $i => &$node) {
if (is_array($node)) {
$node = $this->traverseArray($node);
if ($this->stopTraversal) {
break;
}
} elseif ($node instanceof Node) {
$traverseChildren = true;
foreach ($this->visitors as $visitor) {
$return = $visitor->enterNode($node);
if (self::DONT_TRAVERSE_CHILDREN === $return) {
$traverseChildren = false;
} else if (self::STOP_TRAVERSAL === $return) {
$this->stopTraversal = true;
break 2;
} else if (null !== $return) {
$node = $return;
}
@ -137,6 +169,9 @@ class NodeTraverser implements NodeTraverserInterface
if ($traverseChildren) {
$node = $this->traverseNode($node);
if ($this->stopTraversal) {
break;
}
}
foreach ($this->visitors as $visitor) {
@ -145,6 +180,9 @@ class NodeTraverser implements NodeTraverserInterface
if (self::REMOVE_NODE === $return) {
$doNodes[] = array($i, array());
break;
} else if (self::STOP_TRAVERSAL === $return) {
$this->stopTraversal = true;
break 2;
} elseif (is_array($return)) {
$doNodes[] = array($i, $return);
break;

View File

@ -21,12 +21,18 @@ interface NodeVisitor
* Called when entering a node.
*
* Return value semantics:
* * null: $node stays as-is
* * otherwise: $node is set to the return value
* * null
* => $node stays as-is
* * NodeTraverser::DONT_TRAVERSE_CHILDREN
* => Children of $node are not traversed. $node stays as-is
* * NodeTraverser::STOP_TRAVERSAL
* => Traversal is aborted. $node stays as-is
* * otherwise
* => $node is set to the return value
*
* @param Node $node Node
*
* @return null|Node Node
* @return null|int|Node Node
*/
public function enterNode(Node $node);
@ -34,14 +40,20 @@ interface NodeVisitor
* Called when leaving a node.
*
* Return value semantics:
* * null: $node stays as-is
* * false: $node is removed from the parent array
* * array: The return value is merged into the parent array (at the position of the $node)
* * otherwise: $node is set to the return value
* * null
* => $node stays as-is
* * NodeTraverser::REMOVE_NODE
* => $node is removed from the parent array
* * NodeTraverser::STOP_TRAVERSAL
* => Traversal is aborted. $node stays as-is
* * array (of Nodes)
* => The return value is merged into the parent array (at the position of the $node)
* * otherwise
* => $node is set to the return value
*
* @param Node $node Node
*
* @return null|Node|false|Node[] Node
* @return null|false|int|Node|Node[] Node
*/
public function leaveNode(Node $node);

View File

@ -22,13 +22,21 @@ class NameResolver extends NodeVisitorAbstract
/** @var ErrorHandler Error handler */
protected $errorHandler;
/** @var bool Whether to preserve original names */
protected $preserveOriginalNames;
/**
* Constructs a name resolution visitor.
*
* Options: If "preserveOriginalNames" is enabled, an "originalName" attribute will be added to
* all name nodes that underwent resolution.
*
* @param ErrorHandler|null $errorHandler Error handler
* @param array $options Options
*/
public function __construct(ErrorHandler $errorHandler = null) {
public function __construct(ErrorHandler $errorHandler = null, array $options = []) {
$this->errorHandler = $errorHandler ?: new ErrorHandler\Throwing;
$this->preserveOriginalNames = !empty($options['preserveOriginalNames']);
}
public function beforeTraverse(array $nodes) {
@ -112,7 +120,6 @@ class NameResolver extends NodeVisitorAbstract
}
}
}
}
}
@ -161,16 +168,30 @@ class NameResolver extends NodeVisitorAbstract
/** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */
private function resolveSignature($node) {
foreach ($node->params as $param) {
if ($param->type instanceof Name) {
$param->type = $this->resolveClassName($param->type);
}
$param->type = $this->resolveType($param->type);
}
if ($node->returnType instanceof Name) {
$node->returnType = $this->resolveClassName($node->returnType);
$node->returnType = $this->resolveType($node->returnType);
}
private function resolveType($node) {
if ($node instanceof Node\NullableType) {
$node->type = $this->resolveType($node->type);
return $node;
}
if ($node instanceof Name) {
return $this->resolveClassName($node);
}
return $node;
}
protected function resolveClassName(Name $name) {
if ($this->preserveOriginalNames) {
// Save the original name
$originalName = $name;
$name = clone $originalName;
$name->setAttribute('originalName', $originalName);
}
// don't resolve special class names
if (in_array(strtolower($name->toString()), array('self', 'parent', 'static'))) {
if (!$name->isUnqualified()) {
@ -179,7 +200,6 @@ class NameResolver extends NodeVisitorAbstract
$name->getAttributes()
));
}
return $name;
}
@ -200,6 +220,13 @@ class NameResolver extends NodeVisitorAbstract
}
protected function resolveOtherName(Name $name, $type) {
if ($this->preserveOriginalNames) {
// Save the original name
$originalName = $name;
$name = clone $originalName;
$name->setAttribute('originalName', $originalName);
}
// fully qualified names are already resolved
if ($name->isFullyQualified()) {
return $name;

View File

@ -18,8 +18,8 @@ use PhpParser\Node\Stmt;
class Php5 extends \PhpParser\ParserAbstract
{
protected $tokenToSymbolMapSize = 392;
protected $actionTableSize = 1012;
protected $gotoTableSize = 652;
protected $actionTableSize = 1020;
protected $gotoTableSize = 591;
protected $invalidSymbol = 157;
protected $errorSymbol = 1;
@ -235,278 +235,278 @@ class Php5 extends \PhpParser\ParserAbstract
protected $action = array(
672, 673, 674, 675, 676,-32766, 677, 678, 679, 715,
716, 216, 217, 218, 219, 220, 221, 222, 223, 224,
23, 225, 226, 227, 228, 229, 230, 231, 232, 233,
0, 225, 226, 227, 228, 229, 230, 231, 232, 233,
234, 235, 236,-32766,-32766,-32766,-32766,-32766,-32766,-32766,
-32766,-32767,-32767,-32767,-32767, 460, 237, 238,-32766,-32766,
-32766,-32766, 680,-32766, 0,-32766,-32766,-32766,-32766,-32766,
-32766,-32767,-32767,-32767,-32767, 441, 237, 238,-32766,-32766,
-32766,-32766, 680,-32766, 1036,-32766,-32766,-32766,-32766,-32766,
-32766,-32767,-32767,-32767,-32767,-32767, 681, 682, 683, 684,
685, 686, 687, 909, 204, 747,-32766,-32766,-32766,-32766,
-32766, 419, 688, 689, 690, 691, 692, 693, 694, 695,
685, 686, 687, 909, 329, 747,-32766,-32766,-32766,-32766,
-32766, 282, 688, 689, 690, 691, 692, 693, 694, 695,
696, 697, 698, 718, 719, 720, 721, 722, 710, 711,
712, 713, 714, 699, 700, 701, 702, 703, 704, 705,
741, 742, 743, 744, 745, 746, 706, 707, 708, 709,
739, 730, 728, 729, 725, 726, 306, 717, 723, 724,
739, 730, 728, 729, 725, 726, 1178, 717, 723, 724,
731, 732, 734, 733, 735, 736, 52, 53, 420, 54,
55, 727, 738, 737, 282, 56, 57, 284, 58,-32766,
55, 727, 738, 737, 23, 56, 57, 284, 58,-32766,
-32766,-32766,-32766,-32766,-32766,-32766,-32766,-32766, 7,-32767,
-32767,-32767,-32767, 50, 329, 900, 585, 945, 946, 947,
-32767,-32767,-32767, 50, 325,-32766, 585, 945, 946, 947,
944, 943, 942, 937, 1213, 27, 1215, 1214, 763, 764,
821, 59, 60,-32766,-32766,-32766, 918, 61, 1172, 62,
821, 59, 60,-32766,-32766,-32766, 809, 61, 1172, 62,
291, 292, 63, 64, 65, 66, 67, 68, 69, 70,
356, 24, 299, 71, 413,-32766,-32766,-32766, 1185, 1087,
334, 24, 299, 71, 413,-32766,-32766,-32766, 1185, 1087,
1088, 749, 633, 1178, 213, 214, 215, 464,-32766,-32766,
-32766, 822, 407, 1099, 311,-32766, 1054,-32766,-32766,-32766,
-32766,-32766,-32766, 1036, 200, -269, 428, 1036,-32766, 447,
-32766, 822, 407, 1099, 311,-32766, 1186,-32766,-32766,-32766,
-32766,-32766,-32766, 1036, 200, -269, 428,-32766,-32766,-32766,
-32766,-32766,-32766,-32766,-32766, 120, 491, 945, 946, 947,
944, 943, 942, 297, 473, 474, 283, 623, 125,-32766,
944, 943, 942, 306, 473, 474, 293, 623, 125,-32766,
893, 894, 339, 477, 478,-32766, 1093, 1094, 1095, 1096,
1090, 1091, 307, 492,-32766, 8, 425, 492, 1097, 1092,
425, 121, -220, 869, 1182, 39, 280, 332, 321, 1186,
1090, 1091, 307, 492,-32766, 440, 425, 492, 1097, 1092,
425, 121, -220, 869, 1182, 39, 280, 334, 321, 900,
322, 421, -122, -122, -122, -4, 822, 463, 99, 100,
101, 811, 301, 377, 38, 19, 422, -122, 465, -122,
101, 811, 301, 119, 38, 19, 422, -122, 465, -122,
466, -122, 467, -122, 102, 423, -122, -122, -122, 28,
29, 468, 424, 624, 30, 469, 425, 812, 72, 412,
923, 349, 350, 470, 471,-32766,-32766,-32766, 298, 472,
1036, 808, 793, 840, 475, 476,-32767,-32767,-32767,-32767,
29, 468, 424, 624, 30, 469, 425, 812, 72, 297,
923, 349, 350, 470, 471,-32766,-32766,-32766, 419, 472,
1036, 447, 793, 840, 475, 476,-32767,-32767,-32767,-32767,
94, 95, 96, 97, 98,-32766, 126,-32766,-32766,-32766,
-32766, 1137, 213, 214, 215, 295, 421, 239, 824, 638,
-122, 1036, 463, 893, 894, 1205, 811, 1036, 1204, 38,
19, 422, 200, 465, 18, 466, 492, 467, 127, 425,
19, 422, 200, 465, 356, 466, 492, 467, 127, 425,
423, 213, 214, 215, 28, 29, 468, 424, 414, 30,
469, 1036, 870, 72, 320, 822, 349, 350, 470, 471,
1036, 200, 214, 215, 472, 441, 919, 755, 840, 475,
476, 213, 214, 215, 295, -216, 76, 77, 78, 47,
338, 200, 477, 644, 348, 438, 31, 294, 331, 440,
326, 200, 241, 824, 638, -4, 32, 335, 79, 80,
34, 200, 214, 215, 472, 460, 762, 755, 840, 475,
476, 213, 214, 215, 295, -216, 76, 77, 78, 46,
298, 200, 412, 653, 338, 438, 31, 294, 333, 8,
348, 200, 241, 824, 638, -4, 32, 332, 79, 80,
81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
101, 1210, 301, 34, 822, 421, 801, 124,-32766,-32766,
-32766, 463, 899, 129, 102, 811, 1178, 576, 38, 19,
422, 546, 465, 1172, 466, 119, 467, 49,-32766, 423,
-32766,-32766, 647, 28, 29, 468, 822, 803, 30, 469,
415, 117, 72, 805, 46, 349, 350,-32766,-32766,-32766,
-32766,-32766,-32766, 472, 200, 1036, 234, 235, 236,-32766,
-32766,-32766,-32766,-32766, 641, 1138, 124,-32766,-32766,-32766,
-32766,-32766, 237, 238, 421, 231, 232, 233, 293,-32766,
463, 518, 856, 638, 811, 439, 809, 38, 19, 422,
332, 465, 128, 466, 749, 467, 1178, 339, 423, 96,
97, 98, 28, 29, 468, 822, 421, 30, 469, 118,
762, 72, 463, 215, 349, 350, 811, 242, 1036, 38,
19, 422, 472, 465, 206, 466, 116, 467, 1036, 1064,
423, 200, 833, 642, 28, 29, 468, 822, 1099, 30,
469, 296, 207, 72, 205, 123, 349, 350,-32766,-32766,
492, 824, 638, 425, 472, 115, 213, 214, 215, 434,
492, 244, 640, 425, 243, 653, 237, 238, 429,-32766,
332, 454, 591, 449, 20, 421, 200, 130, 357, 763,
764, 463, 820, 824, 638, 811, 922, 666, 38, 19,
422, 646, 465, 650, 466, 313, 467, 599, 600, 423,
102, 756, 643, 28, 29, 468, 822, 421, 30, 469,
934, 656, 72, 463, 301, 349, 350, 811, 41, 51,
38, 19, 422, 472, 465, 48, 466, 299, 467, 605,
42, 423, 43, 517, 44, 28, 29, 468, 45,-32766,
30, 469, 596, 524, 72, 435, 433, 349, 350, 533,
534, 749, 824, 638, 1208, 472, 776, 33, 103, 104,
101, 1210, 301, 204, 822, 421, 805, 124,-32766,-32766,
-32766, 463, 899, 1054, 102, 811, 18, 206, 38, 19,
422, 518, 465, 1172, 466, 546, 467, 47,-32766, 423,
-32766,-32766, 647, 28, 29, 468, 822, 801, 30, 469,
415, 116, 72, 803, 49, 349, 350,-32766,-32766,-32766,
-32766,-32766,-32766, 472, 477, 808, 234, 235, 236, 213,
214, 215, 1036, 215, 644, 1138, 124,-32766,-32766,-32766,
-32766,-32766, 237, 238, 421, 231, 232, 233, 1099, 200,
463, 200, 824, 638, 811, 439, 918, 38, 19, 422,
1036, 465, 242, 466, 749, 467, 1178, 339, 423, 96,
97, 98, 28, 29, 468, 822, 421, 30, 469, 117,
919, 72, 463, 283, 349, 350, 811, 244, 1036, 38,
19, 422, 472, 465, 243, 466, 118, 467, 377, 1064,
423, 1036, 207, 642, 28, 29, 468, 822, 129, 30,
469, 296, 576, 72,-32766,-32766, 349, 350, 123, 205,
492, 824, 638, 425, 472, 115,-32766,-32766,-32766, 434,
492, 200, 640, 425, 820, 641,-32766,-32766, 429,-32766,
334, 237, 238, 454, 591, 421,-32766, 130, 357, 449,
20, 463, 128, 856, 638, 811, 763, 764, 38, 19,
422, 313, 465, 646, 466, 650, 467, 599, 600, 423,
833, 301, 605, 28, 29, 468, 822, 421, 30, 469,
756, 643, 72, 463, 299, 349, 350, 811, 922, 666,
38, 19, 422, 472, 465, 102, 466, 51, 467, 934,
656, 423, 512, 433, 48, 28, 29, 468, 41, 42,
30, 469, 43, 44, 72, 45, 435, 349, 350, 1057,
750, 1208, 824, 638, 776, 472, 749, 33, 103, 104,
105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
750, 513, 512, 437, 632, 602, 421, 1057, 622, 612,
516, 619, 463, 279, 824, 638, 811, 582, 595, 38,
19, 422, 330, 465, 579, 466, 240, 467, 975, 977,
423, 609, 334, 537, 28, 29, 468, 12, -80, 30,
469, 842, 432, 72, 208, 209, 349, 350, 458, 1144,
210, 384, 211, 327, 472, 841, 9, 393, -398, 409,
328, 0, 310, 1045, 202, 477, 0, 0, 0, 208,
209, 0, 1087, 1088, 0, 210,-32766, 211, -497, 312,
1089, -498, 0, 824, 638, 0, 1098, 4, 372, 202,
3, 11, 303, 0, -407, 0, 370, 1087, 1088, -406,
-497,-32766, 434, 864, 526, 1089, 408, 385, 75, 835,
0, 857, 863, 854, 813, 798, 819, 807, 761, 661,
0, 660, 37, 36, 759, 926, 810, 565, 852, 1093,
1094, 1095, 1096, 1090, 1091, 383, 929, 806, 930, 818,
760, 1097, 1092, 928, 804, 302, 802, 927, 212, 796,
-32766, 872, 565, 639, 1093, 1094, 1095, 1096, 1090, 1091,
383, 649, 651, 652, 654, 655, 1097, 1092, 658, 663,
664, 1034, 665, 212, 122,-32766, 324, 325, 405, 406,
-416, 1211, 757, 758, 839, 838, 766, 453, 1209, 1179,
1177, 1163, 1175, 1078, 911, 1183, 1173, 829, 836, 1038,
1039, 827, 935, 1212, 765, 837, 794, 662, 1050, 861,
768, 767, 862, 0, 304, 290, 289, 25, 26, 281,
305, 336, 203, 74, 411, 417, 35, 73,-32766, 40,
22, 0, 1015, 569, -217, 1016, 1103, 1080, 901, 1040,
1044, 1041, 629, 559, 461, 457, 455, 450, 378, 16,
15, 14, -216, 0, 0, 0, 603, 1157, 1104, 1207,
1077, 1174, 1158, 1162, 1176, 1063, 1048, 1049, 1046, 1047,
0, 1143
534, 533, 517, 513, 524, 437, 421, 602, 516, 622,
612, 619, 463, 582, 824, 638, 811, 595,-32766, 38,
19, 422, 632, 465, 579, 466, 240, 467, 975, 977,
423, 609, 1144, 279, 28, 29, 468, 12, -80, 30,
469, 537, 432, 72, 208, 209, 349, 350, 458, 1098,
210, 596, 211, 328, 472, 326, 11, 842, 323, 393,
4, 385, 408, 303, 202, 1034, 0, 0, 324, 208,
209, 841, 1087, 1088, 0, 210,-32766, 211, -497, -498,
1089, 312, 310, 824, 638, 477, 0, 0, 0, 202,
0, -398, 0, 0, 9, 0, 0, 1087, 1088, 3,
-497,-32766, -406, 370, -407, 1089, 835, 639, 0, 384,
372, 409, 526, 434, 0, 0, 864, 857, 863, 872,
0, 813, 798, 819, 807, 761, 661, 565, 760, 1093,
1094, 1095, 1096, 1090, 1091, 383, 37, 36, 759, 926,
810, 1097, 1092, 854, 852, 302, 806, 929, 212, 818,
-32766, 930, 565, 928, 1093, 1094, 1095, 1096, 1090, 1091,
383, 927, 796, 804, 660, 802, 1097, 1092, 649, 651,
75, 0, 652, 212, 654,-32766, 655, 658, 663, 664,
665, 405, 122, 330, 331, 406, 0, 1211, 757, 758,
839, 838, 766, 453, 1209, 1179, 1177, 1163, 1175, 1078,
911, 1183, 1173, 829, 836, 1038, 1039, 827, 935, 1212,
765, 837, 794, 662, 1050, 768, 767, 861, 862, 0,
304, 290, 289, 25, 26, 281, 203, 74, 305, 336,
411, 417, 35, 73,-32766, 40, 22, 0, 1015, 569,
-217, 1016, 1103, 1080, 901, 1040, 1044, 1041, 629, 559,
461, 457, 455, 450, 378, 16, 15, 14, -216, 0,
0, -416, 0, 1045, 603, 1157, 1104, 1207, 1077, 1174,
1158, 1162, 1176, 1063, 1048, 1049, 1046, 1047, 0, 1143
);
protected $actionCheck = array(
2, 3, 4, 5, 6, 8, 8, 9, 10, 11,
12, 31, 32, 33, 34, 35, 36, 37, 38, 39,
7, 41, 42, 43, 44, 45, 46, 47, 48, 49,
0, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 8, 9, 10, 31, 32, 33, 34,
35, 36, 37, 38, 39, 7, 66, 67, 31, 32,
33, 34, 54, 28, 0, 30, 31, 32, 33, 34,
33, 34, 54, 28, 12, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 68, 69, 70, 71,
72, 73, 74, 79, 7, 77, 31, 32, 33, 34,
35, 7, 84, 85, 86, 87, 88, 89, 90, 91,
92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
122, 123, 124, 125, 126, 127, 7, 129, 130, 131,
122, 123, 124, 125, 126, 127, 79, 129, 130, 131,
132, 133, 134, 135, 136, 137, 2, 3, 4, 5,
6, 143, 144, 145, 7, 11, 12, 153, 14, 31,
32, 33, 34, 35, 36, 37, 38, 39, 103, 41,
42, 43, 44, 67, 109, 152, 82, 112, 113, 114,
42, 43, 44, 67, 109, 79, 82, 112, 113, 114,
115, 116, 117, 118, 77, 7, 79, 80, 102, 103,
1, 47, 48, 8, 9, 10, 148, 53, 79, 55,
56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
7, 67, 68, 69, 70, 8, 9, 10, 1, 75,
153, 67, 68, 69, 70, 8, 9, 10, 1, 75,
76, 77, 77, 79, 8, 9, 10, 83, 8, 9,
10, 1, 146, 139, 128, 28, 152, 30, 31, 32,
33, 34, 35, 12, 28, 79, 102, 12, 28, 7,
33, 34, 35, 12, 28, 79, 102, 151, 28, 153,
30, 31, 32, 33, 34, 149, 112, 112, 113, 114,
115, 116, 117, 7, 120, 121, 35, 77, 149, 103,
130, 131, 153, 129, 130, 109, 132, 133, 134, 135,
136, 137, 138, 143, 118, 7, 146, 143, 144, 145,
146, 7, 152, 29, 77, 151, 13, 153, 154, 152,
156, 71, 72, 73, 74, 0, 1, 77, 50, 51,
52, 81, 54, 78, 84, 85, 86, 87, 88, 89,
52, 81, 54, 13, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 66, 95, 96, 97, 98, 99,
100, 101, 102, 143, 104, 105, 146, 148, 108, 7,
150, 111, 112, 113, 114, 8, 9, 10, 35, 119,
12, 148, 122, 123, 124, 125, 41, 42, 43, 44,
150, 111, 112, 113, 114, 8, 9, 10, 7, 119,
12, 7, 122, 123, 124, 125, 41, 42, 43, 44,
45, 46, 47, 48, 49, 28, 149, 30, 31, 32,
33, 155, 8, 9, 10, 35, 71, 13, 148, 149,
150, 12, 77, 130, 131, 79, 81, 12, 82, 84,
85, 86, 28, 88, 152, 90, 143, 92, 67, 146,
85, 86, 28, 88, 7, 90, 143, 92, 67, 146,
95, 8, 9, 10, 99, 100, 101, 102, 103, 104,
105, 12, 148, 108, 109, 1, 111, 112, 113, 114,
12, 28, 9, 10, 119, 7, 148, 122, 123, 124,
13, 28, 9, 10, 119, 7, 148, 122, 123, 124,
125, 8, 9, 10, 35, 152, 8, 9, 10, 67,
67, 28, 129, 29, 7, 29, 140, 141, 143, 7,
35, 28, 7, 29, 67, 29, 140, 141, 143, 7,
7, 28, 29, 148, 149, 150, 28, 7, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 150, 54, 13, 1, 71, 148, 147, 8, 9,
10, 77, 152, 149, 66, 81, 79, 153, 84, 85,
86, 128, 88, 79, 90, 13, 92, 67, 28, 95,
52, 150, 54, 7, 1, 71, 148, 147, 8, 9,
10, 77, 152, 152, 66, 81, 152, 15, 84, 85,
86, 82, 88, 79, 90, 128, 92, 67, 28, 95,
30, 31, 29, 99, 100, 101, 1, 148, 104, 105,
123, 149, 108, 148, 67, 111, 112, 8, 9, 10,
31, 32, 33, 119, 28, 12, 50, 51, 52, 8,
9, 10, 8, 9, 29, 152, 147, 28, 151, 30,
31, 32, 66, 67, 71, 47, 48, 49, 35, 28,
77, 82, 148, 149, 81, 149, 148, 84, 85, 86,
153, 88, 29, 90, 77, 92, 79, 153, 95, 47,
31, 32, 33, 119, 129, 148, 50, 51, 52, 8,
9, 10, 12, 10, 29, 152, 147, 28, 151, 30,
31, 32, 66, 67, 71, 47, 48, 49, 139, 28,
77, 28, 148, 149, 81, 149, 148, 84, 85, 86,
12, 88, 15, 90, 77, 92, 79, 153, 95, 47,
48, 49, 99, 100, 101, 1, 71, 104, 105, 149,
148, 108, 77, 10, 111, 112, 81, 15, 12, 84,
85, 86, 119, 88, 15, 90, 149, 92, 12, 112,
95, 28, 35, 29, 99, 100, 101, 1, 139, 104,
105, 35, 15, 108, 15, 29, 111, 112, 31, 32,
148, 108, 77, 35, 111, 112, 81, 15, 12, 84,
85, 86, 119, 88, 15, 90, 149, 92, 78, 112,
95, 12, 15, 29, 99, 100, 101, 1, 149, 104,
105, 35, 153, 108, 31, 32, 111, 112, 29, 15,
143, 148, 149, 146, 119, 15, 8, 9, 10, 146,
143, 15, 149, 146, 15, 29, 66, 67, 151, 31,
153, 72, 73, 72, 73, 71, 28, 97, 98, 102,
103, 77, 29, 148, 149, 81, 148, 149, 84, 85,
143, 28, 149, 146, 29, 29, 8, 9, 151, 31,
153, 66, 67, 72, 73, 71, 28, 97, 98, 72,
73, 77, 29, 148, 149, 81, 102, 103, 84, 85,
86, 29, 88, 29, 90, 29, 92, 106, 107, 95,
66, 148, 149, 99, 100, 101, 1, 71, 104, 105,
148, 149, 108, 77, 54, 111, 112, 81, 67, 67,
84, 85, 86, 119, 88, 67, 90, 68, 92, 74,
67, 95, 67, 77, 67, 99, 100, 101, 67, 82,
104, 105, 109, 82, 108, 77, 77, 111, 112, 77,
35, 54, 74, 99, 100, 101, 1, 71, 104, 105,
148, 149, 108, 77, 68, 111, 112, 81, 148, 149,
84, 85, 86, 119, 88, 66, 90, 67, 92, 148,
149, 95, 77, 77, 67, 99, 100, 101, 67, 67,
104, 105, 67, 67, 108, 67, 77, 111, 112, 79,
77, 77, 148, 149, 77, 119, 77, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
77, 77, 77, 86, 89, 79, 71, 79, 79, 79,
79, 91, 77, 94, 148, 149, 81, 96, 96, 84,
85, 86, 110, 88, 87, 90, 29, 92, 56, 57,
95, 93, 126, 94, 99, 100, 101, 94, 94, 104,
105, 123, 102, 108, 47, 48, 111, 112, 102, 139,
53, 146, 55, 126, 119, 123, 142, 146, 142, 146,
127, -1, 128, 155, 67, 129, -1, -1, -1, 47,
48, -1, 75, 76, -1, 53, 79, 55, 128, 128,
83, 128, -1, 148, 149, -1, 139, 142, 146, 67,
142, 142, 151, -1, 142, -1, 142, 75, 76, 142,
128, 79, 146, 148, 146, 83, 146, 146, 149, 147,
-1, 148, 148, 148, 148, 148, 148, 148, 148, 148,
77, 77, 77, 77, 82, 86, 71, 79, 79, 79,
79, 91, 77, 96, 148, 149, 81, 96, 82, 84,
85, 86, 89, 88, 87, 90, 29, 92, 56, 57,
95, 93, 139, 94, 99, 100, 101, 94, 94, 104,
105, 94, 102, 108, 47, 48, 111, 112, 102, 139,
53, 109, 55, 126, 119, 110, 142, 123, 126, 146,
142, 146, 146, 151, 67, 154, -1, -1, 127, 47,
48, 123, 75, 76, -1, 53, 79, 55, 128, 128,
83, 128, 128, 148, 149, 129, -1, -1, -1, 67,
-1, 142, -1, -1, 142, -1, -1, 75, 76, 142,
128, 79, 142, 142, 142, 83, 147, 149, -1, 146,
146, 146, 146, 146, -1, -1, 148, 148, 148, 148,
-1, 148, 148, 148, 148, 148, 148, 130, 148, 132,
133, 134, 135, 136, 137, 138, 148, 148, 148, 148,
148, 144, 145, 148, 148, 151, 148, 148, 151, 148,
153, 148, 130, 149, 132, 133, 134, 135, 136, 137,
138, 149, 149, 149, 149, 149, 144, 145, 149, 149,
149, 154, 149, 151, 149, 153, 149, 149, 149, 149,
154, 150, 150, 150, 150, 150, 150, 150, 150, 150,
153, 148, 130, 148, 132, 133, 134, 135, 136, 137,
138, 148, 148, 148, 148, 148, 144, 145, 149, 149,
149, -1, 149, 151, 149, 153, 149, 149, 149, 149,
149, 149, 149, 149, 149, 149, -1, 150, 150, 150,
150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
150, 150, 150, -1, 151, 151, 151, 151, 151, 151,
150, 150, 150, 150, 150, 150, 150, 150, 150, -1,
151, 151, 151, 151, 151, 151, 151, 151, 151, 151,
151, -1, 152, 152, 152, 152, 152, 152, 152, 152,
151, 151, 151, 151, 151, 151, 151, -1, 152, 152,
152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
152, 152, 152, -1, -1, -1, 155, 155, 155, 155,
155, 155, 155, 155, 155, 155, 155, 155, 155, 155,
-1, 156
152, 152, 152, 152, 152, 152, 152, 152, 152, -1,
-1, 154, -1, 155, 155, 155, 155, 155, 155, 155,
155, 155, 155, 155, 155, 155, 155, 155, -1, 156
);
protected $actionBase = array(
0, 220, 295, 109, 109, 180, 735, -2, -2, -2,
-2, -2, 135, 574, 473, 606, 473, 505, 404, 675,
675, 675, 330, 389, 513, 513, 825, 513, 328, 359,
365, 225, 586, 221, 576, 398, 398, 398, 398, 134,
134, 398, 398, 398, 398, 398, 398, 398, 398, 398,
398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
398, 254, 179, 482, 460, 738, 736, 729, 731, 827,
659, 823, 778, 779, 533, 780, 781, 782, 783, 784,
777, 785, 841, 786, 418, 418, 418, 418, 418, 418,
0, 220, 295, 109, 109, 180, 745, -2, -2, -2,
-2, -2, 135, 574, 473, 404, 473, 606, 505, 675,
675, 675, 330, 389, 221, 221, 831, 221, 359, 365,
328, 520, 589, 548, 576, 42, 42, 42, 42, 134,
134, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
42, 254, 179, 290, 397, 757, 755, 738, 741, 833,
679, 829, 784, 785, 623, 786, 787, 788, 789, 790,
783, 791, 849, 792, 418, 418, 418, 418, 418, 418,
418, 418, 418, 418, 418, -3, 354, 383, 413, 206,
524, 618, 618, 618, 618, 618, 618, 618, 175, 175,
628, 521, 521, 521, 521, 521, 521, 521, 175, 175,
175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
175, 175, 175, 175, 175, 403, 521, 521, 521, 573,
737, 496, 762, 762, 762, 762, 762, 762, 762, 762,
175, 175, 175, 175, 175, 403, 618, 618, 618, 523,
737, 603, 762, 762, 762, 762, 762, 762, 762, 762,
762, 762, 762, 762, 762, 762, 762, 762, 762, 762,
762, 762, 762, 762, 762, 762, 762, 762, 762, 762,
762, 762, 762, 762, 762, 762, 762, 762, 762, 762,
762, 762, 762, 762, 762, 470, -20, -20, 509, 608,
327, 587, 210, 489, 197, 25, 25, 25, 25, 25,
327, 583, 210, 489, 197, 25, 25, 25, 25, 25,
17, 45, 5, 5, 5, 5, 712, 305, 305, 305,
305, 118, 118, 118, 118, 774, 775, 795, 798, 303,
303, 676, 676, 629, 765, 522, 522, 498, 498, 487,
305, 118, 118, 118, 118, 780, 781, 801, 804, 395,
395, 696, 696, 616, 773, 522, 522, 498, 498, 487,
487, 487, 487, 487, 487, 487, 487, 487, 487, 387,
156, 817, 130, 130, 130, 130, 243, 469, 650, 855,
156, 823, 130, 130, 130, 130, 243, 409, 633, 863,
207, 207, 207, 243, 248, 248, 248, 476, 476, 476,
76, 631, 296, 296, 547, 547, 547, 477, 477, 477,
477, 483, 699, 627, 477, 477, 477, 362, 97, 334,
661, 799, 662, 802, 508, 692, 96, 700, 653, -6,
680, 571, 569, 561, 656, 406, -6, 254, 532, 430,
630, 718, 643, 432, 716, 193, 408, 363, 523, 447,
414, 232, 767, 732, 821, 820, 137, 321, 693, 630,
630, 630, 13, 84, 768, 769, 447, 273, 570, 570,
570, 570, 801, 770, 570, 570, 570, 570, 800, 794,
268, 38, 776, 74, 717, 644, 644, 644, 644, 644,
644, 567, 644, 807, 664, 819, 819, 642, 666, 567,
818, 818, 818, 818, 567, 644, 819, 819, 567, 629,
819, 168, 567, 667, 644, 646, 646, 818, 713, 711,
664, 671, 673, 819, 819, 819, 673, 642, 567, 818,
603, 702, 67, 819, 818, 636, 636, 603, 567, 636,
666, 636, 54, 623, 621, 815, 816, 814, 665, 744,
672, 658, 805, 804, 812, 626, 639, 808, 806, 698,
710, 709, 638, 610, 633, 635, 637, 641, 688, 628,
674, 680, 696, 604, 604, 604, 690, 685, 690, 604,
604, 604, 604, 604, 604, 604, 604, 648, 694, 697,
691, 657, 708, 599, 682, 679, 579, 759, 687, 698,
698, 796, 829, 836, 766, 757, 663, 734, 831, 690,
854, 715, 274, 597, 681, 797, 645, 649, 701, 690,
803, 690, 760, 690, 828, 793, 647, 698, 773, 604,
826, 853, 852, 851, 850, 849, 848, 847, 846, 622,
845, 707, 677, 835, 119, 811, 656, 654, 651, 706,
440, 844, 772, 690, 690, 761, 699, 690, 763, 743,
714, 839, 704, 834, 843, 687, 833, 690, 686, 842,
440, 632, 625, 822, 678, 695, 813, 670, 824, 810,
752, 572, 619, 771, 634, 741, 838, 837, 840, 703,
753, 754, 616, 660, 668, 669, 787, 755, 809, 705,
788, 789, 830, 684, 696, 689, 652, 683, 655, 756,
790, 832, 720, 728, 730, 791, 739, 792, 0, 0,
76, 662, 296, 86, 86, 86, 86, 296, 86, 86,
554, 554, 554, 483, 761, 676, 477, 430, 97, 459,
657, 807, 661, 808, 540, 702, 96, 656, 705, -6,
680, 577, 571, 561, 689, 406, -6, 254, 551, 447,
617, 732, 663, 268, 730, 377, 38, 367, 532, 362,
414, 334, 774, 720, 827, 826, 74, 321, 691, 617,
617, 617, 137, 84, 775, 772, 362, 273, 575, 575,
575, 575, 806, 776, 575, 575, 575, 575, 805, 800,
432, 408, 782, 331, 731, 649, 649, 649, 649, 649,
649, 635, 649, 813, 666, 825, 825, 664, 668, 635,
824, 824, 824, 824, 635, 649, 825, 825, 635, 616,
825, 168, 635, 672, 649, 667, 667, 824, 756, 718,
666, 669, 681, 825, 825, 825, 681, 664, 635, 824,
682, 699, 466, 825, 824, 632, 632, 682, 635, 632,
668, 632, 20, 605, 641, 821, 822, 820, 625, 698,
688, 674, 811, 810, 816, 665, 626, 814, 812, 706,
717, 716, 639, 610, 642, 645, 646, 648, 697, 637,
694, 680, 707, 629, 629, 629, 690, 658, 690, 629,
629, 629, 629, 629, 629, 629, 629, 848, 700, 701,
693, 659, 715, 604, 704, 687, 472, 768, 650, 706,
706, 802, 835, 842, 847, 651, 643, 734, 837, 690,
862, 729, 274, 587, 652, 803, 703, 647, 655, 690,
809, 690, 769, 690, 834, 799, 644, 706, 779, 629,
832, 861, 860, 859, 858, 857, 856, 855, 854, 630,
853, 714, 677, 841, 246, 815, 689, 692, 653, 713,
67, 852, 778, 690, 690, 770, 761, 690, 771, 711,
728, 845, 710, 840, 851, 650, 839, 690, 686, 850,
67, 634, 598, 828, 678, 708, 819, 671, 830, 818,
759, 547, 579, 777, 636, 754, 844, 843, 846, 709,
760, 763, 572, 660, 640, 670, 793, 765, 817, 735,
794, 795, 836, 684, 707, 654, 685, 683, 673, 767,
796, 838, 736, 739, 743, 797, 753, 798, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 134, 134,
@ -539,18 +539,18 @@ class Php5 extends \PhpParser\ParserAbstract
-20, -20, -20, 0, 248, 248, 248, 248, -20, -20,
-20, -20, 55, 55, 55, 55, 487, 487, 487, 487,
487, 487, 248, 248, 476, 476, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 487, 55, 487, 644,
644, 644, 644, 644, 296, 296, 296, 407, 407, 407,
644, 0, 0, 0, 0, 0, 0, 644, 296, 0,
0, 644, 644, 644, 644, 644, 644, 644, 644, 407,
296, 644, 644, 644, 819, 0, 407, 550, 550, 550,
550, 440, 447, 0, 644, 644, 0, 671, 0, 0,
0, 819, 0, 0, 0, 0, 0, 604, 274, 734,
0, 427, 0, 0, 0, 0, 0, 0, 0, 663,
427, 246, 246, 0, 0, 622, 604, 604, 604, 0,
0, 663, 663, 0, 0, 0, 0, 0, 0, 433,
663, 0, 0, 0, 0, 433, 322, 0, 0, 322,
0, 440
0, 0, 0, 0, 0, 0, 487, 55, 487, 649,
649, 649, 649, 649, 296, 296, 296, 47, 47, 47,
649, 0, 0, 0, 0, 0, 0, 649, 296, 0,
487, 487, 487, 487, 0, 487, 487, 649, 649, 649,
649, 47, 296, 649, 825, 0, 47, 550, 550, 550,
550, 67, 362, 0, 649, 649, 0, 669, 0, 0,
0, 825, 0, 0, 0, 0, 0, 629, 274, 734,
0, 433, 0, 0, 0, 0, 0, 0, 0, 643,
433, 322, 322, 0, 0, 630, 629, 629, 629, 0,
0, 643, 643, 0, 0, 0, 0, 0, 0, 440,
643, 0, 0, 0, 0, 440, 425, 0, 0, 425,
0, 67
);
protected $actionDefault = array(
@ -586,7 +586,7 @@ class Php5 extends \PhpParser\ParserAbstract
32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
272,32767, 228, 228, 228, 228, 228,32767,32767,32767,
32767,32767,32767,32767, 321, 322, 320, 448, 449, 447,
32767, 415,32767, 417,32767,32767,32767,32767,32767,32767,
32767, 415,32767,32767,32767,32767,32767, 417,32767,32767,
32767,32767,32767,32767,32767,32767,32767, 486,32767,32767,
32767,32767,32767,32767,32767, 499, 404,32767,32767,32767,
397, 212, 214, 161, 472,32767,32767,32767,32767, 504,
@ -604,7 +604,7 @@ class Php5 extends \PhpParser\ParserAbstract
32767,32767,32767,32767,32767,32767,32767,32767,32767, 399,
32767,32767,32767,32767, 365, 366, 475, 488,32767, 489,
32767, 397,32767, 329, 330, 332, 309,32767, 311, 355,
356, 357, 358, 359, 360, 361, 363,32767,32767, 402,
356, 357, 358, 359, 360, 361, 363,32767, 402,32767,
405,32767,32767,32767, 84, 108, 247,32767, 537, 84,
400,32767,32767, 294, 537,32767,32767,32767,32767, 532,
32767,32767, 288,32767,32767,32767, 84,32767, 84, 243,
@ -635,61 +635,55 @@ class Php5 extends \PhpParser\ParserAbstract
549, 182, 183, 184, 185, 186, 187, 188, 189, 190,
191, 192, 193, 194, 145, 146, 147, 161, 148, 163,
149, 197, 164, 150, 151, 152, 198, 153, 131, 625,
567, 753, 567, 567, 567, 567, 567, 567, 567, 567,
567, 754, 567, 567, 567, 567, 567, 567, 567, 567,
567, 567, 567, 567, 567, 567, 567, 567, 567, 567,
567, 567, 567, 567, 567, 567, 567, 567, 567, 567,
567, 567, 567, 567, 567, 567, 567, 567, 567, 567,
567, 567, 567, 567, 567, 1100, 754, 1100, 1100, 1100,
567, 567, 567, 567, 567, 1100, 753, 1100, 1100, 1100,
1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100,
1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100,
1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100,
1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100,
885, 885, 1190, 1190, 6, 611, 784, 168, 617, 509,
358, 509, 171, 172, 173, 388, 389, 390, 391, 167,
523, 784, 497, 497, 497, 497, 497, 497, 6, 508,
634, 508, 497, 497, 497, 497, 497, 497, 497, 497,
497, 497, 509, 550, 509, 580, 606, 522, 885, 885,
1190, 1190, 815, 849, 849, 849, 849, 168, 844, 850,
522, 522, 171, 172, 173, 388, 389, 390, 391, 167,
195, 199, 201, 249, 251, 253, 260, 261, 262, 263,
264, 265, 271, 272, 273, 274, 287, 288, 317, 318,
319, 394, 395, 396, 397, 169, 174, 246, 247, 175,
176, 177, 497, 497, 497, 497, 497, 497, 341, 580,
606, 523, 497, 497, 497, 497, 497, 497, 497, 497,
497, 497, 508, 634, 508, 387, 608, 543, 543, 573,
539, 1076, 1075, 790, 752, 541, 541, 496, 498, 529,
545, 574, 577, 587, 593, 871, 1169, 851, 1169, 657,
815, 511, 880, 875, 566, 855, 566, 566, 566, 566,
176, 177, 387, 608, 543, 543, 573, 539, 583, 586,
631, 855, 541, 541, 496, 498, 529, 545, 574, 577,
587, 593, 341, 1169, 566, 1169, 566, 566, 566, 566,
566, 566, 566, 566, 566, 566, 566, 566, 566, 566,
566, 566, 566, 566, 566, 566, 566, 566, 566, 566,
566, 566, 566, 566, 566, 566, 566, 566, 566, 566,
566, 566, 566, 566, 566, 566, 566, 566, 566, 551,
552, 553, 554, 555, 556, 557, 558, 560, 589, 550,
323, 309, 514, 522, 1201, 1201, 519, 519, 519, 583,
586, 631, 510, 519, 510, 1161, 522, 522, 903, 1201,
590, 344, 404, 430, 430, 430, 430, 430, 430, 538,
519, 544, 1058, 430, 430, 430, 430, 430, 430, 430,
430, 430, 430, 1065, 1194, 1065, 892, 892, 892, 892,
892, 361, 598, 535, 777, 659, 562, 892, 594, 868,
882, 613, 867, 616, 878, 620, 621, 628, 630, 635,
637, 849, 849, 849, 849, 1149, 1081, 607, 844, 850,
615, 777, 777, 1019, 17, 13, 355, 519, 519, 536,
568, 519, 519, 1187, 519, 443, 445, 933, 636, 375,
561, 1101, 618, 931, 1061, 1062, 889, 520, 1058, 276,
277, 278, 21, 1200, 1200, 548, 547, 604, 572, 342,
343, 1059, 1160, 1059, 1168, 362, 1168, 1009, 1200, 527,
898, 1060, 941, 540, 347, 1184, 1184, 1184, 1203, 770,
770, 778, 778, 778, 780, 960, 769, 398, 373, 451,
369, 369, 369, 773, 368, 771, 645, 1167, 907, 10,
402, 1051, 1056, 446, 781, 578, 912, 859, 1146, 459,
949, 0, 369, 0, 0, 0, 0, 0, 0, 386,
566, 566, 566, 566, 566, 566, 566, 566, 566, 514,
443, 445, 933, 636, 327, 309, 1101, 618, 931, 519,
519, 519, 519, 777, 551, 552, 553, 554, 555, 556,
557, 558, 560, 589, 903, 611, 538, 519, 617, 548,
358, 544, 572, 430, 430, 430, 430, 430, 430, 1194,
777, 777, 361, 430, 430, 430, 430, 430, 430, 430,
430, 430, 430, 1065, 1161, 1065, 892, 892, 892, 892,
892, 1168, 598, 1168, 590, 344, 404, 892, 369, 369,
369, 1058, 1184, 1184, 1184, 1076, 1075, 1065, 1065, 1065,
1065, 1149, 1065, 1065, 519, 519, 536, 568, 519, 519,
615, 519, 369, 510, 960, 510, 1167, 386, 770, 770,
778, 778, 778, 780, 520, 769, 276, 277, 278, 535,
607, 659, 562, 547, 594, 868, 882, 613, 867, 616,
878, 620, 621, 628, 630, 635, 637, 1081, 375, 1201,
1201, 1187, 1009, 889, 1019, 17, 13, 355, 790, 752,
1200, 1200, 898, 1061, 1062, 362, 941, 1058, 1201, 527,
871, 561, 851, 540, 657, 347, 511, 880, 875, 1200,
1059, 1160, 1059, 21, 398, 373, 773, 1203, 604, 451,
1060, 771, 907, 342, 343, 368, 645, 402, 446, 10,
1056, 1051, 912, 781, 578, 1146, 859, 459, 949, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 528
528
);
protected $gotoCheck = array(
@ -704,78 +698,72 @@ class Php5 extends \PhpParser\ParserAbstract
39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 53,
112, 11, 112, 112, 112, 112, 112, 112, 112, 112,
112, 112, 112, 112, 112, 112, 112, 112, 112, 112,
112, 112, 112, 112, 112, 112, 112, 112, 112, 112,
112, 112, 112, 112, 112, 112, 112, 112, 112, 112,
112, 112, 112, 112, 112, 119, 12, 119, 119, 119,
63, 12, 63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 119, 11, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
70, 70, 70, 70, 90, 57, 25, 23, 57, 112,
57, 112, 23, 23, 23, 23, 23, 23, 23, 23,
94, 25, 110, 110, 110, 110, 110, 110, 91, 63,
5, 63, 110, 110, 110, 110, 110, 110, 110, 110,
110, 110, 110, 40, 110, 36, 36, 40, 71, 71,
71, 71, 46, 63, 63, 63, 63, 23, 63, 63,
40, 40, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 109, 109, 109, 109, 109, 109, 65, 36,
36, 93, 109, 109, 109, 109, 109, 109, 109, 109,
109, 109, 109, 5, 109, 47, 47, 47, 47, 47,
47, 117, 117, 10, 10, 47, 47, 47, 47, 47,
47, 47, 47, 47, 47, 10, 110, 10, 110, 10,
46, 10, 10, 10, 53, 29, 53, 53, 53, 53,
23, 23, 47, 47, 47, 47, 47, 47, 56, 56,
56, 29, 47, 47, 47, 47, 47, 47, 47, 47,
47, 47, 66, 111, 53, 111, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 102,
102, 102, 102, 102, 102, 102, 102, 102, 102, 40,
118, 118, 8, 40, 134, 134, 8, 8, 8, 56,
56, 56, 115, 8, 115, 75, 40, 40, 77, 134,
63, 63, 63, 53, 53, 53, 53, 53, 53, 8,
8, 101, 75, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 132, 53, 53, 53, 53, 53,
53, 43, 120, 28, 19, 28, 28, 53, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 53, 53, 53, 53, 124, 30, 45, 53, 53,
53, 19, 19, 30, 30, 30, 30, 8, 8, 8,
8, 8, 8, 130, 8, 7, 7, 7, 7, 44,
30, 7, 7, 7, 75, 75, 72, 8, 75, 61,
61, 61, 30, 133, 133, 2, 8, 30, 2, 65,
65, 75, 75, 75, 111, 54, 111, 94, 133, 54,
74, 75, 90, 54, 14, 111, 111, 111, 133, 19,
19, 19, 19, 19, 19, 93, 19, 18, 13, 54,
116, 116, 116, 21, 9, 20, 67, 111, 78, 54,
17, 105, 107, 59, 22, 60, 79, 64, 123, 100,
92, -1, 116, -1, -1, -1, -1, -1, -1, 116,
53, 53, 53, 53, 53, 53, 53, 53, 53, 8,
7, 7, 7, 7, 118, 118, 7, 7, 7, 8,
8, 8, 8, 19, 103, 103, 103, 103, 103, 103,
103, 103, 103, 103, 78, 57, 8, 8, 57, 2,
57, 102, 2, 53, 53, 53, 53, 53, 53, 132,
19, 19, 43, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 76, 53, 53, 53, 53, 53,
53, 112, 120, 112, 64, 64, 64, 53, 116, 116,
116, 76, 112, 112, 112, 117, 117, 53, 53, 53,
53, 124, 53, 53, 8, 8, 8, 8, 8, 8,
53, 8, 116, 115, 94, 115, 112, 116, 19, 19,
19, 19, 19, 19, 8, 19, 61, 61, 61, 28,
45, 28, 28, 8, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 30, 44, 134,
134, 130, 95, 73, 30, 30, 30, 30, 10, 10,
133, 133, 75, 76, 76, 54, 91, 76, 134, 54,
10, 30, 10, 54, 10, 14, 10, 10, 10, 133,
76, 76, 76, 30, 18, 13, 21, 133, 30, 54,
76, 20, 79, 66, 66, 9, 68, 17, 59, 54,
108, 106, 80, 22, 60, 123, 65, 101, 93, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 93
94
);
protected $gotoBase = array(
0, 0, -165, 0, 0, 261, 0, 452, 42, 183,
282, 109, 154, 161, 174, 0, 0, 114, 182, 94,
167, 187, 84, 7, 0, 198, 0, 0, -226, 287,
23, 0, 0, 0, 0, 0, 223, 0, 0, -22,
337, 0, 0, 373, 169, 157, 284, -4, 0, 0,
0, 0, 0, 104, 61, 0, 66, -251, 0, 87,
79, -194, 0, 52, 80, -181, 0, 159, 0, 0,
-79, 0, 160, 0, 177, 38, 0, 355, 162, 85,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192, 0, 70, 222, 186, 0, 0, 0, 0, 0,
72, 366, 307, 0, 0, 105, 0, 103, 0, -27,
-3, 185, -90, 0, 0, 73, 200, -30, 39, -45,
209, 0, 0, 76, 231, 0, 0, 0, 0, 0,
171, 0, 377, 165, 56, 0, 0
0, 0, -261, 0, 0, 198, 0, 347, 29, 192,
487, 154, 109, 168, 185, 0, 0, 121, 183, 43,
173, 184, 93, 37, 0, 193, 0, 0, -180, 273,
64, 0, 0, 0, 0, 0, 189, 0, 0, -22,
201, 0, 0, 354, 188, 180, 216, 3, 0, 0,
0, 0, 0, 104, 71, 0, -15, -81, 0, 92,
88, -207, 0, -90, 90, 89, -137, 0, 169, 0,
0, -51, 0, 177, 0, 179, 67, 0, 351, 166,
91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 196, 0, 78, 161, 181, 0, 0, 0, 0,
0, 80, 356, 322, 0, 0, 115, 0, 111, 0,
-77, 4, 112, 0, 0, 144, 108, 114, 33, -45,
209, 0, 0, 83, 227, 0, 0, 0, 0, 0,
199, 0, 362, 182, 171, 0, 0
);
protected $gotoDefault = array(
@ -785,14 +773,14 @@ class Php5 extends \PhpParser\ParserAbstract
1010, 351, 795, 352, 592, 797, 531, 799, 800, 132,
481, 365, 366, 532, 374, 581, 814, 266, 371, 816,
353, 817, 826, 354, 614, 597, 563, 610, 482, 442,
575, 275, 542, 570, 858, 340, 866, 648, 874, 877,
483, 564, 888, 448, 896, 1086, 382, 902, 908, 913,
916, 418, 401, 588, 920, 921, 5, 925, 626, 627,
940, 300, 948, 961, 416, 1029, 1031, 484, 485, 525,
456, 507, 530, 486, 1052, 436, 403, 1055, 487, 488,
426, 427, 1073, 1070, 346, 1154, 345, 444, 308, 1141,
575, 275, 542, 1073, 570, 858, 340, 866, 648, 874,
877, 483, 564, 888, 448, 896, 1086, 382, 902, 908,
913, 916, 418, 401, 588, 920, 921, 5, 925, 626,
627, 940, 300, 948, 961, 416, 1029, 1031, 484, 485,
525, 456, 507, 530, 486, 1052, 436, 403, 1055, 487,
488, 426, 427, 1070, 346, 1154, 345, 444, 308, 1141,
584, 1105, 452, 1193, 1150, 337, 489, 490, 359, 376,
1188, 431, 1195, 1202, 333, 367, 571
1188, 431, 1195, 1202, 335, 367, 571
);
protected $ruleToNonTerminal = array(
@ -814,17 +802,17 @@ class Php5 extends \PhpParser\ParserAbstract
29, 29, 29, 29, 29, 29, 10, 10, 50, 50,
52, 51, 51, 44, 44, 54, 54, 55, 55, 11,
12, 12, 12, 58, 58, 58, 59, 59, 62, 62,
60, 60, 63, 63, 37, 37, 46, 46, 49, 49,
49, 48, 48, 64, 38, 38, 38, 38, 65, 65,
66, 66, 67, 67, 35, 35, 31, 31, 68, 33,
33, 69, 32, 32, 34, 34, 45, 45, 45, 56,
56, 71, 71, 72, 72, 74, 74, 74, 73, 73,
57, 57, 75, 75, 75, 76, 76, 77, 77, 77,
41, 41, 78, 78, 78, 42, 42, 79, 79, 61,
61, 80, 80, 80, 80, 85, 85, 86, 86, 87,
87, 87, 87, 87, 88, 89, 89, 84, 84, 81,
81, 83, 83, 91, 91, 90, 90, 90, 90, 90,
90, 82, 82, 92, 92, 43, 43, 36, 36, 39,
60, 60, 64, 64, 37, 37, 46, 46, 49, 49,
49, 48, 48, 65, 38, 38, 38, 38, 66, 66,
67, 67, 68, 68, 35, 35, 31, 31, 69, 33,
33, 70, 32, 32, 34, 34, 45, 45, 45, 56,
56, 72, 72, 73, 73, 75, 75, 75, 74, 74,
57, 57, 76, 76, 76, 77, 77, 78, 78, 78,
41, 41, 79, 79, 79, 42, 42, 80, 80, 61,
61, 81, 81, 81, 81, 86, 86, 87, 87, 88,
88, 88, 88, 88, 89, 90, 90, 85, 85, 82,
82, 84, 84, 92, 92, 91, 91, 91, 91, 91,
91, 83, 83, 93, 93, 43, 43, 36, 36, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
@ -833,22 +821,22 @@ class Php5 extends \PhpParser\ParserAbstract
39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 30, 30, 40, 40, 97, 97, 98,
98, 98, 98, 104, 93, 93, 100, 100, 106, 106,
107, 108, 108, 108, 108, 108, 108, 112, 112, 53,
53, 53, 94, 94, 113, 113, 109, 109, 114, 114,
114, 114, 95, 95, 95, 99, 99, 99, 105, 105,
39, 39, 39, 30, 30, 40, 40, 98, 98, 99,
99, 99, 99, 105, 94, 94, 101, 101, 107, 107,
108, 109, 109, 109, 109, 109, 109, 63, 63, 53,
53, 53, 95, 95, 113, 113, 110, 110, 114, 114,
114, 114, 96, 96, 96, 100, 100, 100, 106, 106,
119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 23, 23, 23, 23, 23, 23, 121,
121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
121, 121, 121, 121, 121, 121, 121, 121, 121, 121,
121, 121, 103, 103, 96, 96, 96, 96, 120, 120,
121, 121, 104, 104, 97, 97, 97, 97, 120, 120,
123, 123, 122, 122, 124, 124, 47, 47, 47, 47,
126, 126, 125, 125, 125, 125, 125, 127, 127, 111,
111, 115, 115, 110, 110, 128, 128, 128, 128, 116,
116, 116, 116, 102, 102, 117, 117, 117, 117, 70,
129, 129, 130, 130, 130, 101, 101, 131, 131, 132,
126, 126, 125, 125, 125, 125, 125, 127, 127, 112,
112, 115, 115, 111, 111, 128, 128, 128, 128, 116,
116, 116, 116, 103, 103, 117, 117, 117, 117, 71,
129, 129, 130, 130, 130, 102, 102, 131, 131, 132,
132, 132, 132, 118, 118, 118, 118, 134, 135, 133,
133, 133, 133, 133, 133, 133, 136, 136, 136
);
@ -1269,15 +1257,21 @@ class Php5 extends \PhpParser\ParserAbstract
}
protected function reduceRule89() {
$this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(3-2)], null, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); $this->checkNamespace($this->semValue);
$this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(3-2)], null, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
$this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON);
$this->checkNamespace($this->semValue);
}
protected function reduceRule90() {
$this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(5-2)], $this->semStack[$this->stackPos-(5-4)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); $this->checkNamespace($this->semValue);
$this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(5-2)], $this->semStack[$this->stackPos-(5-4)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
$this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
$this->checkNamespace($this->semValue);
}
protected function reduceRule91() {
$this->semValue = new Stmt\Namespace_(null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); $this->checkNamespace($this->semValue);
$this->semValue = new Stmt\Namespace_(null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
$this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
$this->checkNamespace($this->semValue);
}
protected function reduceRule92() {
@ -1422,7 +1416,14 @@ class Php5 extends \PhpParser\ParserAbstract
}
protected function reduceRule127() {
$this->semValue = $this->semStack[$this->stackPos-(3-2)]; $attrs = $this->startAttributeStack[$this->stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments']) && isset($stmts[0])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); };
if ($this->semStack[$this->stackPos-(3-2)]) {
$this->semValue = $this->semStack[$this->stackPos-(3-2)]; $attrs = $this->startAttributeStack[$this->stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); };
} else {
$startAttributes = $this->startAttributeStack[$this->stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $this->semValue = null; };
if (null === $this->semValue) { $this->semValue = array(); }
}
}
protected function reduceRule128() {
@ -3131,7 +3132,7 @@ class Php5 extends \PhpParser\ParserAbstract
}
protected function reduceRule547() {
$this->semValue = new Scalar\String_($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
$this->semValue = $this->parseNumString($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
}
protected function reduceRule548() {

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@ namespace PhpParser;
use PhpParser\Node\Name;
use PhpParser\Node\Param;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Stmt\ClassMethod;
@ -314,7 +315,11 @@ abstract class ParserAbstract implements Parser
//$this->traceShift($this->errorSymbol);
++$this->stackPos;
$stateStack[$this->stackPos] = $state = $action;
$this->endAttributes = $this->endAttributeStack[$this->stackPos];
// We treat the error symbol as being empty, so we reset the end attributes
// to the end attributes of the last non-error symbol
$this->endAttributeStack[$this->stackPos] = $this->endAttributeStack[$this->stackPos - 1];
$this->endAttributes = $this->endAttributeStack[$this->stackPos - 1];
break;
case 3:
@ -440,6 +445,7 @@ abstract class ParserAbstract implements Parser
if ($stmt instanceof Node\Stmt\Namespace_) {
$afterFirstNamespace = true;
} elseif (!$stmt instanceof Node\Stmt\HaltCompiler
&& !$stmt instanceof Node\Stmt\Nop
&& $afterFirstNamespace && !$hasErrored) {
$this->emitError(new Error(
'No code may exist outside of namespace {}', $stmt->getAttributes()));
@ -524,6 +530,7 @@ abstract class ParserAbstract implements Parser
'string' => true,
'iterable' => true,
'void' => true,
'object' => true,
];
if (!$name->isUnqualified()) {
@ -554,6 +561,19 @@ abstract class ParserAbstract implements Parser
}
}
protected function parseNumString($str, $attributes) {
if (!preg_match('/^(?:0|-?[1-9][0-9]*)$/', $str)) {
return new String_($str, $attributes);
}
$num = +$str;
if (!is_int($num)) {
return new String_($str, $attributes);
}
return new LNumber($num, $attributes);
}
protected function checkModifier($a, $b, $modifierPos) {
// Jumping through some hoops here because verifyModifier() is also used elsewhere
try {

View File

@ -34,7 +34,7 @@ class Standard extends PrettyPrinterAbstract
}
protected function pNullableType(Node\NullableType $node) {
return '?' . $node->type;
return '?' . $this->pType($node->type);
}
// Names
@ -141,26 +141,52 @@ class Standard extends PrettyPrinterAbstract
}
protected function pScalar_LNumber(Scalar\LNumber $node) {
if ($node->value === -\PHP_INT_MAX-1) {
// PHP_INT_MIN cannot be represented as a literal,
// because the sign is not part of the literal
return '(-' . \PHP_INT_MAX . '-1)';
}
$kind = $node->getAttribute('kind', Scalar\LNumber::KIND_DEC);
if (Scalar\LNumber::KIND_DEC === $kind) {
return (string) $node->value;
}
$sign = $node->value < 0 ? '-' : '';
$str = (string) $node->value;
switch ($node->getAttribute('kind', Scalar\LNumber::KIND_DEC)) {
switch ($kind) {
case Scalar\LNumber::KIND_BIN:
return '0b' . base_convert($str, 10, 2);
return $sign . '0b' . base_convert($str, 10, 2);
case Scalar\LNumber::KIND_OCT:
return '0' . base_convert($str, 10, 8);
case Scalar\LNumber::KIND_DEC:
return $str;
return $sign . '0' . base_convert($str, 10, 8);
case Scalar\LNumber::KIND_HEX:
return '0x' . base_convert($str, 10, 16);
return $sign . '0x' . base_convert($str, 10, 16);
}
throw new \Exception('Invalid number kind');
}
protected function pScalar_DNumber(Scalar\DNumber $node) {
if (!is_finite($node->value)) {
if ($node->value === \INF) {
return '\INF';
} elseif ($node->value === -\INF) {
return '-\INF';
} else {
return '\NAN';
}
}
// Try to find a short full-precision representation
$stringValue = sprintf('%.16G', $node->value);
if ($node->value !== (double) $stringValue) {
$stringValue = sprintf('%.17G', $node->value);
}
// %G is locale dependent and there exists no locale-independent alternative. We don't want
// mess with switching locales here, so let's assume that a comma is the only non-standard
// decimal separator we may encounter...
$stringValue = str_replace(',', '.', $stringValue);
// ensure that number is really printed as float
return preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue;
}
@ -417,12 +443,12 @@ class Standard extends PrettyPrinterAbstract
protected function pExpr_FuncCall(Expr\FuncCall $node) {
return $this->pCallLhs($node->name)
. '(' . $this->pCommaSeparated($node->args) . ')';
. '(' . $this->pMaybeMultiline($node->args) . ')';
}
protected function pExpr_MethodCall(Expr\MethodCall $node) {
return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name)
. '(' . $this->pCommaSeparated($node->args) . ')';
. '(' . $this->pMaybeMultiline($node->args) . ')';
}
protected function pExpr_StaticCall(Expr\StaticCall $node) {
@ -432,7 +458,7 @@ class Standard extends PrettyPrinterAbstract
? $this->p($node->name)
: '{' . $this->p($node->name) . '}')
: $node->name)
. '(' . $this->pCommaSeparated($node->args) . ')';
. '(' . $this->pMaybeMultiline($node->args) . ')';
}
protected function pExpr_Empty(Expr\Empty_ $node) {
@ -464,6 +490,10 @@ class Standard extends PrettyPrinterAbstract
// Other
protected function pExpr_Error(Expr\Error $node) {
throw new \LogicException('Cannot pretty-print AST with Error nodes');
}
protected function pExpr_Variable(Expr\Variable $node) {
if ($node->name instanceof Expr) {
return '${' . $this->p($node->name) . '}';
@ -476,9 +506,9 @@ class Standard extends PrettyPrinterAbstract
$syntax = $node->getAttribute('kind',
$this->options['shortArraySyntax'] ? Expr\Array_::KIND_SHORT : Expr\Array_::KIND_LONG);
if ($syntax === Expr\Array_::KIND_SHORT) {
return '[' . $this->pCommaSeparated($node->items) . ']';
return '[' . $this->pMaybeMultiline($node->items, true) . ']';
} else {
return 'array(' . $this->pCommaSeparated($node->items) . ')';
return 'array(' . $this->pMaybeMultiline($node->items, true) . ')';
}
}
@ -497,7 +527,8 @@ class Standard extends PrettyPrinterAbstract
}
protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node) {
return $this->p($node->class) . '::' . $node->name;
return $this->p($node->class) . '::'
. (is_string($node->name) ? $node->name : $this->p($node->name));
}
protected function pExpr_PropertyFetch(Expr\PropertyFetch $node) {
@ -527,10 +558,10 @@ class Standard extends PrettyPrinterAbstract
protected function pExpr_New(Expr\New_ $node) {
if ($node->class instanceof Stmt\Class_) {
$args = $node->args ? '(' . $this->pCommaSeparated($node->args) . ')' : '';
$args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : '';
return 'new ' . $this->pClassCommon($node->class, $args);
}
return 'new ' . $this->p($node->class) . '(' . $this->pCommaSeparated($node->args) . ')';
return 'new ' . $this->p($node->class) . '(' . $this->pMaybeMultiline($node->args) . ')';
}
protected function pExpr_Clone(Expr\Clone_ $node) {
@ -589,7 +620,7 @@ class Standard extends PrettyPrinterAbstract
. ($node->name->getLast() !== $node->alias ? ' as ' . $node->alias : '');
}
private function pUseType($type) {
protected function pUseType($type) {
return $type === Stmt\Use_::TYPE_FUNCTION ? 'function '
: ($type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : '');
}
@ -918,4 +949,21 @@ class Standard extends PrettyPrinterAbstract
return '(' . $this->p($node) . ')';
}
}
private function hasNodeWithComments(array $nodes) {
foreach ($nodes as $node) {
if ($node && $node->getAttribute('comments')) {
return true;
}
}
return false;
}
private function pMaybeMultiline(array $nodes, $trailingComma = false) {
if (!$this->hasNodeWithComments($nodes)) {
return $this->pCommaSeparated($nodes);
} else {
return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . "\n";
}
}
}

View File

@ -247,11 +247,11 @@ abstract class PrettyPrinterAbstract
if ($childPrecedence > $parentPrecedence
|| ($parentPrecedence == $childPrecedence && $parentAssociativity != $childPosition)
) {
return '(' . $this->{'p' . $type}($node) . ')';
return '(' . $this->p($node) . ')';
}
}
return $this->{'p' . $type}($node);
return $this->p($node);
}
/**
@ -286,6 +286,38 @@ abstract class PrettyPrinterAbstract
return $this->pImplode($nodes, ', ');
}
/**
* Pretty prints a comma-separated list of nodes in multiline style, including comments.
*
* The result includes a leading newline and one level of indentation (same as pStmts).
*
* @param Node[] $nodes Array of Nodes to be printed
* @param bool $trailingComma Whether to use a trailing comma
*
* @return string Comma separated pretty printed nodes in multiline style
*/
protected function pCommaSeparatedMultiline(array $nodes, $trailingComma) {
$result = '';
$lastIdx = count($nodes) - 1;
foreach ($nodes as $idx => $node) {
if ($node !== null) {
$comments = $node->getAttribute('comments', array());
if ($comments) {
$result .= "\n" . $this->pComments($comments);
}
$result .= "\n" . $this->p($node);
} else {
$result .= "\n";
}
if ($trailingComma || $idx !== $lastIdx) {
$result .= ',';
}
}
return preg_replace('~\n(?!$|' . $this->noIndentToken . ')~', "\n ", $result);
}
/**
* Signals the pretty printer that a string shall not be indented.
*

View File

@ -2,6 +2,9 @@
namespace PhpParser;
/**
* @deprecated
*/
interface Serializer
{
/**

View File

@ -7,6 +7,9 @@ use PhpParser\Node;
use PhpParser\Serializer;
use XMLWriter;
/**
* @deprecated
*/
class XML implements Serializer
{
protected $writer;

View File

@ -2,6 +2,9 @@
namespace PhpParser;
/**
* @deprecated
*/
interface Unserializer
{
/**

View File

@ -6,6 +6,9 @@ use DomainException;
use PhpParser\Unserializer;
use XMLReader;
/**
* @deprecated
*/
class XML implements Unserializer
{
protected $reader;

View File

@ -2,6 +2,7 @@
namespace PhpParser\Builder;
use PhpParser\Comment\Doc;
use PhpParser\Node;
use PhpParser\Node\Stmt;
@ -15,19 +16,23 @@ class NamespaceTest extends \PHPUnit_Framework_TestCase
$stmt1 = new Stmt\Class_('SomeClass');
$stmt2 = new Stmt\Interface_('SomeInterface');
$stmt3 = new Stmt\Function_('someFunction');
$docComment = new Doc('/** Test */');
$expected = new Stmt\Namespace_(
new Node\Name('Name\Space'),
array($stmt1, $stmt2, $stmt3)
array($stmt1, $stmt2, $stmt3),
array('comments' => array($docComment))
);
$node = $this->createNamespaceBuilder('Name\Space')
->addStmt($stmt1)
->addStmts(array($stmt2, $stmt3))
->setDocComment($docComment)
->getNode()
;
$this->assertEquals($expected, $node);
$node = $this->createNamespaceBuilder(new Node\Name(array('Name', 'Space')))
->setDocComment($docComment)
->addStmts(array($stmt1, $stmt2))
->addStmt($stmt3)
->getNode()

View File

@ -112,6 +112,7 @@ class ParamTest extends \PHPUnit_Framework_TestCase
array('float', 'float'),
array('string', 'string'),
array('iterable', 'iterable'),
array('object', 'object'),
array('Array', 'array'),
array('CALLABLE', 'callable'),
array('Some\Class', new Node\Name('Some\Class')),
@ -155,4 +156,16 @@ class ParamTest extends \PHPUnit_Framework_TestCase
$node
);
}
public function testVariadic() {
$node = $this->createParamBuilder('test')
->makeVariadic()
->getNode()
;
$this->assertEquals(
new Node\Param('test', null, null, false, true),
$node
);
}
}

View File

@ -3,6 +3,7 @@
namespace PhpParser\Builder;
use PhpParser\Comment;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt;
class TraitTest extends \PHPUnit_Framework_TestCase
@ -18,19 +19,21 @@ class TraitTest extends \PHPUnit_Framework_TestCase
$prop = new Stmt\Property(Stmt\Class_::MODIFIER_PUBLIC, array(
new Stmt\PropertyProperty('test')
));
$use = new Stmt\TraitUse([new Name('OtherTrait')]);
$trait = $this->createTraitBuilder('TestTrait')
->setDocComment('/** Nice trait */')
->addStmt($method1)
->addStmts(array($method2, $method3))
->addStmts([$method2, $method3])
->addStmt($prop)
->addStmt($use)
->getNode();
$this->assertEquals(new Stmt\Trait_('TestTrait', array(
'stmts' => array($prop, $method1, $method2, $method3)
), array(
'comments' => array(
$this->assertEquals(new Stmt\Trait_('TestTrait', [
'stmts' => [$use, $prop, $method1, $method2, $method3]
], [
'comments' => [
new Comment\Doc('/** Nice trait */')
)
)), $trait);
]
]), $trait);
}
/**

View File

@ -201,7 +201,13 @@ class LexerTest extends \PHPUnit_Framework_TestCase
array(), array()
)
)
)
),
// tests no tokens
array(
'',
array(),
array()
),
);
}

View File

@ -166,6 +166,63 @@ class NodeTraverserTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($stmts, $traverser->traverse($stmts));
}
public function testStopTraversal() {
$varNode1 = new Expr\Variable('a');
$varNode2 = new Expr\Variable('b');
$varNode3 = new Expr\Variable('c');
$mulNode = new Expr\BinaryOp\Mul($varNode1, $varNode2);
$printNode = new Expr\Print_($varNode3);
$stmts = [$mulNode, $printNode];
// From enterNode() with array parent
$visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
$visitor->expects($this->at(1))->method('enterNode')->with($mulNode)
->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL));
$visitor->expects($this->at(2))->method('afterTraverse');
$traverser = new NodeTraverser;
$traverser->addVisitor($visitor);
$this->assertEquals($stmts, $traverser->traverse($stmts));
// From enterNode with Node parent
$visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
$visitor->expects($this->at(2))->method('enterNode')->with($varNode1)
->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL));
$visitor->expects($this->at(3))->method('afterTraverse');
$traverser = new NodeTraverser;
$traverser->addVisitor($visitor);
$this->assertEquals($stmts, $traverser->traverse($stmts));
// From leaveNode with Node parent
$visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
$visitor->expects($this->at(3))->method('leaveNode')->with($varNode1)
->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL));
$visitor->expects($this->at(4))->method('afterTraverse');
$traverser = new NodeTraverser;
$traverser->addVisitor($visitor);
$this->assertEquals($stmts, $traverser->traverse($stmts));
// From leaveNode with array parent
$visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
$visitor->expects($this->at(6))->method('leaveNode')->with($mulNode)
->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL));
$visitor->expects($this->at(7))->method('afterTraverse');
$traverser = new NodeTraverser;
$traverser->addVisitor($visitor);
$this->assertEquals($stmts, $traverser->traverse($stmts));
// Check that pending array modifications are still carried out
$visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
$visitor->expects($this->at(6))->method('leaveNode')->with($mulNode)
->will($this->returnValue(NodeTraverser::REMOVE_NODE));
$visitor->expects($this->at(7))->method('enterNode')->with($printNode)
->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL));
$visitor->expects($this->at(8))->method('afterTraverse');
$traverser = new NodeTraverser;
$traverser->addVisitor($visitor);
$this->assertEquals([$printNode], $traverser->traverse($stmts));
}
public function testRemovingVisitor() {
$visitor1 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
$visitor2 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();

View File

@ -199,9 +199,12 @@ interface A extends C, D {
public function a(A $a) : A;
}
function fn() : A {}
function fn2() : array {}
function() : A {};
function fn(A $a) : A {}
function fn2(array $a) : array {}
function(A $a) : A {};
function fn3(?A $a) : ?A {}
function fn4(?array $a) : ?array {}
A::b();
A::$b;
@ -233,14 +236,20 @@ interface A extends \NS\C, \NS\D
{
public function a(\NS\A $a) : \NS\A;
}
function fn() : \NS\A
function fn(\NS\A $a) : \NS\A
{
}
function fn2() : array
function fn2(array $a) : array
{
}
function () : \NS\A {
function (\NS\A $a) : \NS\A {
};
function fn3(?\NS\A $a) : ?\NS\A
{
}
function fn4(?array $a) : ?array
{
}
\NS\A::b();
\NS\A::$b;
\NS\A::B;
@ -437,4 +446,23 @@ EOC;
$this->assertSame('PARENT', (string)$methodStmt->stmts[1]->class);
$this->assertSame('STATIC', (string)$methodStmt->stmts[2]->class);
}
public function testAddOriginalNames() {
$traverser = new PhpParser\NodeTraverser;
$traverser->addVisitor(new NameResolver(null, ['preserveOriginalNames' => true]));
$n1 = new Name('Bar');
$n2 = new Name('bar');
$origStmts = [
new Stmt\Namespace_(new Name('Foo'), [
new Expr\ClassConstFetch($n1, 'FOO'),
new Expr\FuncCall($n2),
])
];
$stmts = $traverser->traverse($origStmts);
$this->assertSame($n1, $stmts[0]->stmts[0]->class->getAttribute('originalName'));
$this->assertSame($n2, $stmts[0]->stmts[1]->name->getAttribute('originalName'));
}
}

View File

@ -169,6 +169,9 @@ EOC;
array("exit(1)", ['kind' => Expr\Exit_::KIND_EXIT]),
array("?>Foo", ['hasLeadingNewline' => false]),
array("?>\nFoo", ['hasLeadingNewline' => true]),
array("namespace Foo;", ['kind' => Node\Stmt\Namespace_::KIND_SEMICOLON]),
array("namespace Foo {}", ['kind' => Node\Stmt\Namespace_::KIND_BRACED]),
array("namespace {}", ['kind' => Node\Stmt\Namespace_::KIND_BRACED]),
);
}
}

View File

@ -4,8 +4,11 @@ namespace PhpParser;
use PhpParser\Comment;
use PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar\DNumber;
use PhpParser\Node\Scalar\Encapsed;
use PhpParser\Node\Scalar\EncapsedStringPart;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt;
use PhpParser\PrettyPrinter\Standard;
@ -161,4 +164,44 @@ class PrettyPrinterTest extends CodeTestAbstract
[new Encapsed([new EncapsedStringPart("STR")], $heredoc), '"STR"'],
];
}
/** @dataProvider provideTestUnnaturalLiterals */
public function testUnnaturalLiterals($node, $expected) {
$prttyPrinter = new PrettyPrinter\Standard;
$result = $prttyPrinter->prettyPrintExpr($node);
$this->assertSame($expected, $result);
}
public function provideTestUnnaturalLiterals() {
return [
[new LNumber(-1), '-1'],
[new LNumber(-PHP_INT_MAX - 1), '(-' . PHP_INT_MAX . '-1)'],
[new LNumber(-1, ['kind' => LNumber::KIND_BIN]), '-0b1'],
[new LNumber(-1, ['kind' => LNumber::KIND_OCT]), '-01'],
[new LNumber(-1, ['kind' => LNumber::KIND_HEX]), '-0x1'],
[new DNumber(\INF), '\INF'],
[new DNumber(-\INF), '-\INF'],
[new DNumber(-\NAN), '\NAN'],
];
}
/**
* @expectedException \LogicException
* @expectedExceptionMessage Cannot pretty-print AST with Error nodes
*/
public function testPrettyPrintWithError() {
$stmts = [new Expr\PropertyFetch(new Expr\Variable('a'), new Expr\Error())];
$prettyPrinter = new PrettyPrinter\Standard;
$prettyPrinter->prettyPrint($stmts);
}
/**
* @expectedException \LogicException
* @expectedExceptionMessage Cannot pretty-print AST with Error nodes
*/
public function testPrettyPrintWithErrorInClassConstFetch() {
$stmts = [new Expr\ClassConstFetch(new Name('Foo'), new Expr\Error())];
$prettyPrinter = new PrettyPrinter\Standard;
$prettyPrinter->prettyPrint($stmts);
}
}

View File

@ -10,6 +10,9 @@ Comments on blocks
$a;
}
}
// empty
{}
-----
array(
0: Expr_Variable(
@ -20,4 +23,9 @@ array(
2: // baz
)
)
1: Stmt_Nop(
comments: array(
0: // empty
)
)
)

View File

@ -248,11 +248,11 @@ $foo->
!!positions
Syntax error, unexpected ';', expecting T_STRING or T_VARIABLE or '{' or '$' from 3:1 to 3:1
array(
0: Expr_PropertyFetch[2:1 - 3:1](
0: Expr_PropertyFetch[2:1 - 2:6](
var: Expr_Variable[2:1 - 2:4](
name: foo
)
name: Expr_Error[3:1 - 3:1](
name: Expr_Error[3:1 - 2:6](
)
)
)
@ -272,11 +272,11 @@ array(
)
returnType: null
stmts: array(
0: Expr_PropertyFetch[3:5 - 4:1](
0: Expr_PropertyFetch[3:5 - 3:10](
var: Expr_Variable[3:5 - 3:8](
name: bar
)
name: Expr_Error[4:1 - 4:1](
name: Expr_Error[4:1 - 3:10](
)
)
)
@ -305,8 +305,8 @@ new
!!php7,positions
Syntax error, unexpected EOF from 2:4 to 2:4
array(
0: Expr_New[2:1 - 2:4](
class: Expr_Error[2:4 - 2:4](
0: Expr_New[2:1 - 2:3](
class: Expr_Error[2:4 - 2:3](
)
args: array(
)
@ -372,4 +372,495 @@ array(
name: Expr_Error(
)
)
)
-----
<?php
namespace Foo
use A
use function a
use A\{B}
const A = 1
break
break 2
continue
continue 2
return
return 2
echo $a
unset($a)
throw $x
goto label
-----
!!php7
Syntax error, unexpected T_USE, expecting ';' or '{' from 3:1 to 3:3
Syntax error, unexpected T_USE, expecting ';' from 5:1 to 5:3
Syntax error, unexpected T_CONST, expecting ';' from 6:1 to 6:5
Syntax error, unexpected T_BREAK, expecting ';' from 7:1 to 7:5
Syntax error, unexpected T_THROW, expecting ';' from 15:1 to 15:5
array(
0: Stmt_Namespace(
name: Name(
parts: array(
0: Foo
)
)
stmts: array(
0: Stmt_Use(
type: TYPE_NORMAL (1)
uses: array(
0: Stmt_UseUse(
type: TYPE_UNKNOWN (0)
name: Name(
parts: array(
0: A
)
)
alias: A
)
)
)
1: Stmt_Use(
type: TYPE_FUNCTION (2)
uses: array(
0: Stmt_UseUse(
type: TYPE_UNKNOWN (0)
name: Name(
parts: array(
0: a
)
)
alias: a
)
)
)
2: Stmt_GroupUse(
type: TYPE_UNKNOWN (0)
prefix: Name(
parts: array(
0: A
)
)
uses: array(
0: Stmt_UseUse(
type: TYPE_NORMAL (1)
name: Name(
parts: array(
0: B
)
)
alias: B
)
)
)
3: Stmt_Const(
consts: array(
0: Const(
name: A
value: Scalar_LNumber(
value: 1
)
)
)
)
4: Stmt_Break(
num: null
)
5: Stmt_Break(
num: Scalar_LNumber(
value: 2
)
)
6: Stmt_Continue(
num: null
)
7: Stmt_Continue(
num: Scalar_LNumber(
value: 2
)
)
8: Stmt_Return(
expr: null
)
9: Stmt_Return(
expr: Scalar_LNumber(
value: 2
)
)
10: Stmt_Echo(
exprs: array(
0: Expr_Variable(
name: a
)
)
)
11: Stmt_Unset(
vars: array(
0: Expr_Variable(
name: a
)
)
)
12: Stmt_Throw(
expr: Expr_Variable(
name: x
)
)
13: Stmt_Goto(
name: label
)
)
)
)
-----
<?php
use A\{B, };
use function A\{b, };
use A, ;
const A = 42, ;
class X implements Y, {
use A, ;
use A, {
A::b insteadof C, ;
}
const A = 42, ;
public $x, ;
}
interface I extends J, {}
unset($x, );
isset($x, );
declare(a=42, );
function foo($a, ) {}
foo($a, );
global $a, ;
static $a, ;
echo $a, ;
for ($a, ; $b, ; $c, );
function ($a, ) use ($b, ) {};
-----
!!php7
A trailing comma is not allowed here from 5:6 to 5:6
A trailing comma is not allowed here from 6:13 to 6:13
A trailing comma is not allowed here from 8:21 to 8:21
A trailing comma is not allowed here from 9:10 to 9:10
A trailing comma is not allowed here from 10:10 to 10:10
A trailing comma is not allowed here from 11:25 to 11:25
A trailing comma is not allowed here from 13:17 to 13:17
A trailing comma is not allowed here from 14:14 to 14:14
A trailing comma is not allowed here from 16:22 to 16:22
A trailing comma is not allowed here from 18:9 to 18:9
A trailing comma is not allowed here from 19:9 to 19:9
A trailing comma is not allowed here from 21:13 to 21:13
A trailing comma is not allowed here from 23:16 to 23:16
A trailing comma is not allowed here from 24:7 to 24:7
A trailing comma is not allowed here from 25:10 to 25:10
A trailing comma is not allowed here from 26:10 to 26:10
A trailing comma is not allowed here from 27:8 to 27:8
A trailing comma is not allowed here from 29:8 to 29:8
A trailing comma is not allowed here from 29:14 to 29:14
A trailing comma is not allowed here from 29:20 to 29:20
A trailing comma is not allowed here from 30:13 to 30:13
A trailing comma is not allowed here from 30:24 to 30:24
array(
0: Stmt_GroupUse(
type: TYPE_UNKNOWN (0)
prefix: Name(
parts: array(
0: A
)
)
uses: array(
0: Stmt_UseUse(
type: TYPE_NORMAL (1)
name: Name(
parts: array(
0: B
)
)
alias: B
)
)
)
1: Stmt_GroupUse(
type: TYPE_FUNCTION (2)
prefix: Name(
parts: array(
0: A
)
)
uses: array(
0: Stmt_UseUse(
type: TYPE_UNKNOWN (0)
name: Name(
parts: array(
0: b
)
)
alias: b
)
)
)
2: Stmt_Use(
type: TYPE_NORMAL (1)
uses: array(
0: Stmt_UseUse(
type: TYPE_UNKNOWN (0)
name: Name(
parts: array(
0: A
)
)
alias: A
)
)
)
3: Stmt_Const(
consts: array(
0: Const(
name: A
value: Scalar_LNumber(
value: 42
)
)
)
)
4: Stmt_Class(
flags: 0
name: X
extends: null
implements: array(
0: Name(
parts: array(
0: Y
)
)
)
stmts: array(
0: Stmt_TraitUse(
traits: array(
0: Name(
parts: array(
0: A
)
)
)
adaptations: array(
)
)
1: Stmt_TraitUse(
traits: array(
0: Name(
parts: array(
0: A
)
)
)
adaptations: array(
0: Stmt_TraitUseAdaptation_Precedence(
trait: Name(
parts: array(
0: A
)
)
method: b
insteadof: array(
0: Name(
parts: array(
0: C
)
)
)
)
)
)
2: Stmt_ClassConst(
flags: 0
consts: array(
0: Const(
name: A
value: Scalar_LNumber(
value: 42
)
)
)
)
3: Stmt_Property(
flags: MODIFIER_PUBLIC (1)
props: array(
0: Stmt_PropertyProperty(
name: x
default: null
)
)
)
)
)
5: Stmt_Interface(
name: I
extends: array(
0: Name(
parts: array(
0: J
)
)
)
stmts: array(
)
)
6: Stmt_Unset(
vars: array(
0: Expr_Variable(
name: x
)
)
)
7: Expr_Isset(
vars: array(
0: Expr_Variable(
name: x
)
)
)
8: Stmt_Declare(
declares: array(
0: Stmt_DeclareDeclare(
key: a
value: Scalar_LNumber(
value: 42
)
)
)
stmts: null
)
9: Stmt_Function(
byRef: false
name: foo
params: array(
0: Param(
type: null
byRef: false
variadic: false
name: a
default: null
)
)
returnType: null
stmts: array(
)
)
10: Expr_FuncCall(
name: Name(
parts: array(
0: foo
)
)
args: array(
0: Arg(
value: Expr_Variable(
name: a
)
byRef: false
unpack: false
)
)
)
11: Stmt_Global(
vars: array(
0: Expr_Variable(
name: a
)
)
)
12: Stmt_Static(
vars: array(
0: Stmt_StaticVar(
name: a
default: null
)
)
)
13: Stmt_Echo(
exprs: array(
0: Expr_Variable(
name: a
)
)
)
14: Stmt_For(
init: array(
0: Expr_Variable(
name: a
)
)
cond: array(
0: Expr_Variable(
name: b
)
)
loop: array(
0: Expr_Variable(
name: c
)
)
stmts: array(
)
)
15: Expr_Closure(
static: false
byRef: false
params: array(
0: Param(
type: null
byRef: false
variadic: false
name: a
default: null
)
)
uses: array(
0: Expr_ClosureUse(
var: b
byRef: false
)
)
returnType: null
stmts: array(
)
)
)
-----
<?php
foo(Bar::);
-----
!!php7,positions
Syntax error, unexpected ')' from 3:10 to 3:10
array(
0: Expr_FuncCall[3:1 - 3:10](
name: Name[3:1 - 3:3](
parts: array(
0: foo
)
)
args: array(
0: Arg[3:5 - 3:9](
value: Expr_ClassConstFetch[3:5 - 3:9](
class: Name[3:5 - 3:7](
parts: array(
0: Bar
)
)
name: Expr_Error[3:10 - 3:9](
)
)
byRef: false
unpack: false
)
)
)
)

View File

@ -4,13 +4,22 @@ Non-simple variables are forbidden in PHP 7
global $$foo->bar;
-----
!!php7
Syntax error, unexpected T_OBJECT_OPERATOR, expecting ',' or ';' from 2:13 to 2:14
Syntax error, unexpected T_OBJECT_OPERATOR, expecting ';' from 2:13 to 2:14
array(
0: Expr_ConstFetch(
0: Stmt_Global(
vars: array(
0: Expr_Variable(
name: Expr_Variable(
name: foo
)
)
)
)
1: Expr_ConstFetch(
name: Name(
parts: array(
0: bar
)
)
)
)
)

View File

@ -0,0 +1,72 @@
Encapsed string negative var offsets
-----
<?php
"$a[-0]";
"$a[-1]";
"$a[-0x0]";
"$a[-00]";
"$a[@@{ -PHP_INT_MAX - 1 }@@]";
-----
!!php7
array(
0: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: Scalar_String(
value: -0
)
)
)
)
1: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: Scalar_LNumber(
value: -1
)
)
)
)
2: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: Scalar_String(
value: -0x0
)
)
)
)
3: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: Scalar_String(
value: -00
)
)
)
)
4: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: Scalar_LNumber(
value: @@{ -PHP_INT_MAX - 1 }@@
)
)
)
)
)

View File

@ -6,7 +6,11 @@ Encapsed strings
"$A->B";
"$A[B]";
"$A[0]";
"$A[1234]";
"$A[9223372036854775808]";
"$A[000]";
"$A[0x0]";
"$A[0b0]";
"$A[$B]";
"{$A}";
"{$A['B']}";
@ -59,13 +63,49 @@ array(
var: Expr_Variable(
name: A
)
dim: Scalar_String(
dim: Scalar_LNumber(
value: 0
)
)
)
)
4: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Scalar_LNumber(
value: 1234
)
)
)
)
5: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Scalar_String(
value: 9223372036854775808
)
)
)
)
6: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Scalar_String(
value: 000
)
)
)
)
7: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
@ -77,7 +117,19 @@ array(
)
)
)
5: Scalar_Encapsed(
8: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Scalar_String(
value: 0b0
)
)
)
)
9: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
@ -89,45 +141,45 @@ array(
)
)
)
6: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: A
)
)
)
7: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Scalar_String(
value: B
)
)
)
)
8: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: A
)
)
)
9: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Scalar_String(
value: B
)
)
)
)
10: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: A
)
)
)
11: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Scalar_String(
value: B
)
)
)
)
12: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: A
)
)
)
13: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Scalar_String(
value: B
)
)
)
)
14: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: Expr_Variable(
@ -136,7 +188,7 @@ array(
)
)
)
11: Scalar_Encapsed(
15: Scalar_Encapsed(
parts: array(
0: Scalar_EncapsedStringPart(
value: \{
@ -149,7 +201,7 @@ array(
)
)
)
12: Scalar_Encapsed(
16: Scalar_Encapsed(
parts: array(
0: Scalar_EncapsedStringPart(
value: \{
@ -162,7 +214,7 @@ array(
)
)
)
13: Scalar_Encapsed(
17: Scalar_Encapsed(
parts: array(
0: Scalar_EncapsedStringPart(
value: \
@ -172,7 +224,7 @@ array(
)
)
)
14: Scalar_Encapsed(
18: Scalar_Encapsed(
parts: array(
0: Scalar_EncapsedStringPart(
value: \{
@ -185,7 +237,7 @@ array(
)
)
)
15: Scalar_Encapsed(
19: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: Expr_Variable(
@ -197,7 +249,7 @@ array(
)
)
)
16: Scalar_Encapsed(
20: Scalar_Encapsed(
parts: array(
0: Scalar_EncapsedStringPart(
value: $
@ -212,7 +264,7 @@ array(
)
)
)
17: Scalar_Encapsed(
21: Scalar_Encapsed(
parts: array(
0: Scalar_EncapsedStringPart(
value: A
@ -225,14 +277,14 @@ array(
)
)
)
18: Scalar_Encapsed(
22: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: A
)
)
)
19: Scalar_Encapsed(
23: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: A

View File

@ -76,8 +76,21 @@ array(
-----
<?php class A extends static {}
-----
Syntax error, unexpected T_STATIC, expecting T_STRING or T_NAMESPACE or T_NS_SEPARATOR from 1:23 to 1:28
Cannot use 'static' as class name as it is reserved from 1:23 to 1:28
array(
0: Stmt_Class(
flags: 0
name: A
extends: Name(
parts: array(
0: static
)
)
implements: array(
)
stmts: array(
)
)
)
-----
<?php class A implements self {}
@ -122,8 +135,22 @@ array(
-----
<?php class A implements static {}
-----
Syntax error, unexpected T_STATIC, expecting T_STRING or T_NAMESPACE or T_NS_SEPARATOR from 1:26 to 1:31
Cannot use 'static' as interface name as it is reserved from 1:26 to 1:31
array(
0: Stmt_Class(
flags: 0
name: A
extends: null
implements: array(
0: Name(
parts: array(
0: static
)
)
)
stmts: array(
)
)
)
-----
<?php interface self {}
@ -196,6 +223,18 @@ array(
-----
<?php interface A extends static {}
-----
Syntax error, unexpected T_STATIC, expecting T_STRING or T_NAMESPACE or T_NS_SEPARATOR from 1:27 to 1:32
Cannot use 'static' as interface name as it is reserved from 1:27 to 1:32
array(
)
0: Stmt_Interface(
name: A
extends: array(
0: Name(
parts: array(
0: static
)
)
)
stmts: array(
)
)
)

View File

@ -1,7 +1,7 @@
Scalar type declarations
-----
<?php
function test(bool $a, Int $b, FLOAT $c, StRiNg $d, iterable $e) : void {}
function test(bool $a, Int $b, FLOAT $c, StRiNg $d, iterable $e, object $f) : void {}
-----
!!php7
array(
@ -44,9 +44,16 @@ array(
name: e
default: null
)
5: Param(
type: object
byRef: false
variadic: false
name: f
default: null
)
)
returnType: void
stmts: array(
)
)
)
)

View File

@ -0,0 +1,22 @@
Trailing comment after braced namespace declaration
-----
<?php
namespace Foo {}
// Comment
-----
array(
0: Stmt_Namespace(
name: Name(
parts: array(
0: Foo
)
)
stmts: array(
)
)
1: Stmt_Nop(
comments: array(
0: // Comment
)
)
)

View File

@ -5,9 +5,32 @@ Invalid group use syntax
use Foo\{Bar}
use Bar\{Foo};
-----
!!php7
Syntax error, unexpected T_USE, expecting ';' from 4:1 to 4:3
array(
0: Stmt_GroupUse(
type: TYPE_UNKNOWN (0)
prefix: Name(
parts: array(
0: Foo
)
)
uses: array(
0: Stmt_UseUse(
type: TYPE_NORMAL (1)
name: Name(
parts: array(
0: Bar
)
)
alias: Bar
)
)
comments: array(
0: // Missing semicolon
)
)
1: Stmt_GroupUse(
type: TYPE_UNKNOWN (0)
prefix: Name(
parts: array(
@ -32,16 +55,34 @@ array(
// Missing NS separator
use Foo {Bar, Baz};
-----
Syntax error, unexpected '{', expecting ',' or ';' from 3:9 to 3:9
!!php7
Syntax error, unexpected '{', expecting ';' from 3:9 to 3:9
array(
0: Expr_ConstFetch(
0: Stmt_Use(
type: TYPE_NORMAL (1)
uses: array(
0: Stmt_UseUse(
type: TYPE_UNKNOWN (0)
name: Name(
parts: array(
0: Foo
)
)
alias: Foo
)
)
comments: array(
0: // Missing NS separator
)
)
1: Expr_ConstFetch(
name: Name(
parts: array(
0: Bar
)
)
)
1: Expr_ConstFetch(
2: Expr_ConstFetch(
name: Name(
parts: array(
0: Baz

View File

@ -0,0 +1,47 @@
Group use can have trailing comma
-----
<?php
use A\{B,};
use function A\{b,};
-----
!!php7
array(
0: Stmt_GroupUse(
type: TYPE_UNKNOWN (0)
prefix: Name(
parts: array(
0: A
)
)
uses: array(
0: Stmt_UseUse(
type: TYPE_NORMAL (1)
name: Name(
parts: array(
0: B
)
)
alias: B
)
)
)
1: Stmt_GroupUse(
type: TYPE_FUNCTION (2)
prefix: Name(
parts: array(
0: A
)
)
uses: array(
0: Stmt_UseUse(
type: TYPE_UNKNOWN (0)
name: Name(
parts: array(
0: b
)
)
alias: b
)
)
)
)

View File

@ -0,0 +1,53 @@
Comments in arrays and function calls
-----
<?php
$arr = [
// Foo
$foo,
// Bar
$bar,
// Discarded
];
[
// Foo
$foo,
,
// Bar
$bar,
] = $arr;
foo(
// Foo
$foo,
// Bar
$bar
);
new Foo(
// Foo
$foo
);
-----
!!php7
$arr = [
// Foo
$foo,
// Bar
$bar,
];
[
// Foo
$foo,
,
// Bar
$bar,
] = $arr;
foo(
// Foo
$foo,
// Bar
$bar
);
new Foo(
// Foo
$foo
);

View File

@ -110,7 +110,7 @@ FALSE;
0.0;
1.0;
1.0E+100;
INF;
\INF;
1.0E-100;
1.0E+84;
378282246310005.0;

View File

@ -31,5 +31,5 @@ Number literals
-42.5;
1.0E+42;
-1.0E+42;
INF;
-INF;
\INF;
-\INF;

View File

@ -1,11 +1,11 @@
Nullable types
-----
<?php
function test(?Foo $bar, ?string $foo) : ?Baz
function test(?Foo $bar, ?string $foo, ?\Xyz $zyx) : ?Baz
{
}
-----
!!php7
function test(?Foo $bar, ?string $foo) : ?Baz
function test(?Foo $bar, ?string $foo, ?\Xyz $zyx) : ?Baz
{
}

View File

@ -1,4 +1,4 @@
wget -q https://github.com/php/php-src/archive/php-7.0.5.tar.gz
wget -q https://github.com/php/php-src/archive/php-7.1.0.tar.gz
mkdir -p ./data/php-src
tar -xzf ./php-7.0.5.tar.gz -C ./data/php-src --strip-components=1
tar -xzf ./php-7.1.0.tar.gz -C ./data/php-src --strip-components=1
php -n test_old/run.php --verbose --no-progress PHP7 ./data/php-src

View File

@ -83,18 +83,15 @@ switch ($testType) {
| Zend.tests.multibyte.multibyte_encoding_001
| Zend.tests.multibyte.multibyte_encoding_004
| Zend.tests.multibyte.multibyte_encoding_005
# token_get_all bug (https://bugs.php.net/bug.php?id=60097)
| Zend.tests.bug47516
# pretty print difference due to INF vs 1e1000
| ext.standard.tests.general_functions.bug27678
| tests.lang.bug24640
# pretty print differences due to negative LNumbers
| Zend.tests.neg_num_string
| Zend.tests.bug72918
# pretty print difference due to nop statements
| ext.mbstring.tests.htmlent
| ext.standard.tests.file.fread_basic
# tests using __halt_compiler as semi reserved keyword
| Zend.tests.grammar.semi_reserved_001
| Zend.tests.grammar.semi_reserved_002
| Zend.tests.grammar.semi_reserved_005
)\.phpt$~x', $file)) {
return null;
}