mirror of
https://github.com/nikic/PHP-Parser.git
synced 2025-07-09 16:36:31 +02:00
Compare commits
218 Commits
Author | SHA1 | Date | |
---|---|---|---|
ce5be709d5 | |||
9829bf69cd | |||
c8282e6e76 | |||
a73aa7eec1 | |||
1fe8f09caa | |||
47509cf927 | |||
5b96a11a1f | |||
7faa1dcab9 | |||
65af37f7b0 | |||
d6361136e1 | |||
e05ef23743 | |||
73a9d494fb | |||
94f10d3c50 | |||
c4bbc8e236 | |||
6dffb72ce0 | |||
eb73441032 | |||
9a6a147369 | |||
5c2cc50455 | |||
58eb1ea7c3 | |||
719ca71d4a | |||
c542e5d86a | |||
a9074c7444 | |||
b2f26d30ee | |||
75cd4ab7a5 | |||
33602889c1 | |||
98d28d7aa0 | |||
e4b837e0c4 | |||
2b9c5a62cb | |||
99e89743bd | |||
39a039fa42 | |||
fcf23101dd | |||
c8898df3dd | |||
b2961915a6 | |||
6f3fd7834a | |||
f78af2c9c8 | |||
eecaf1e93b | |||
950ada4cba | |||
0d4239ef56 | |||
e3a9356178 | |||
5118e21c6e | |||
40455b5c18 | |||
fe6755ff4c | |||
f57d217e91 | |||
e0a75ededa | |||
2496cd38ad | |||
965e53a164 | |||
dc85742034 | |||
196f177cfe | |||
b9afcdfd92 | |||
3bb874fcec | |||
feb82eed33 | |||
0ef15c111a | |||
d341d94976 | |||
0265c28e6e | |||
5bd8cb84de | |||
ebeeae19a6 | |||
5ede167835 | |||
49324ea412 | |||
21e51c8cf6 | |||
e7a2abb03b | |||
b862de1f5b | |||
8090531acd | |||
49253c5dbb | |||
c5ac17711d | |||
1d62e9d8cc | |||
e3195c246f | |||
2a3bc608dc | |||
90ab32f046 | |||
7434a682e5 | |||
0fbb5f90a1 | |||
5e6627c895 | |||
f872fa9b0b | |||
d5668f536d | |||
a5db176903 | |||
7fbbf83011 | |||
42e368e964 | |||
9c9a8cddce | |||
fd7ee2e083 | |||
179d32cfaf | |||
f2b7a31509 | |||
d8312a09a3 | |||
813c9f1545 | |||
ef9a154d09 | |||
0da72fad00 | |||
71fa7c6674 | |||
f3f24e03ae | |||
bc21514ecf | |||
04e05907c3 | |||
61e060694d | |||
602b9807eb | |||
f372a4c4ab | |||
d18dcc0c7f | |||
74c57eef0e | |||
fdbddc4b8c | |||
ca3b44bf60 | |||
dca46febc9 | |||
1a1bd1448d | |||
9620f79cdc | |||
583b560f71 | |||
db3dafd64d | |||
bb2c5303ae | |||
5038dcc251 | |||
69c00ebbe4 | |||
a0e7d5e0aa | |||
51ec2a25fe | |||
5d1e3be7d4 | |||
9d42e4a2e2 | |||
cc75dd3612 | |||
5f621c5adc | |||
29b9015f51 | |||
e6619f5514 | |||
6b4a17b3e0 | |||
30abe062f2 | |||
dff239267f | |||
8b64195cf2 | |||
9caa51b3a5 | |||
5513073a53 | |||
659d26c231 | |||
648800f07f | |||
23bf4f0c13 | |||
57ac7e39bf | |||
272ab6c8d8 | |||
0731b47655 | |||
3b7d8e8b5d | |||
a35c2a2067 | |||
55b2ead967 | |||
e1a0ec3724 | |||
66896dbde6 | |||
338bc1f8e7 | |||
ab80054e97 | |||
a6d2cd69f8 | |||
6996db1e3a | |||
e30c3ac01b | |||
a5477a4eaf | |||
7a40498cb4 | |||
65f1adbe65 | |||
c8454271e1 | |||
62f83a0dc2 | |||
611fa5c7f1 | |||
4defbc2174 | |||
33a39fae06 | |||
e4eab9ec0c | |||
6aaa87f143 | |||
08f97eb4ef | |||
8d18848fb0 | |||
805078e0a9 | |||
52dafafd10 | |||
dba7524b37 | |||
617bf0aa41 | |||
dce19b074b | |||
edbf162e4c | |||
b23c53df5f | |||
cea0c4a9d6 | |||
879e8dcd6d | |||
729c7bde0c | |||
8982315b4e | |||
0f556c16f5 | |||
7ec277e1e1 | |||
1a627872f0 | |||
592836c4dc | |||
68defc2c6a | |||
d225555830 | |||
251e689283 | |||
01f4be6b4d | |||
dc28449d81 | |||
3ad0d4b310 | |||
4dbf067b4b | |||
5567f0ab3b | |||
0c34706799 | |||
f9fc2fc9ee | |||
a2d7e8977a | |||
73cace360d | |||
c96636d192 | |||
d56ff5a351 | |||
3028bc8081 | |||
91295a0790 | |||
d600c60779 | |||
e3bc5b564d | |||
53eac36a3f | |||
ce5c76d79b | |||
b7ffdbbb92 | |||
8f1eacdab7 | |||
1366e833a1 | |||
6930feac43 | |||
54275ad181 | |||
21ca7eaf1b | |||
a86779198f | |||
ac05ef6f95 | |||
74251fca9f | |||
0a445c7656 | |||
a710f32a6a | |||
9689763e20 | |||
1a63a915f2 | |||
4071c4645d | |||
f56db26d8b | |||
0dd2b9a74c | |||
4cd2b95a23 | |||
7ab88416ac | |||
ba625063e7 | |||
b4b93ccb21 | |||
01643e06d3 | |||
4387454fe0 | |||
55fdbc6dbc | |||
e69c9ee38c | |||
894c3f787d | |||
a7797918b8 | |||
46975107a7 | |||
e0f3e8a492 | |||
158322e1e4 | |||
2438848487 | |||
f5432a76b6 | |||
800d278369 | |||
8507af6f4a | |||
7c98ad6f9b | |||
d774dbc1b7 | |||
1a93cc3b9d | |||
e26e63e9b0 | |||
0f69f12b94 |
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
vendor/
|
||||||
|
composer.lock
|
||||||
|
grammar/kmyacc.exe
|
||||||
|
grammar/y.output
|
17
.travis.yml
17
.travis.yml
@ -1,13 +1,26 @@
|
|||||||
language: php
|
language: php
|
||||||
|
|
||||||
|
sudo: false
|
||||||
|
|
||||||
php:
|
php:
|
||||||
- 5.3
|
|
||||||
- 5.4
|
- 5.4
|
||||||
- 5.5
|
- 5.5
|
||||||
- 5.6
|
- 5.6
|
||||||
|
- 7.0
|
||||||
|
- nightly
|
||||||
- hhvm
|
- hhvm
|
||||||
|
|
||||||
|
install:
|
||||||
|
- if [ $TRAVIS_PHP_VERSION = '5.6' ]; then composer require satooshi/php-coveralls '~1.0'; fi
|
||||||
|
- composer install --prefer-source
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- php: hhvm
|
- php: nightly
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
|
|
||||||
|
script:
|
||||||
|
if [ $TRAVIS_PHP_VERSION = '5.6' ]; then vendor/bin/phpunit --coverage-clover build/logs/clover.xml; else vendor/bin/phpunit; fi
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
if [ $TRAVIS_PHP_VERSION = '5.6' ]; then php vendor/bin/coveralls; fi
|
||||||
|
232
CHANGELOG.md
232
CHANGELOG.md
@ -1,16 +1,231 @@
|
|||||||
Version 1.0.3-dev
|
Version 2.0.2-dev
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Nothing yet.
|
Nothing yet.
|
||||||
|
|
||||||
Version 1.0.2 (04.11.2014)
|
Version 2.0.1 (2016-02-28)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* `declare() {}` and `declare();` are not semantically equivalent and will now result in different
|
||||||
|
ASTs. The format case will have an empty `stmts` array, while the latter will set `stmts` to
|
||||||
|
`null`.
|
||||||
|
* Magic constants are now supported as semi-reserved keywords.
|
||||||
|
* A shebang line like `#!/usr/bin/env php` is now allowed at the start of a namespaced file.
|
||||||
|
Previously this generated an exception.
|
||||||
|
* The `prettyPrintFile()` method will not strip a trailing `?>` from the raw data that follows a
|
||||||
|
`__halt_compiler()` statement.
|
||||||
|
* The `prettyPrintFile()` method will not strip an opening `<?php` if the file starts with a
|
||||||
|
comment followed by InlineHTML.
|
||||||
|
|
||||||
|
Version 2.0.0 (2015-12-04)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* String parts of encapsed strings are now represented using `Scalar\EncapsStringPart` nodes.
|
||||||
|
Previously raw strings were used. This affects the `parts` child of `Scalar\Encaps` and
|
||||||
|
`Expr\ShellExec`. The change has been done to allow assignment of attributes to encapsed string
|
||||||
|
parts.
|
||||||
|
|
||||||
|
Version 2.0.0-beta1 (2015-10-21)
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fixed issue with too many newlines being stripped at the end of heredoc/nowdoc strings in some
|
||||||
|
cases. (#227)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Update group use support to be in line with recent PHP 7.0 builds.
|
||||||
|
* Renamed `php-parse.php` to `php-parse` and registered it as a composer bin.
|
||||||
|
* Use composer PSR-4 autoloader instead of custom autoloader.
|
||||||
|
* Specify phpunit as a dev dependency.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Added `shortArraySyntax` option to pretty printer, to print all arrays using short syntax.
|
||||||
|
|
||||||
|
Version 2.0.0-alpha1 (2015-07-14)
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
A more detailed description of backwards incompatible changes can be found in the
|
||||||
|
[upgrading guide](UPGRADE-2.0.md).
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
* Removed support for running on PHP 5.4. It is however still possible to parse PHP 5.2 and PHP 5.3
|
||||||
|
code while running on a newer version.
|
||||||
|
* Removed legacy class name aliases. This includes the old non-namespaced class names and the old
|
||||||
|
names for classes that were renamed for PHP 7 compatibility.
|
||||||
|
* Removed support for legacy node format. All nodes must have a `getSubNodeNames()` method now.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Added support for remaining PHP 7 features that were not present in 1.x:
|
||||||
|
* Group use declarations. These are represented using `Stmt\GroupUse` nodes. Furthermore a `type`
|
||||||
|
attribute was added to `Stmt\UseUse` to handle mixed group use declarations.
|
||||||
|
* Uniform variable syntax.
|
||||||
|
* Generalized yield operator.
|
||||||
|
* Scalar type declarations. These are presented using `'bool'`, `'int'`, `'float'` and `'string'`
|
||||||
|
as the type. The PHP 5 parser also accepts these, however they'll be `Name` instances there.
|
||||||
|
* Unicode escape sequences.
|
||||||
|
* Added `PhpParser\ParserFactory` class, which should be used to create parser instances.
|
||||||
|
* Added `Name::concat()` which concatenates two names.
|
||||||
|
* Added `Name->slice()` which takes a subslice of a name.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* `PhpParser\Parser` is now an interface, implemented by `Parser\Php5`, `Parser\Php7` and
|
||||||
|
`Parser\Multiple`. The `Multiple` parser will try multiple parsers, until one succeeds.
|
||||||
|
* Token constants are now defined on `PhpParser\Parser\Tokens` rather than `PhpParser\Parser`.
|
||||||
|
* The `Name->set()`, `Name->append()`, `Name->prepend()` and `Name->setFirst()` methods are
|
||||||
|
deprecated in favor of `Name::concat()` and `Name->slice()`.
|
||||||
|
* The `NodeTraverser` no longer clones nodes by default. The old behavior can be restored by
|
||||||
|
passing `true` to the constructor.
|
||||||
|
* The constructor for `Scalar` nodes no longer has a default value. E.g. `new LNumber()` should now
|
||||||
|
be written as `new LNumber(0)`.
|
||||||
|
|
||||||
|
Version 1.4.0 (2015-07-14)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Added interface `PhpParser\Node\FunctionLike`, which is implemented by `Stmt\ClassMethod`,
|
||||||
|
`Stmt\Function_` and `Expr\Closure` nodes. This interface provides getters for their common
|
||||||
|
subnodes.
|
||||||
|
* Added `Node\Stmt\ClassLike::getMethod()` to look up a specific method on a class/interface/trait.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fixed `isPublic()` return value for implicitly public properties and methods that define and
|
||||||
|
additional modifier like `static` or `abstract`.
|
||||||
|
* Properties are now accepted by the trait builder.
|
||||||
|
* Fixed `__HALT_COMPILER_OFFSET__` support on HHVM.
|
||||||
|
|
||||||
|
Version 1.3.0 (2015-05-02)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Errors can now store the attributes of the node/token where the error occurred. Previously only the start line was
|
||||||
|
stored.
|
||||||
|
* If file positions are enabled in the lexer, errors can now provide column information if it is available. See
|
||||||
|
[documentation](https://github.com/nikic/PHP-Parser/blob/master/doc/component/Error.markdown#column-information).
|
||||||
|
* The parser now provides an experimental error recovery mode, which can be enabled by disabling the `throwOnError`
|
||||||
|
parser option. In this mode the parser will try to construct a partial AST even if the code is not valid PHP. See
|
||||||
|
[documentation](https://github.com/nikic/PHP-Parser/blob/master/doc/component/Error.markdown#error-recovery).
|
||||||
|
* Added support for PHP 7 `yield from` expression. It is represented by `Expr\YieldFrom`.
|
||||||
|
* Added support for PHP 7 anonymous classes. These are represented by ordinary `Stmt\Class_` nodes with the name set to
|
||||||
|
`null`. Furthermore this implies that `Expr\New_` can now contain a `Stmt\Class_` in its `class` subnode.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fixed registration of PHP 7 aliases, for the case where the old name was used before the new name.
|
||||||
|
* Fixed handling of precedence when pretty-printing `print` expressions.
|
||||||
|
* Floating point numbers are now pretty-printed with a higher precision.
|
||||||
|
* Checks for special class names like `self` are now case-insensitive.
|
||||||
|
|
||||||
|
Version 1.2.2 (2015-04-03)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
* The `NameResolver` now resolves parameter type hints when entering the function/method/closure node. As such other
|
||||||
|
visitors running after it will be able to make use of the resolved names at that point already.
|
||||||
|
* The autoloader no longer sets the `unserialize_callback_func` ini option on registration - this is not necessary and
|
||||||
|
may cause issues when running PhpUnit tests with process isolation.
|
||||||
|
|
||||||
|
Version 1.2.1 (2015-03-24)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
* Fixed registration of the aliases introduced in 1.2.0. Previously the old class names could not be used in
|
||||||
|
`instanceof` checks under some circumstances.
|
||||||
|
|
||||||
|
Version 1.2.0 (2015-03-22)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* To ensure compatibility with PHP 7, the following node classes have been renamed:
|
||||||
|
|
||||||
|
OLD => NEW
|
||||||
|
PhpParser\Node\Expr\Cast\Bool => PhpParser\Node\Expr\Cast\Bool_
|
||||||
|
PhpParser\Node\Expr\Cast\Int => PhpParser\Node\Expr\Cast\Int_
|
||||||
|
PhpParser\Node\Expr\Cast\Object => PhpParser\Node\Expr\Cast\Object_
|
||||||
|
PhpParser\Node\Expr\Cast\String => PhpParser\Node\Expr\Cast\String_
|
||||||
|
PhpParser\Node\Scalar\String => PhpParser\Node\Scalar\String_
|
||||||
|
|
||||||
|
**The previous class names are still supported as aliases.** However it is strongly encouraged to use the new names
|
||||||
|
in order to make your code compatible with PHP 7.
|
||||||
|
|
||||||
|
* Subnodes are now stored using real properties instead of an array. This improves performance and memory usage of the
|
||||||
|
initial parse and subsequent node tree operations. The `NodeAbstract` class still supports the old way of specifying
|
||||||
|
subnodes, however this is *deprecated*. In any case properties that are assigned to a node after creation will no
|
||||||
|
longer be considered as subnodes.
|
||||||
|
|
||||||
|
* Methods and property declarations will no longer set the `Stmt\Class_::MODIFIER_PUBLIC` flag if no visibility is
|
||||||
|
explicitly given. However the `isPublic()` method will continue to return true. This allows you to distinguish whether
|
||||||
|
a method/property is explicitly or implicitly public and control the pretty printer output more precisely.
|
||||||
|
|
||||||
|
* The `Stmt\Class_`, `Stmt\Interface_` and `Stmt\Trait_` nodes now inherit from `Stmt\ClassLike`, which provides a
|
||||||
|
`getMethods()` method. Previously this method was only available on `Stmt\Class_`.
|
||||||
|
|
||||||
|
* Support including the `bootstrap.php` file multiple times.
|
||||||
|
|
||||||
|
* Make documentation and tests part of the release tarball again.
|
||||||
|
|
||||||
|
* Improve support for HHVM and PHP 7.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Added support for PHP 7 return type declarations. This adds an additional `returnType` subnode to `Stmt\Function_`,
|
||||||
|
`Stmt\ClassMethod` and `Expr\Closure`.
|
||||||
|
|
||||||
|
* Added support for the PHP 7 null coalesce operator `??`. The operator is represented by `Expr\BinaryOp\Coalesce`.
|
||||||
|
|
||||||
|
* Added support for the PHP 7 spaceship operator `<=>`. The operator is represented by `Expr\BinaryOp\Spaceship`.
|
||||||
|
|
||||||
|
* Added use builder.
|
||||||
|
|
||||||
|
* Added global namespace support to the namespace builder.
|
||||||
|
|
||||||
|
* Added a constructor flag to `NodeTraverser`, which disables cloning of nodes.
|
||||||
|
|
||||||
|
Version 1.1.0 (2015-01-18)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
* Methods that do not specify an explicit visibility (e.g. `function method()`) will now have the `MODIFIER_PUBLIC`
|
||||||
|
flag set. This also means that their `isPublic()` method will return true.
|
||||||
|
|
||||||
|
* Declaring a property as abstract or final is now an error.
|
||||||
|
|
||||||
|
* The `Lexer` and `Lexer\Emulative` classes now accept an `$options` array in their constructors. Currently only the
|
||||||
|
`usedAttributes` option is supported, which determines which attributes will be added to AST nodes. In particular
|
||||||
|
it is now possible to add information on the token and file positions corresponding to a node. For more details see
|
||||||
|
the [Lexer component](https://github.com/nikic/PHP-Parser/blob/master/doc/component/Lexer.markdown) documentation.
|
||||||
|
|
||||||
|
* Node visitors can now return `NodeTraverser::DONT_TRAVERSE_CHILDREN` from `enterNode()` in order to skip all children
|
||||||
|
of the current node, for all visitors.
|
||||||
|
|
||||||
|
* Added builders for traits and namespaces.
|
||||||
|
|
||||||
|
* The class, interface, trait, function, method and property builders now support adding doc comments using the
|
||||||
|
`setDocComment()` method.
|
||||||
|
|
||||||
|
* Added support for fully-qualified and namespace-relative names in builders. No longer allow use of name component
|
||||||
|
arrays.
|
||||||
|
|
||||||
|
* Do not add documentation and tests to distribution archive files.
|
||||||
|
|
||||||
|
Version 1.0.2 (2014-11-04)
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
* The `NameResolver` visitor now also resolves names in trait adaptations (aliases and precedence declarations).
|
* The `NameResolver` visitor now also resolves names in trait adaptations (aliases and precedence declarations).
|
||||||
|
|
||||||
* Remove stray whitespace when pretty-printing trait adaptations that only change visibility.
|
* Remove stray whitespace when pretty-printing trait adaptations that only change visibility.
|
||||||
|
|
||||||
Version 1.0.1 (14.10.2014)
|
Version 1.0.1 (2014-10-14)
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
* Disallow `new` expressions without a class name. Previously `new;` was accidentally considered to be valid code.
|
* Disallow `new` expressions without a class name. Previously `new;` was accidentally considered to be valid code.
|
||||||
@ -21,14 +236,14 @@ Version 1.0.1 (14.10.2014)
|
|||||||
|
|
||||||
* Prevent truncation of `var_dump()` output in the `php-parse.php` script if XDebug is used.
|
* Prevent truncation of `var_dump()` output in the `php-parse.php` script if XDebug is used.
|
||||||
|
|
||||||
Version 1.0.0 (12.09.2014)
|
Version 1.0.0 (2014-09-12)
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
* [BC] Removed deprecated `Template` and `TemplateLoader` classes.
|
* [BC] Removed deprecated `Template` and `TemplateLoader` classes.
|
||||||
|
|
||||||
* Fixed XML unserializer to properly work with new namespaced node names.
|
* Fixed XML unserializer to properly work with new namespaced node names.
|
||||||
|
|
||||||
Version 1.0.0-beta2 (31.08.2014)
|
Version 1.0.0-beta2 (2014-08-31)
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
* [PHP 5.6] Updated support for constant scalar expressions to comply with latest changes. This means that arrays
|
* [PHP 5.6] Updated support for constant scalar expressions to comply with latest changes. This means that arrays
|
||||||
@ -53,7 +268,7 @@ Version 1.0.0-beta2 (31.08.2014)
|
|||||||
`lib/PhpParser/Parser.php`). Furthermore the parser now uses meaningful variable names and contains comments
|
`lib/PhpParser/Parser.php`). Furthermore the parser now uses meaningful variable names and contains comments
|
||||||
explaining their usage.
|
explaining their usage.
|
||||||
|
|
||||||
Version 1.0.0-beta1 (27.03.2014)
|
Version 1.0.0-beta1 (2014-03-27)
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
* [BC] PHP-Parser now requires PHP 5.3 or newer to run. It is however still possible to *parse* PHP 5.2 source code,
|
* [BC] PHP-Parser now requires PHP 5.3 or newer to run. It is however still possible to *parse* PHP 5.2 source code,
|
||||||
@ -110,6 +325,5 @@ Version 1.0.0-beta1 (27.03.2014)
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**This changelog only includes changes from the 1.0 series. For older changes see the [0.9 series changelog][1].**
|
**This changelog only includes changes from the 1.0 and 2.0 series. For older changes see the
|
||||||
|
[0.9 series changelog][https://github.com/nikic/PHP-Parser/blob/0.9/CHANGELOG.md].**
|
||||||
[1]: https://github.com/nikic/PHP-Parser/blob/0.9/CHANGELOG.md
|
|
32
README.md
32
README.md
@ -1,12 +1,14 @@
|
|||||||
PHP Parser
|
PHP Parser
|
||||||
==========
|
==========
|
||||||
|
|
||||||
This is a PHP 5.2 to PHP 5.6 parser written in PHP. It's purpose is to simplify static code analysis and
|
[](https://travis-ci.org/nikic/PHP-Parser) [](https://coveralls.io/github/nikic/PHP-Parser?branch=master)
|
||||||
|
|
||||||
|
This is a PHP 5.2 to PHP 7.0 parser written in PHP. Its purpose is to simplify static code analysis and
|
||||||
manipulation.
|
manipulation.
|
||||||
|
|
||||||
[**Documentation for version 1.0.x**][doc_master] (stable; for running on PHP >= 5.3).
|
[**Documentation for version 2.x**][doc_master] (stable; for running on PHP >= 5.4; for parsing PHP 5.2 to PHP 7.0).
|
||||||
|
|
||||||
[Documentation for version 0.9.x][doc_0_9] (unsupported; for running on PHP 5.2).
|
[Documentation for version 1.x][doc_1_x] (stable; for running on PHP >= 5.3; for parsing PHP 5.2 to PHP 5.6).
|
||||||
|
|
||||||
In a Nutshell
|
In a Nutshell
|
||||||
-------------
|
-------------
|
||||||
@ -22,7 +24,7 @@ hello\world('foo', 'bar' . 'baz');
|
|||||||
|
|
||||||
You'll get a syntax tree looking roughly like this:
|
You'll get a syntax tree looking roughly like this:
|
||||||
|
|
||||||
```
|
```php
|
||||||
array(
|
array(
|
||||||
0: Stmt_Echo(
|
0: Stmt_Echo(
|
||||||
exprs: array(
|
exprs: array(
|
||||||
@ -70,7 +72,25 @@ programming errors or security issues).
|
|||||||
Additionally, you can convert a syntax tree back to PHP code. This allows you to do code preprocessing
|
Additionally, you can convert a syntax tree back to PHP code. This allows you to do code preprocessing
|
||||||
(like automatedly porting code to older PHP versions).
|
(like automatedly porting code to older PHP versions).
|
||||||
|
|
||||||
So, that's it, in a nutshell. You can find everything else in the [docs][doc_master].
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
[doc_0_9]: https://github.com/nikic/PHP-Parser/tree/0.9/doc
|
The preferred installation method is [composer](https://getcomposer.org):
|
||||||
|
|
||||||
|
php composer.phar require nikic/php-parser
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
-------------
|
||||||
|
|
||||||
|
1. [Introduction](doc/0_Introduction.markdown)
|
||||||
|
2. [Usage of basic components](doc/2_Usage_of_basic_components.markdown)
|
||||||
|
3. [Other node tree representations](doc/3_Other_node_tree_representations.markdown)
|
||||||
|
4. [Code generation](doc/4_Code_generation.markdown)
|
||||||
|
|
||||||
|
Component documentation:
|
||||||
|
|
||||||
|
1. [Error](doc/component/Error.markdown)
|
||||||
|
2. [Lexer](doc/component/Lexer.markdown)
|
||||||
|
|
||||||
|
[doc_1_x]: https://github.com/nikic/PHP-Parser/tree/1.x/doc
|
||||||
[doc_master]: https://github.com/nikic/PHP-Parser/tree/master/doc
|
[doc_master]: https://github.com/nikic/PHP-Parser/tree/master/doc
|
74
UPGRADE-2.0.md
Normal file
74
UPGRADE-2.0.md
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
Upgrading from PHP-Parser 1.x to 2.0
|
||||||
|
====================================
|
||||||
|
|
||||||
|
### PHP version requirements
|
||||||
|
|
||||||
|
PHP-Parser now requires PHP 5.4 or newer to run. It is however still possible to *parse* PHP 5.2 and
|
||||||
|
PHP 5.3 source code, while running on a newer version.
|
||||||
|
|
||||||
|
### Creating a parser instance
|
||||||
|
|
||||||
|
Parser instances should now be created through the `ParserFactory`. Old direct instantiation code
|
||||||
|
will not work, because the parser class was renamed.
|
||||||
|
|
||||||
|
Old:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use PhpParser\Parser, PhpParser\Lexer;
|
||||||
|
$parser = new Parser(new Lexer\Emulative);
|
||||||
|
```
|
||||||
|
|
||||||
|
New:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use PhpParser\ParserFactory;
|
||||||
|
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
|
||||||
|
```
|
||||||
|
|
||||||
|
The first argument to `ParserFactory` determines how different PHP versions are handled. The
|
||||||
|
possible values are:
|
||||||
|
|
||||||
|
* `ParserFactory::PREFER_PHP7`: Try to parse code as PHP 7. If this fails, try to parse it as PHP 5.
|
||||||
|
* `ParserFactory::PREFER_PHP5`: Try to parse code as PHP 5. If this fails, try to parse it as PHP 7.
|
||||||
|
* `ParserFactory::ONLY_PHP7`: Parse code as PHP 7.
|
||||||
|
* `ParserFactory::ONLY_PHP5`: Parse code as PHP 5.
|
||||||
|
|
||||||
|
For most practical purposes the difference between `PREFER_PHP7` and `PREFER_PHP5` is mainly whether
|
||||||
|
a scalar type hint like `string` will be stored as `'string'` (PHP 7) or as `new Name('string')`
|
||||||
|
(PHP 5).
|
||||||
|
|
||||||
|
To use a custom lexer, pass it as the second argument to the `create()` method:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use PhpParser\ParserFactory;
|
||||||
|
$lexer = new MyLexer;
|
||||||
|
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7, $lexer);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rename of the `PhpParser\Parser` class
|
||||||
|
|
||||||
|
`PhpParser\Parser` is now an interface, which is implemented by `Parser\Php5`, `Parser\Php7` and
|
||||||
|
`Parser\Multiple`. Parser tokens are now defined in `Parser\Tokens`. If you use the `ParserFactory`
|
||||||
|
described above to create your parser instance, these changes should have no further impact on you.
|
||||||
|
|
||||||
|
### Removal of legacy aliases
|
||||||
|
|
||||||
|
All legacy aliases for classes have been removed. This includes the old non-namespaced `PHPParser_`
|
||||||
|
classes, as well as the classes that had to be renamed for PHP 7 support.
|
||||||
|
|
||||||
|
### Deprecations
|
||||||
|
|
||||||
|
The `set()`, `setFirst()`, `append()` and `prepend()` methods of the `Node\Name` class have been
|
||||||
|
deprecated. Instead `Name::concat()` and `Name->slice()` should be used.
|
||||||
|
|
||||||
|
### Miscellaneous
|
||||||
|
|
||||||
|
* The `NodeTraverser` no longer clones nodes by default. If you want to restore the old behavior,
|
||||||
|
pass `true` to the constructor.
|
||||||
|
* The legacy node format has been removed. If you use custom nodes, they are now expected to
|
||||||
|
implement a `getSubNodeNames()` method.
|
||||||
|
* The default value for `Scalar` node constructors was removed. This means that something like
|
||||||
|
`new LNumber()` should be replaced by `new LNumber(0)`.
|
||||||
|
* String parts of encapsed strings are now represented using `Scalar\EncapsStringPart` nodes, while
|
||||||
|
previously raw strings were used. This affects the `parts` child of `Scalar\Encaps` and
|
||||||
|
`Expr\ShellExec`.
|
@ -1,15 +1,21 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
require __DIR__ . '/../lib/bootstrap.php';
|
foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) {
|
||||||
|
if (file_exists($file)) {
|
||||||
|
require $file;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ini_set('xdebug.max_nesting_level', 2000);
|
ini_set('xdebug.max_nesting_level', 3000);
|
||||||
|
|
||||||
// Disable XDebug var_dump() output truncation
|
// Disable XDebug var_dump() output truncation
|
||||||
ini_set('xdebug.var_display_max_children', -1);
|
ini_set('xdebug.var_display_max_children', -1);
|
||||||
ini_set('xdebug.var_display_max_data', -1);
|
ini_set('xdebug.var_display_max_data', -1);
|
||||||
ini_set('xdebug.var_display_max_depth', -1);
|
ini_set('xdebug.var_display_max_depth', -1);
|
||||||
|
|
||||||
list($operations, $files) = parseArgs($argv);
|
list($operations, $files, $attributes) = parseArgs($argv);
|
||||||
|
|
||||||
/* Dump nodes by default */
|
/* Dump nodes by default */
|
||||||
if (empty($operations)) {
|
if (empty($operations)) {
|
||||||
@ -20,7 +26,10 @@ if (empty($files)) {
|
|||||||
showHelp("Must specify at least one file.");
|
showHelp("Must specify at least one file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$parser = new PhpParser\Parser(new PhpParser\Lexer\Emulative);
|
$lexer = new PhpParser\Lexer\Emulative(array('usedAttributes' => array(
|
||||||
|
'startLine', 'endLine', 'startFilePos', 'endFilePos'
|
||||||
|
)));
|
||||||
|
$parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7, $lexer);
|
||||||
$dumper = new PhpParser\NodeDumper;
|
$dumper = new PhpParser\NodeDumper;
|
||||||
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
|
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
|
||||||
$serializer = new PhpParser\Serializer\XML;
|
$serializer = new PhpParser\Serializer\XML;
|
||||||
@ -44,7 +53,17 @@ foreach ($files as $file) {
|
|||||||
try {
|
try {
|
||||||
$stmts = $parser->parse($code);
|
$stmts = $parser->parse($code);
|
||||||
} catch (PhpParser\Error $e) {
|
} catch (PhpParser\Error $e) {
|
||||||
die("==> Parse Error: {$e->getMessage()}\n");
|
if ($attributes['with-column-info'] && $e->hasColumnInfo()) {
|
||||||
|
$startLine = $e->getStartLine();
|
||||||
|
$endLine = $e->getEndLine();
|
||||||
|
$startColumn = $e->getStartColumn($code);
|
||||||
|
$endColumn = $e->getEndColumn($code);
|
||||||
|
$message .= $e->getRawMessage() . " from $startLine:$startColumn to $endLine:$endColumn";
|
||||||
|
} else {
|
||||||
|
$message = $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
die($message . "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($operations as $operation) {
|
foreach ($operations as $operation) {
|
||||||
@ -70,27 +89,25 @@ foreach ($files as $file) {
|
|||||||
function showHelp($error) {
|
function showHelp($error) {
|
||||||
die($error . "\n\n" .
|
die($error . "\n\n" .
|
||||||
<<<OUTPUT
|
<<<OUTPUT
|
||||||
Usage:
|
Usage: php-parse [operations] file1.php [file2.php ...]
|
||||||
|
or: php-parse [operations] "<?php code"
|
||||||
php php-parse.php [operations] file1.php [file2.php ...]
|
Turn PHP source code into an abstract syntax tree.
|
||||||
|
|
||||||
The file arguments can also be replaced with a code string:
|
|
||||||
|
|
||||||
php php-parse.php [operations] "<?php code"
|
|
||||||
|
|
||||||
Operations is a list of the following options (--dump by default):
|
Operations is a list of the following options (--dump by default):
|
||||||
|
|
||||||
--dump -d Dump nodes using NodeDumper
|
-d, --dump Dump nodes using NodeDumper
|
||||||
--pretty-print -p Pretty print file using PrettyPrinter\Standard
|
-p, --pretty-print Pretty print file using PrettyPrinter\Standard
|
||||||
--serialize-xml Serialize nodes using Serializer\XML
|
--serialize-xml Serialize nodes using Serializer\XML
|
||||||
--var-dump var_dump() nodes (for exact structure)
|
--var-dump var_dump() nodes (for exact structure)
|
||||||
--resolve-names -N Resolve names using NodeVisitor\NameResolver
|
-N, --resolve-names Resolve names using NodeVisitor\NameResolver
|
||||||
|
-c, --with-column-info Show column-numbers for errors (if available)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
php-parse -d -p -N -d file.php
|
||||||
php php-parse.php -d -p -N -d file.php
|
|
||||||
|
|
||||||
Dumps nodes, pretty prints them, then resolves names and dumps them again.
|
Dumps nodes, pretty prints them, then resolves names and dumps them again.
|
||||||
|
|
||||||
|
|
||||||
OUTPUT
|
OUTPUT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -98,6 +115,9 @@ OUTPUT
|
|||||||
function parseArgs($args) {
|
function parseArgs($args) {
|
||||||
$operations = array();
|
$operations = array();
|
||||||
$files = array();
|
$files = array();
|
||||||
|
$attributes = array(
|
||||||
|
'with-column-info' => false,
|
||||||
|
);
|
||||||
|
|
||||||
array_shift($args);
|
array_shift($args);
|
||||||
$parseOptions = true;
|
$parseOptions = true;
|
||||||
@ -126,6 +146,10 @@ function parseArgs($args) {
|
|||||||
case '-N';
|
case '-N';
|
||||||
$operations[] = 'resolve-names';
|
$operations[] = 'resolve-names';
|
||||||
break;
|
break;
|
||||||
|
case '--with-column-info':
|
||||||
|
case '-c';
|
||||||
|
$attributes['with-column-info'] = true;
|
||||||
|
break;
|
||||||
case '--':
|
case '--':
|
||||||
$parseOptions = false;
|
$parseOptions = false;
|
||||||
break;
|
break;
|
||||||
@ -138,5 +162,5 @@ function parseArgs($args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return array($operations, $files);
|
return array($operations, $files, $attributes);
|
||||||
}
|
}
|
@ -10,15 +10,21 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3",
|
"php": ">=5.4",
|
||||||
"ext-tokenizer": "*"
|
"ext-tokenizer": "*"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"require-dev": {
|
||||||
"files": ["lib/bootstrap.php"]
|
"phpunit/phpunit": "~4.0"
|
||||||
},
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"PhpParser\\": "lib/PhpParser"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bin": ["bin/php-parse"],
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.0-dev"
|
"dev-master": "2.0-dev"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
Introduction
|
Introduction
|
||||||
============
|
============
|
||||||
|
|
||||||
This project is a PHP 5.2 to PHP 5.6 parser **written in PHP itself**.
|
This project is a PHP 5.2 to PHP 7.0 parser **written in PHP itself**.
|
||||||
|
|
||||||
What is this for?
|
What is this for?
|
||||||
-----------------
|
-----------------
|
||||||
@ -18,7 +18,7 @@ For example an AST abstracts away the fact that in PHP variables can be written
|
|||||||
as `$$bar`, `${'foobar'}` or even `${!${''}=barfoo()}`. You don't have to worry about recognizing
|
as `$$bar`, `${'foobar'}` or even `${!${''}=barfoo()}`. You don't have to worry about recognizing
|
||||||
all the different syntaxes from a stream of tokens.
|
all the different syntaxes from a stream of tokens.
|
||||||
|
|
||||||
Another questions is: Why would I want to have a PHP parser *written in PHP*? Well, PHP might not be
|
Another question is: Why would I want to have a PHP parser *written in PHP*? Well, PHP might not be
|
||||||
a language especially suited for fast parsing, but processing the AST is much easier in PHP than it
|
a language especially suited for fast parsing, but processing the AST is much easier in PHP than it
|
||||||
would be in other, faster languages like C. Furthermore the people most probably wanting to do
|
would be in other, faster languages like C. Furthermore the people most probably wanting to do
|
||||||
programmatic PHP code analysis are incidentally PHP developers, not C developers.
|
programmatic PHP code analysis are incidentally PHP developers, not C developers.
|
||||||
@ -26,13 +26,12 @@ programmatic PHP code analysis are incidentally PHP developers, not C developers
|
|||||||
What can it parse?
|
What can it parse?
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
The parser uses a PHP 5.6 compliant grammar, which is backwards compatible with all PHP version from PHP 5.2
|
The parser supports parsing PHP 5.2-5.6 and PHP 7.
|
||||||
upwards (and maybe older).
|
|
||||||
|
|
||||||
As the parser is based on the tokens returned by `token_get_all` (which is only able to lex the PHP
|
As the parser is based on the tokens returned by `token_get_all` (which is only able to lex the PHP
|
||||||
version it runs on), additionally a wrapper for emulating new tokens from 5.3, 5.4, 5.5 and 5.6 is provided.
|
version it runs on), additionally a wrapper for emulating new tokens from 5.5, 5.6 and 7.0 is
|
||||||
This allows to parse PHP 5.6 source code running on PHP 5.3, for example. This emulation is very hacky and not
|
provided. This allows to parse PHP 7.0 source code running on PHP 5.4, for example. This emulation
|
||||||
perfect, but it should work well on any sane code.
|
is somewhat hacky and not perfect, but it should work well on any sane code.
|
||||||
|
|
||||||
What output does it produce?
|
What output does it produce?
|
||||||
----------------------------
|
----------------------------
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
Installation
|
|
||||||
============
|
|
||||||
|
|
||||||
There are multiple ways to include the PHP parser into your project:
|
|
||||||
|
|
||||||
Installing via Composer
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
Create a `composer.json` file in your project root and use it to define your dependencies:
|
|
||||||
|
|
||||||
{
|
|
||||||
"require": {
|
|
||||||
"nikic/php-parser": "~1.0.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Then install Composer in your project (or [download the composer.phar][1] directly):
|
|
||||||
|
|
||||||
curl -s http://getcomposer.org/installer | php
|
|
||||||
|
|
||||||
And finally ask Composer to install the dependencies:
|
|
||||||
|
|
||||||
php composer.phar install
|
|
||||||
|
|
||||||
Installing as a Git Submodule
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
Run the following command to install the parser into the `vendor/PHP-Parser` folder:
|
|
||||||
|
|
||||||
git submodule add git://github.com/nikic/PHP-Parser.git vendor/PHP-Parser
|
|
||||||
|
|
||||||
Installing from the Zip- or Tarball
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
Download the latest version from [the download page][2], unpack it and move the files somewhere into your project.
|
|
||||||
|
|
||||||
|
|
||||||
[1]: http://getcomposer.org/composer.phar
|
|
||||||
[2]: https://github.com/nikic/PHP-Parser/tags
|
|
@ -6,21 +6,16 @@ This document explains how to use the parser, the pretty printer and the node tr
|
|||||||
Bootstrapping
|
Bootstrapping
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
The library needs to register a class autoloader. You can either use the ''vendor/autoload.php'' file generated by
|
To bootstrap the library, include the autoloader generated by composer:
|
||||||
Composer or by including the bundled `lib/bootstrap.php` file:
|
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
|
||||||
require 'path/to/PHP-Parser/lib/bootstrap.php';
|
|
||||||
// Or, if you're using Composer:
|
|
||||||
require 'path/to/vendor/autoload.php';
|
require 'path/to/vendor/autoload.php';
|
||||||
```
|
```
|
||||||
|
|
||||||
Additionally you may want to set the `xdebug.max_nesting_level` ini option to a higher value:
|
Additionally you may want to set the `xdebug.max_nesting_level` ini option to a higher value:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
ini_set('xdebug.max_nesting_level', 3000);
|
||||||
ini_set('xdebug.max_nesting_level', 2000);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This ensures that there will be no errors when traversing highly nested node trees.
|
This ensures that there will be no errors when traversing highly nested node trees.
|
||||||
@ -28,33 +23,41 @@ This ensures that there will be no errors when traversing highly nested node tre
|
|||||||
Parsing
|
Parsing
|
||||||
-------
|
-------
|
||||||
|
|
||||||
In order to parse some source code you first have to create a `PhpParser\Parser` object, which
|
In order to parse code, you first have to create a parser instance:
|
||||||
needs to be passed a `PhpParser\Lexer` instance:
|
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
use PhpParser\ParserFactory;
|
||||||
|
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
|
||||||
$parser = new PhpParser\Parser(new PhpParser\Lexer);
|
|
||||||
// or
|
|
||||||
$parser = new PhpParser\Parser(new PhpParser\Lexer\Emulative);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Use of the emulative lexer is required if you want to parse PHP code from newer versions than the one
|
The factory accepts a kind argument, that determines how different PHP versions are treated:
|
||||||
you're running on. For example it will allow you to parse PHP 5.6 code while running on PHP 5.3.
|
|
||||||
|
Kind | Behavior
|
||||||
|
-----|---------
|
||||||
|
`ParserFactory::PREFER_PHP7` | Try to parse code as PHP 7. If this fails, try to parse it as PHP 5.
|
||||||
|
`ParserFactory::PREFER_PHP5` | Try to parse code as PHP 5. If this fails, try to parse it as PHP 7.
|
||||||
|
`ParserFactory::ONLY_PHP7` | Parse code as PHP 7.
|
||||||
|
`ParserFactory::ONLY_PHP5` | Parse code as PHP 5.
|
||||||
|
|
||||||
|
Unless you have strong reason to use something else, `PREFER_PHP7` is a reasonable default.
|
||||||
|
|
||||||
|
The `create()` method optionally accepts a `Lexer` instance as the second argument. Some use cases
|
||||||
|
that require customized lexers are discussed in the [lexer documentation](component/Lexer.markdown).
|
||||||
|
|
||||||
Subsequently you can pass PHP code (including the opening `<?php` tag) to the `parse` method in order to
|
Subsequently you can pass PHP code (including the opening `<?php` tag) to the `parse` method in order to
|
||||||
create a syntax tree. If a syntax error is encountered, an `PhpParser\Error` exception will be thrown:
|
create a syntax tree. If a syntax error is encountered, an `PhpParser\Error` exception will be thrown:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
use PhpParser\Error;
|
||||||
$code = '<?php // some code';
|
use PhpParser\ParserFactory;
|
||||||
|
|
||||||
$parser = new PhpParser\Parser(new PhpParser\Lexer\Emulative);
|
$code = '<?php // some code';
|
||||||
|
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$stmts = $parser->parse($code);
|
$stmts = $parser->parse($code);
|
||||||
// $stmts is an array of statement nodes
|
// $stmts is an array of statement nodes
|
||||||
} catch (PhpParser\Error $e) {
|
} catch (Error $e) {
|
||||||
echo 'Parse Error: ', $e->getMessage();
|
echo 'Parse Error: ', $e->getMessage();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -102,7 +105,7 @@ with them easier they are grouped into three categories:
|
|||||||
and thus can occur in other expressions. Examples of expressions are `$var`
|
and thus can occur in other expressions. Examples of expressions are `$var`
|
||||||
(`PhpParser\Node\Expr\Variable`) and `func()` (`PhpParser\Node\Expr\FuncCall`).
|
(`PhpParser\Node\Expr\Variable`) and `func()` (`PhpParser\Node\Expr\FuncCall`).
|
||||||
* `PhpParser\Node\Scalar`s are nodes representing scalar values, like `'string'`
|
* `PhpParser\Node\Scalar`s are nodes representing scalar values, like `'string'`
|
||||||
(`PhpParser\Node\Scalar\String`), `0` (`PhpParser\Node\Scalar\LNumber`) or magic constants
|
(`PhpParser\Node\Scalar\String_`), `0` (`PhpParser\Node\Scalar\LNumber`) or magic constants
|
||||||
like `__FILE__` (`PhpParser\Node\Scalar\MagicConst\File`). All `PhpParser\Node\Scalar`s extend
|
like `__FILE__` (`PhpParser\Node\Scalar\MagicConst\File`). All `PhpParser\Node\Scalar`s extend
|
||||||
`PhpParser\Node\Expr`, as scalars are expressions, too.
|
`PhpParser\Node\Expr`, as scalars are expressions, too.
|
||||||
* There are some nodes not in either of these groups, for example names (`PhpParser\Node\Name`)
|
* There are some nodes not in either of these groups, for example names (`PhpParser\Node\Name`)
|
||||||
@ -137,11 +140,14 @@ information the formatting is done using a specified scheme. Currently there is
|
|||||||
namely `PhpParser\PrettyPrinter\Standard`.
|
namely `PhpParser\PrettyPrinter\Standard`.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
use PhpParser\Error;
|
||||||
|
use PhpParser\ParserFactory;
|
||||||
|
use PhpParser\PrettyPrinter;
|
||||||
|
|
||||||
$code = "<?php echo 'Hi ', hi\\getTarget();";
|
$code = "<?php echo 'Hi ', hi\\getTarget();";
|
||||||
|
|
||||||
$parser = new PhpParser\Parser(new PhpParser\Lexer);
|
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
|
||||||
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
|
$prettyPrinter = new PrettyPrinter\Standard;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// parse
|
// parse
|
||||||
@ -158,7 +164,7 @@ try {
|
|||||||
$code = $prettyPrinter->prettyPrint($stmts);
|
$code = $prettyPrinter->prettyPrint($stmts);
|
||||||
|
|
||||||
echo $code;
|
echo $code;
|
||||||
} catch (PhpParser\Error $e) {
|
} catch (Error $e) {
|
||||||
echo 'Parse Error: ', $e->getMessage();
|
echo 'Parse Error: ', $e->getMessage();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -188,11 +194,13 @@ For this purpose the parser provides a component for traversing and visiting the
|
|||||||
structure of a program using this `PhpParser\NodeTraverser` looks like this:
|
structure of a program using this `PhpParser\NodeTraverser` looks like this:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
use PhpParser\NodeTraverser;
|
||||||
|
use PhpParser\ParserFactory;
|
||||||
|
use PhpParser\PrettyPrinter;
|
||||||
|
|
||||||
$parser = new PhpParser\Parser(new PhpParser\Lexer\Emulative);
|
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
|
||||||
$traverser = new PhpParser\NodeTraverser;
|
$traverser = new NodeTraverser;
|
||||||
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
|
$prettyPrinter = new PrettyPrinter\Standard;
|
||||||
|
|
||||||
// add your visitor
|
// add your visitor
|
||||||
$traverser->addVisitor(new MyNodeVisitor);
|
$traverser->addVisitor(new MyNodeVisitor);
|
||||||
@ -218,13 +226,13 @@ try {
|
|||||||
The corresponding node visitor might look like this:
|
The corresponding node visitor might look like this:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
|
use PhpParser\NodeVisitorAbstract;
|
||||||
|
|
||||||
class MyNodeVisitor extends PhpParser\NodeVisitorAbstract
|
class MyNodeVisitor extends NodeVisitorAbstract
|
||||||
{
|
{
|
||||||
public function leaveNode(Node $node) {
|
public function leaveNode(Node $node) {
|
||||||
if ($node instanceof Node\Scalar\String) {
|
if ($node instanceof Node\Scalar\String_) {
|
||||||
$node->value = 'foo';
|
$node->value = 'foo';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,28 +244,34 @@ The above node visitor would change all string literals in the program to `'foo'
|
|||||||
All visitors must implement the `PhpParser\NodeVisitor` interface, which defines the following four
|
All visitors must implement the `PhpParser\NodeVisitor` interface, which defines the following four
|
||||||
methods:
|
methods:
|
||||||
|
|
||||||
|
```php
|
||||||
public function beforeTraverse(array $nodes);
|
public function beforeTraverse(array $nodes);
|
||||||
public function enterNode(PhpParser\Node $node);
|
public function enterNode(\PhpParser\Node $node);
|
||||||
public function leaveNode(PhpParser\Node $node);
|
public function leaveNode(\PhpParser\Node $node);
|
||||||
public function afterTraverse(array $nodes);
|
public function afterTraverse(array $nodes);
|
||||||
|
```
|
||||||
|
|
||||||
The `beforeTraverse` method is called once before the traversal begins and is passed the nodes the
|
The `beforeTraverse()` method is called once before the traversal begins and is passed the nodes the
|
||||||
traverser was called with. This method can be used for resetting values before traversation or
|
traverser was called with. This method can be used for resetting values before traversation or
|
||||||
preparing the tree for traversal.
|
preparing the tree for traversal.
|
||||||
|
|
||||||
The `afterTraverse` method is similar to the `beforeTraverse` method, with the only difference that
|
The `afterTraverse()` method is similar to the `beforeTraverse()` method, with the only difference that
|
||||||
it is called once after the traversal.
|
it is called once after the traversal.
|
||||||
|
|
||||||
The `enterNode` and `leaveNode` methods are called on every node, the former when it is entered,
|
The `enterNode()` and `leaveNode()` methods are called on every node, the former when it is entered,
|
||||||
i.e. before its subnodes are traversed, the latter when it is left.
|
i.e. before its subnodes are traversed, the latter when it is left.
|
||||||
|
|
||||||
All four methods can either return the changed node or not return at all (i.e. `null`) in which
|
All four methods can either return the changed node or not return at all (i.e. `null`) in which
|
||||||
case the current node is not changed. The `leaveNode` method can additionally return two special
|
case the current node is not changed.
|
||||||
values:
|
|
||||||
|
|
||||||
If `false` is returned the current node will be removed from the parent array. If an array is returned
|
The `enterNode()` method can additionally return the value `NodeTraverser::DONT_TRAVERSE_CHILDREN`,
|
||||||
it will be merged into the parent array at the offset of the current node. I.e. if in `array(A, B, C)`
|
which instructs the traverser to skip all children of the current node.
|
||||||
the node `B` should be replaced with `array(X, Y, Z)` the result will be `array(A, X, Y, Z, C)`.
|
|
||||||
|
The `leaveNode()` method can additionally return the value `NodeTraverser::REMOVE_NODE`, in which
|
||||||
|
case the current node will be removed from the parent array. Furthermore it is possible to return
|
||||||
|
an array of nodes, which will be merged into the parent array at the offset of the current node.
|
||||||
|
I.e. if in `array(A, B, C)` the node `B` should be replaced with `array(X, Y, Z)` the result will
|
||||||
|
be `array(A, X, Y, Z, C)`.
|
||||||
|
|
||||||
Instead of manually implementing the `NodeVisitor` interface you can also extend the `NodeVisitorAbstract`
|
Instead of manually implementing the `NodeVisitor` interface you can also extend the `NodeVisitorAbstract`
|
||||||
class, which will define empty default implementations for all the above methods.
|
class, which will define empty default implementations for all the above methods.
|
||||||
@ -295,20 +309,24 @@ assume that no dynamic features are used.
|
|||||||
We start off with the following base code:
|
We start off with the following base code:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
use PhpParser\ParserFactory;
|
||||||
|
use PhpParser\PrettyPrinter;
|
||||||
|
use PhpParser\NodeTraverser;
|
||||||
|
use PhpParser\NodeVisitor\NameResolver;
|
||||||
|
|
||||||
$inDir = '/some/path';
|
$inDir = '/some/path';
|
||||||
$outDir = '/some/other/path';
|
$outDir = '/some/other/path';
|
||||||
|
|
||||||
$parser = new PhpParser\Parser(new PhpParser\Lexer\Emulative);
|
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
|
||||||
$traverser = new PhpParser\NodeTraverser;
|
$traverser = new NodeTraverser;
|
||||||
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
|
$prettyPrinter = new PrettyPrinter\Standard;
|
||||||
|
|
||||||
$traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver); // we will need resolved names
|
$traverser->addVisitor(new NameResolver); // we will need resolved names
|
||||||
$traverser->addVisitor(new NodeVisitor\NamespaceConverter); // our own node visitor
|
$traverser->addVisitor(new NamespaceConverter); // our own node visitor
|
||||||
|
|
||||||
// iterate over all .php files in the directory
|
// iterate over all .php files in the directory
|
||||||
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($inDir));
|
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($inDir));
|
||||||
$files = new RegexIterator($files, '/\.php$/');
|
$files = new \RegexIterator($files, '/\.php$/');
|
||||||
|
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
try {
|
try {
|
||||||
@ -339,9 +357,9 @@ Now lets start with the main code, the `NodeVisitor\NamespaceConverter`. One thi
|
|||||||
is convert `A\\B` style names to `A_B` style ones.
|
is convert `A\\B` style names to `A_B` style ones.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
class NodeVisitor_NamespaceConverter extends PhpParser\NodeVisitorAbstract
|
|
||||||
|
class NamespaceConverter extends \PhpParser\NodeVisitorAbstract
|
||||||
{
|
{
|
||||||
public function leaveNode(Node $node) {
|
public function leaveNode(Node $node) {
|
||||||
if ($node instanceof Node\Name) {
|
if ($node instanceof Node\Name) {
|
||||||
@ -358,14 +376,14 @@ create a name with backslashes either write `$node->toString()` or `(string) $no
|
|||||||
a new name from the string and return it. Returning a new node replaces the old node.
|
a new name from the string and return it. Returning a new node replaces the old node.
|
||||||
|
|
||||||
Another thing we need to do is change the class/function/const declarations. Currently they contain
|
Another thing we need to do is change the class/function/const declarations. Currently they contain
|
||||||
only the shortname (i.e. the last part of the name), but they need to contain the complete name inclduing
|
only the shortname (i.e. the last part of the name), but they need to contain the complete name including
|
||||||
the namespace prefix:
|
the namespace prefix:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\Node\Stmt;
|
use PhpParser\Node\Stmt;
|
||||||
class NodeVisitor_NamespaceConverter extends PhpParser\NodeVisitorAbstract
|
|
||||||
|
class NodeVisitor_NamespaceConverter extends \PhpParser\NodeVisitorAbstract
|
||||||
{
|
{
|
||||||
public function leaveNode(Node $node) {
|
public function leaveNode(Node $node) {
|
||||||
if ($node instanceof Node\Name) {
|
if ($node instanceof Node\Name) {
|
||||||
@ -388,10 +406,10 @@ There is not much more to it than converting the namespaced name to string with
|
|||||||
The last thing we need to do is remove the `namespace` and `use` statements:
|
The last thing we need to do is remove the `namespace` and `use` statements:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\Node\Stmt;
|
use PhpParser\Node\Stmt;
|
||||||
class NodeVisitor_NamespaceConverter extends PhpParser\NodeVisitorAbstract
|
|
||||||
|
class NodeVisitor_NamespaceConverter extends \PhpParser\NodeVisitorAbstract
|
||||||
{
|
{
|
||||||
public function leaveNode(Node $node) {
|
public function leaveNode(Node $node) {
|
||||||
if ($node instanceof Node\Name) {
|
if ($node instanceof Node\Name) {
|
||||||
|
@ -17,7 +17,6 @@ Furthermore it is possible to dump nodes into a human readable format using the
|
|||||||
`PhpParser\NodeDumper`. This can be used for debugging.
|
`PhpParser\NodeDumper`. This can be used for debugging.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
|
||||||
$code = <<<'CODE'
|
$code = <<<'CODE'
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
@ -28,7 +27,7 @@ function printLine($msg) {
|
|||||||
printLine('Hello World!!!');
|
printLine('Hello World!!!');
|
||||||
CODE;
|
CODE;
|
||||||
|
|
||||||
$parser = new PhpParser\Parser(new PhpParser\Lexer);
|
$parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7);
|
||||||
$nodeDumper = new PhpParser\NodeDumper;
|
$nodeDumper = new PhpParser\NodeDumper;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -106,7 +105,7 @@ function printLine($msg) {
|
|||||||
printLine('Hello World!!!');
|
printLine('Hello World!!!');
|
||||||
CODE;
|
CODE;
|
||||||
|
|
||||||
$parser = new PhpParser\Parser(new PhpParser\Lexer);
|
$parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7);
|
||||||
$serializer = new PhpParser\Serializer\XML;
|
$serializer = new PhpParser\Serializer\XML;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -2,52 +2,79 @@ Code generation
|
|||||||
===============
|
===============
|
||||||
|
|
||||||
It is also possible to generate code using the parser, by first creating an Abstract Syntax Tree and then using the
|
It is also possible to generate code using the parser, by first creating an Abstract Syntax Tree and then using the
|
||||||
pretty printer to convert it to PHP code. To simplify code generation, the project comes with a set of builders for
|
pretty printer to convert it to PHP code. To simplify code generation, the project comes with builders which allow
|
||||||
classes, interfaces, methods, functions, parameters and properties. The builders allow creating node trees using a
|
creating node trees using a fluid interface, instead of instantiating all nodes manually. Builders are available for
|
||||||
fluid interface, instead of instantiating all nodes manually.
|
the following syntactic elements:
|
||||||
|
|
||||||
|
* namespaces and use statements
|
||||||
|
* classes, interfaces and traits
|
||||||
|
* methods, functions and parameters
|
||||||
|
* properties
|
||||||
|
|
||||||
Here is an example:
|
Here is an example:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
use PhpParser\BuilderFactory;
|
||||||
$factory = new PhpParser\BuilderFactory;
|
use PhpParser\PrettyPrinter;
|
||||||
$node = $factory->class('SomeClass')
|
use PhpParser\Node;
|
||||||
|
|
||||||
|
$factory = new BuilderFactory;
|
||||||
|
$node = $factory->namespace('Name\Space')
|
||||||
|
->addStmt($factory->use('Some\Other\Thingy')->as('SomeOtherClass'))
|
||||||
|
->addStmt($factory->class('SomeClass')
|
||||||
->extend('SomeOtherClass')
|
->extend('SomeOtherClass')
|
||||||
->implement('A\Few', 'Interfaces')
|
->implement('A\Few', '\Interfaces')
|
||||||
->makeAbstract() // ->makeFinal()
|
->makeAbstract() // ->makeFinal()
|
||||||
|
|
||||||
->addStmt($factory->method('someMethod')
|
->addStmt($factory->method('someMethod')
|
||||||
|
->makePublic()
|
||||||
->makeAbstract() // ->makeFinal()
|
->makeAbstract() // ->makeFinal()
|
||||||
->addParam($factory->param('someParam')->setTypeHint('SomeClass'))
|
->addParam($factory->param('someParam')->setTypeHint('SomeClass'))
|
||||||
|
->setDocComment('/**
|
||||||
|
* This method does something.
|
||||||
|
*
|
||||||
|
* @param SomeClass And takes a parameter
|
||||||
|
*/')
|
||||||
)
|
)
|
||||||
|
|
||||||
->addStmt($factory->method('anotherMethod')
|
->addStmt($factory->method('anotherMethod')
|
||||||
->makeProtected() // ->makePublic() [default], ->makePrivate()
|
->makeProtected() // ->makePublic() [default], ->makePrivate()
|
||||||
->addParam($factory->param('someParam')->setDefault('test'))
|
->addParam($factory->param('someParam')->setDefault('test'))
|
||||||
// it is possible to add manually created nodes
|
// it is possible to add manually created nodes
|
||||||
->addStmt(new PhpParser\Node\Expr\Print_(new PhpParser\Node\Expr\Variable('someParam')))
|
->addStmt(new Node\Expr\Print_(new Node\Expr\Variable('someParam')))
|
||||||
)
|
)
|
||||||
|
|
||||||
// properties will be correctly reordered above the methods
|
// properties will be correctly reordered above the methods
|
||||||
->addStmt($factory->property('someProperty')->makeProtected())
|
->addStmt($factory->property('someProperty')->makeProtected())
|
||||||
->addStmt($factory->property('anotherProperty')->makePrivate()->setDefault(array(1, 2, 3)))
|
->addStmt($factory->property('anotherProperty')->makePrivate()->setDefault(array(1, 2, 3)))
|
||||||
|
)
|
||||||
|
|
||||||
->getNode()
|
->getNode()
|
||||||
;
|
;
|
||||||
|
|
||||||
$stmts = array($node);
|
$stmts = array($node);
|
||||||
echo $prettyPrinter->prettyPrint($stmts);
|
$prettyPrinter = new PrettyPrinter\Standard();
|
||||||
|
echo $prettyPrinter->prettyPrintFile($stmts);
|
||||||
```
|
```
|
||||||
|
|
||||||
This will produce the following output with the default pretty printer:
|
This will produce the following output with the standard pretty printer:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
<?php
|
||||||
abstract class SomeClass extends SomeOtherClass implements A\Few, Interfaces
|
|
||||||
|
namespace Name\Space;
|
||||||
|
|
||||||
|
use Some\Other\Thingy as SomeClass;
|
||||||
|
abstract class SomeClass extends SomeOtherClass implements A\Few, \Interfaces
|
||||||
{
|
{
|
||||||
protected $someProperty;
|
protected $someProperty;
|
||||||
private $anotherProperty = array(1, 2, 3);
|
private $anotherProperty = array(1, 2, 3);
|
||||||
abstract function someMethod(SomeClass $someParam);
|
/**
|
||||||
|
* This method does something.
|
||||||
|
*
|
||||||
|
* @param SomeClass And takes a parameter
|
||||||
|
*/
|
||||||
|
public abstract function someMethod(SomeClass $someParam);
|
||||||
protected function anotherMethod($someParam = 'test')
|
protected function anotherMethod($someParam = 'test')
|
||||||
{
|
{
|
||||||
print $someParam;
|
print $someParam;
|
||||||
|
77
doc/component/Error.markdown
Normal file
77
doc/component/Error.markdown
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
Error handling
|
||||||
|
==============
|
||||||
|
|
||||||
|
Errors during parsing or analysis are represented using the `PhpParser\Error` exception class. In addition to an error
|
||||||
|
message, an error can also store additional information about the location the error occurred at.
|
||||||
|
|
||||||
|
How much location information is available depends on the origin of the error and how many lexer attributes have been
|
||||||
|
enabled. At a minimum the start line of the error is usually available.
|
||||||
|
|
||||||
|
Column information
|
||||||
|
------------------
|
||||||
|
|
||||||
|
In order to receive information about not only the line, but also the column span an error occurred at, the file
|
||||||
|
position attributes in the lexer need to be enabled:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$lexer = new PhpParser\Lexer(array(
|
||||||
|
'usedAttributes' => array('comments', 'startLine', 'endLine', 'startFilePos', 'endFilePos'),
|
||||||
|
));
|
||||||
|
$parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7, $lexer);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmts = $parser->parse($code);
|
||||||
|
// ...
|
||||||
|
} catch (PhpParser\Error $e) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Before using column information its availability needs to be checked with `$e->hasColumnInfo()`, as the precise
|
||||||
|
location of an error cannot always be determined. The methods for retrieving column information also have to be passed
|
||||||
|
the source code of the parsed file. An example for printing an error:
|
||||||
|
|
||||||
|
```php
|
||||||
|
if ($e->hasColumnInfo()) {
|
||||||
|
echo $e->getRawMessage() . ' from ' . $e->getStartLine() . ':' . $e->getStartColumn($code)
|
||||||
|
. ' to ' . $e->getEndLine() . ':' . $e->getEndColumn($code);
|
||||||
|
} else {
|
||||||
|
echo $e->getMessage();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Both line numbers and column numbers are 1-based. EOF errors will be located at the position one past the end of the
|
||||||
|
file.
|
||||||
|
|
||||||
|
Error recovery
|
||||||
|
--------------
|
||||||
|
|
||||||
|
> **EXPERIMENTAL**
|
||||||
|
|
||||||
|
By default the parser will throw an exception upon encountering the first error during parsing. An alternative mode is
|
||||||
|
also supported, in which the parser will remember the error, but try to continue parsing the rest of the source code.
|
||||||
|
|
||||||
|
To enable this mode the `throwOnError` parser option needs to be disabled. Any errors that occurred during parsing can
|
||||||
|
then be retrieved using `$parser->getErrors()`. The `$parser->parse()` method will either return a partial syntax tree
|
||||||
|
or `null` if recovery fails.
|
||||||
|
|
||||||
|
A usage example:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7, null, array(
|
||||||
|
'throwOnError' => false,
|
||||||
|
));
|
||||||
|
|
||||||
|
$stmts = $parser->parse($code);
|
||||||
|
$errors = $parser->getErrors();
|
||||||
|
|
||||||
|
foreach ($errors as $error) {
|
||||||
|
// $error is an ordinary PhpParser\Error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $stmts) {
|
||||||
|
// $stmts is a best-effort partial AST
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The error recovery implementation is experimental -- it currently won't be able to recover from many types of errors.
|
@ -5,83 +5,47 @@ The lexer is responsible for providing tokens to the parser. The project comes w
|
|||||||
`PhpParser\Lexer\Emulative`. The latter is an extension of the former, which adds the ability to emulate tokens of
|
`PhpParser\Lexer\Emulative`. The latter is an extension of the former, which adds the ability to emulate tokens of
|
||||||
newer PHP versions and thus allows parsing of new code on older versions.
|
newer PHP versions and thus allows parsing of new code on older versions.
|
||||||
|
|
||||||
A lexer has to define the following public interface:
|
This documentation discusses options available for the default lexers and explains how lexers can be extended.
|
||||||
|
|
||||||
void startLexing(string $code);
|
Lexer options
|
||||||
string handleHaltCompiler();
|
-------------
|
||||||
int getNextToken(string &$value = null, array &$startAttributes = null, array &$endAttributes = null);
|
|
||||||
|
|
||||||
The `startLexing()` method is invoked with the source code that is to be lexed (including the opening tag) whenever the
|
The two default lexers accept an `$options` array in the constructor. Currently only the `'usedAttributes'` option is
|
||||||
`parse()` method of the parser is called. It can be used to reset state or preprocess the source code or tokens.
|
supported, which allows you to specify which attributes will be added to the AST nodes. The attributes can then be
|
||||||
|
accessed using `$node->getAttribute()`, `$node->setAttribute()`, `$node->hasAttribute()` and `$node->getAttributes()`
|
||||||
The `handleHaltCompiler()` method is called whenever a `T_HALT_COMPILER` token is encountered. It has to return the
|
methods. A sample options array:
|
||||||
remaining string after the construct (not including `();`).
|
|
||||||
|
|
||||||
The `getNextToken()` method returns the ID of the next token (as defined by the `Parser::T_*` constants). If no more
|
|
||||||
tokens are available it must return `0`, which is the ID of the `EOF` token. Furthermore the string content of the
|
|
||||||
token should be written into the by-reference `$value` parameter (which will then be available as `$n` in the parser).
|
|
||||||
|
|
||||||
Attribute handling
|
|
||||||
------------------
|
|
||||||
|
|
||||||
The other two by-ref variables `$startAttributes` and `$endAttributes` define which attributes will eventually be
|
|
||||||
assigned to the generated nodes: The parser will take the `$startAttributes` from the first token which is part of the
|
|
||||||
node and the `$endAttributes` from the last token that is part of the node.
|
|
||||||
|
|
||||||
E.g. if the tokens `T_FUNCTION T_STRING ... '{' ... '}'` constitute a node, then the `$startAttributes` from the
|
|
||||||
`T_FUNCTION` token will be taken and the `$endAttributes` from the `'}'` token.
|
|
||||||
|
|
||||||
By default the lexer creates the attributes `startLine`, `comments` (both part of `$startAttributes`) and `endLine`
|
|
||||||
(part of `$endAttributes`).
|
|
||||||
|
|
||||||
If you don't want all these attributes to be added (to reduce memory usage of the AST) you can simply remove them by
|
|
||||||
overriding the method:
|
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
$lexer = new PhpParser\Lexer(array(
|
||||||
|
'usedAttributes' => array(
|
||||||
class LessAttributesLexer extends PhpParser\Lexer {
|
'comments', 'startLine', 'endLine'
|
||||||
public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) {
|
)
|
||||||
$tokenId = parent::getNextToken($value, $startAttributes, $endAttributes);
|
));
|
||||||
|
|
||||||
// only keep startLine attribute
|
|
||||||
unset($startAttributes['comments']);
|
|
||||||
unset($endAttributes['endLine']);
|
|
||||||
|
|
||||||
return $tokenId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Token offset lexer
|
The attributes used in this example match the default behavior of the lexer. The following attributes are supported:
|
||||||
------------------
|
|
||||||
|
|
||||||
A useful application for custom attributes is the token offset lexer, which provides the start and end token for a node
|
* `comments`: Array of `PhpParser\Comment` or `PhpParser\Comment\Doc` instances, representing all comments that occurred
|
||||||
as attributes:
|
between the previous non-discarded token and the current one. Use of this attribute is required for the
|
||||||
|
`$node->getDocComment()` method to work. The attribute is also needed if you wish the pretty printer to retain
|
||||||
|
comments present in the original code.
|
||||||
|
* `startLine`: Line in which the node starts. This attribute is required for the `$node->getLine()` to work. It is also
|
||||||
|
required if syntax errors should contain line number information.
|
||||||
|
* `endLine`: Line in which the node ends.
|
||||||
|
* `startTokenPos`: Offset into the token array of the first token in the node.
|
||||||
|
* `endTokenPos`: Offset into the token array of the last token in the node.
|
||||||
|
* `startFilePos`: Offset into the code string of the first character that is part of the node.
|
||||||
|
* `endFilePos`: Offset into the code string of the last character that is part of the node.
|
||||||
|
|
||||||
```php
|
### Using token positions
|
||||||
<?php
|
|
||||||
|
|
||||||
class TokenOffsetLexer extends PhpParser\Lexer {
|
The token offset information is useful if you wish to examine the exact formatting used for a node. For example the AST
|
||||||
public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) {
|
does not distinguish whether a property was declared using `public` or using `var`, but you can retrieve this
|
||||||
$tokenId = parent::getNextToken($value, $startAttributes, $endAttributes);
|
information based on the token position:
|
||||||
$startAttributes['startOffset'] = $endAttributes['endOffset'] = $this->pos;
|
|
||||||
return $tokenId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTokens() {
|
|
||||||
return $this->tokens;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This information can now be used to examine the exact formatting used for a node. For example the AST does not
|
|
||||||
distinguish whether a property was declared using `public` or using `var`, but you can retrieve this information based
|
|
||||||
on the token offset:
|
|
||||||
|
|
||||||
```php
|
```php
|
||||||
function isDeclaredUsingVar(array $tokens, PhpParser\Node\Stmt\Property $prop) {
|
function isDeclaredUsingVar(array $tokens, PhpParser\Node\Stmt\Property $prop) {
|
||||||
$i = $prop->getAttribute('startOffset');
|
$i = $prop->getAttribute('startTokenPos');
|
||||||
return $tokens[$i][0] === T_VAR;
|
return $tokens[$i][0] === T_VAR;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -103,8 +67,12 @@ class MyNodeVisitor extends PhpParser\NodeVisitorAbstract {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$lexer = new TokenOffsetLexer();
|
$lexer = new PhpParser\Lexer(array(
|
||||||
$parser = new PhpParser\Parser($lexer);
|
'usedAttributes' => array(
|
||||||
|
'comments', 'startLine', 'endLine', 'startTokenPos', 'endTokenPos'
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7, $lexer);
|
||||||
|
|
||||||
$visitor = new MyNodeVisitor();
|
$visitor = new MyNodeVisitor();
|
||||||
$traverser = new PhpParser\NodeTraverser();
|
$traverser = new PhpParser\NodeTraverser();
|
||||||
@ -121,3 +89,61 @@ try {
|
|||||||
|
|
||||||
The same approach can also be used to perform specific modifications in the code, without changing the formatting in
|
The same approach can also be used to perform specific modifications in the code, without changing the formatting in
|
||||||
other places (which is the case when using the pretty printer).
|
other places (which is the case when using the pretty printer).
|
||||||
|
|
||||||
|
Lexer extension
|
||||||
|
---------------
|
||||||
|
|
||||||
|
A lexer has to define the following public interface:
|
||||||
|
|
||||||
|
void startLexing(string $code);
|
||||||
|
array getTokens();
|
||||||
|
string handleHaltCompiler();
|
||||||
|
int getNextToken(string &$value = null, array &$startAttributes = null, array &$endAttributes = null);
|
||||||
|
|
||||||
|
The `startLexing()` method is invoked with the source code that is to be lexed (including the opening tag) whenever the
|
||||||
|
`parse()` method of the parser is called. It can be used to reset state or preprocess the source code or tokens.
|
||||||
|
|
||||||
|
The `getTokens()` method returns the current token array, in the usual `token_get_all()` format. This method is not
|
||||||
|
used by the parser (which uses `getNextToken()`), but is useful in combination with the token position attributes.
|
||||||
|
|
||||||
|
The `handleHaltCompiler()` method is called whenever a `T_HALT_COMPILER` token is encountered. It has to return the
|
||||||
|
remaining string after the construct (not including `();`).
|
||||||
|
|
||||||
|
The `getNextToken()` method returns the ID of the next token (as defined by the `Parser::T_*` constants). If no more
|
||||||
|
tokens are available it must return `0`, which is the ID of the `EOF` token. Furthermore the string content of the
|
||||||
|
token should be written into the by-reference `$value` parameter (which will then be available as `$n` in the parser).
|
||||||
|
|
||||||
|
### Attribute handling
|
||||||
|
|
||||||
|
The other two by-ref variables `$startAttributes` and `$endAttributes` define which attributes will eventually be
|
||||||
|
assigned to the generated nodes: The parser will take the `$startAttributes` from the first token which is part of the
|
||||||
|
node and the `$endAttributes` from the last token that is part of the node.
|
||||||
|
|
||||||
|
E.g. if the tokens `T_FUNCTION T_STRING ... '{' ... '}'` constitute a node, then the `$startAttributes` from the
|
||||||
|
`T_FUNCTION` token will be taken and the `$endAttributes` from the `'}'` token.
|
||||||
|
|
||||||
|
An application of custom attributes is storing the original formatting of literals: The parser does not retain
|
||||||
|
information about the formatting of integers (like decimal vs. hexadecimal) or strings (like used quote type or used
|
||||||
|
escape sequences). This can be remedied by storing the original value in an attribute:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use PhpParser\Lexer;
|
||||||
|
use PhpParser\Parser\Tokens;
|
||||||
|
|
||||||
|
class KeepOriginalValueLexer extends Lexer // or Lexer\Emulative
|
||||||
|
{
|
||||||
|
public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) {
|
||||||
|
$tokenId = parent::getNextToken($value, $startAttributes, $endAttributes);
|
||||||
|
|
||||||
|
if ($tokenId == Tokens::T_CONSTANT_ENCAPSED_STRING // non-interpolated string
|
||||||
|
|| $tokenId == Tokens::T_LNUMBER // integer
|
||||||
|
|| $tokenId == Tokens::T_DNUMBER // floating point number
|
||||||
|
) {
|
||||||
|
// could also use $startAttributes, doesn't really matter here
|
||||||
|
$endAttributes['originalValue'] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tokenId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
What do all those files mean?
|
What do all those files mean?
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
* `zend_language_parser.phpy`: PHP grammer written in a pseudo language
|
* `php5.y`: PHP 5 grammar written in a pseudo language
|
||||||
* `analyze.php`: Analyzes the `.phpy`-grammer and outputs some info about it
|
* `php7.y`: PHP 7 grammar written in a pseudo language
|
||||||
* `rebuildParser.php`: Preprocesses the `.phpy`-grammar and builds the parser using `kmyacc`
|
* `tokens.y`: Tokens definition shared between PHP 5 and PHP 7 grammars
|
||||||
* `kmyacc.php.parser`: A `kmyacc` parser prototype file for PHP
|
* `parser.template`: A `kmyacc` parser prototype file for PHP
|
||||||
|
* `tokens.template`: A `kmyacc` prototype file for the `Tokens` class
|
||||||
|
* `analyze.php`: Analyzes the grammer and outputs some info about it
|
||||||
|
* `rebuildParser.php`: Preprocesses the grammar and builds the parser using `kmyacc`
|
||||||
|
|
||||||
.phpy pseudo language
|
.phpy pseudo language
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
The `.phpy` file is a normal grammer in `kmyacc` (`yacc`) style, with some transformations
|
The `.y` file is a normal grammer in `kmyacc` (`yacc`) style, with some transformations
|
||||||
applied to it:
|
applied to it:
|
||||||
|
|
||||||
* Nodes are created using the syntax `Name[..., ...]`. This is transformed into
|
* Nodes are created using the syntax `Name[..., ...]`. This is transformed into
|
||||||
`new Node\Name(..., ..., $attributes)`
|
`new Name(..., ..., attributes())`
|
||||||
* `Name::abc` is transformed to `Node\Name::abc`
|
|
||||||
* Some function-like constructs are resolved (see `rebuildParser.php` for a list)
|
* Some function-like constructs are resolved (see `rebuildParser.php` for a list)
|
||||||
* Associative arrays are written as `[key: value, ...]`, which is transformed to
|
|
||||||
`array('key' => value, ...)`
|
|
||||||
|
|
||||||
Building the parser
|
Building the parser
|
||||||
===================
|
===================
|
||||||
@ -25,5 +25,5 @@ Building the parser
|
|||||||
In order to rebuild the parser, you need [moriyoshi's fork of kmyacc](https://github.com/moriyoshi/kmyacc-forked).
|
In order to rebuild the parser, you need [moriyoshi's fork of kmyacc](https://github.com/moriyoshi/kmyacc-forked).
|
||||||
After you compiled/installed it, run the `rebuildParser.php` script.
|
After you compiled/installed it, run the `rebuildParser.php` script.
|
||||||
|
|
||||||
By default only the `Parser.php` is built. If you want to additionally build `Parser/Debug.php` and `y.output` run the
|
By default only the `Parser.php` is built. If you want to additionally emit debug symbols and create `y.output`, run the
|
||||||
script with `--debug`. If you want to retain the preprocessed grammar pass `--keep-tmp-grammar`.
|
script with `--debug`. If you want to retain the preprocessed grammar pass `--keep-tmp-grammar`.
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
const GRAMMAR_FILE = './zend_language_parser.phpy';
|
const GRAMMAR_FILE = './php5.y';
|
||||||
|
|
||||||
const LIB = '(?(DEFINE)
|
const LIB = '(?(DEFINE)
|
||||||
(?<singleQuotedString>\'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\')
|
(?<singleQuotedString>\'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\')
|
||||||
|
@ -2,35 +2,39 @@
|
|||||||
$meta #
|
$meta #
|
||||||
#semval($) $this->semValue
|
#semval($) $this->semValue
|
||||||
#semval($,%t) $this->semValue
|
#semval($,%t) $this->semValue
|
||||||
#semval(%n) $this->semStack[$this->stackPos-(%l-%n)]
|
#semval(%n) $this->stackPos-(%l-%n)
|
||||||
#semval(%n,%t) $this->semStack[$this->stackPos-(%l-%n)]
|
#semval(%n,%t) $this->stackPos-(%l-%n)
|
||||||
#include;
|
|
||||||
|
|
||||||
namespace PhpParser;
|
namespace PhpParser\Parser;
|
||||||
|
|
||||||
|
use PhpParser\Error;
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\Node\Expr;
|
||||||
|
use PhpParser\Node\Name;
|
||||||
|
use PhpParser\Node\Scalar;
|
||||||
|
use PhpParser\Node\Stmt;
|
||||||
|
#include;
|
||||||
|
|
||||||
/* This is an automatically GENERATED file, which should not be manually edited.
|
/* This is an automatically GENERATED file, which should not be manually edited.
|
||||||
* Instead edit one of the following:
|
* Instead edit one of the following:
|
||||||
* * the grammar file grammar/zend_language_parser.phpy
|
* * the grammar files grammar/php5.y or grammar/php7.y
|
||||||
* * the skeleton file grammar/kymacc.php.parser
|
* * the skeleton file grammar/parser.template
|
||||||
* * the preprocessing script grammar/rebuildParser.php
|
* * the preprocessing script grammar/rebuildParsers.php
|
||||||
*/
|
*/
|
||||||
class Parser extends ParserAbstract
|
class #(-p) extends \PhpParser\ParserAbstract
|
||||||
{
|
{
|
||||||
protected $tokenToSymbolMapSize = #(YYMAXLEX);
|
protected $tokenToSymbolMapSize = #(YYMAXLEX);
|
||||||
protected $actionTableSize = #(YYLAST);
|
protected $actionTableSize = #(YYLAST);
|
||||||
protected $gotoTableSize = #(YYGLAST);
|
protected $gotoTableSize = #(YYGLAST);
|
||||||
|
|
||||||
protected $invalidToken = #(YYBADCH);
|
protected $invalidSymbol = #(YYBADCH);
|
||||||
|
protected $errorSymbol = #(YYINTERRTOK);
|
||||||
protected $defaultAction = #(YYDEFAULT);
|
protected $defaultAction = #(YYDEFAULT);
|
||||||
protected $unexpectedTokenRule = #(YYUNEXPECTED);
|
protected $unexpectedTokenRule = #(YYUNEXPECTED);
|
||||||
|
|
||||||
protected $YY2TBLSTATE = #(YY2TBLSTATE);
|
protected $YY2TBLSTATE = #(YY2TBLSTATE);
|
||||||
protected $YYNLSTATES = #(YYNLSTATES);
|
protected $YYNLSTATES = #(YYNLSTATES);
|
||||||
|
|
||||||
#tokenval
|
|
||||||
const %s = %n;
|
|
||||||
#endtokenval
|
|
||||||
|
|
||||||
protected $symbolToName = array(
|
protected $symbolToName = array(
|
||||||
#listvar terminals
|
#listvar terminals
|
||||||
);
|
);
|
||||||
@ -86,7 +90,7 @@ class Parser extends ParserAbstract
|
|||||||
#endif
|
#endif
|
||||||
#reduce
|
#reduce
|
||||||
|
|
||||||
protected function reduceRule%n($attributes) {
|
protected function reduceRule%n() {
|
||||||
%b
|
%b
|
||||||
}
|
}
|
||||||
#noact
|
#noact
|
@ -1,113 +1,7 @@
|
|||||||
%pure_parser
|
%pure_parser
|
||||||
%expect 2
|
%expect 6
|
||||||
|
|
||||||
%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
|
%tokens
|
||||||
%left ','
|
|
||||||
%left T_LOGICAL_OR
|
|
||||||
%left T_LOGICAL_XOR
|
|
||||||
%left T_LOGICAL_AND
|
|
||||||
%right T_PRINT
|
|
||||||
%right T_YIELD
|
|
||||||
%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL
|
|
||||||
%left '?' ':'
|
|
||||||
%left T_BOOLEAN_OR
|
|
||||||
%left T_BOOLEAN_AND
|
|
||||||
%left '|'
|
|
||||||
%left '^'
|
|
||||||
%left '&'
|
|
||||||
%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL
|
|
||||||
%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL
|
|
||||||
%left T_SL T_SR
|
|
||||||
%left '+' '-' '.'
|
|
||||||
%left '*' '/' '%'
|
|
||||||
%right '!'
|
|
||||||
%nonassoc T_INSTANCEOF
|
|
||||||
%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
|
|
||||||
%right T_POW
|
|
||||||
%right '['
|
|
||||||
%nonassoc T_NEW T_CLONE
|
|
||||||
%token T_EXIT
|
|
||||||
%token T_IF
|
|
||||||
%left T_ELSEIF
|
|
||||||
%left T_ELSE
|
|
||||||
%left T_ENDIF
|
|
||||||
%token T_LNUMBER
|
|
||||||
%token T_DNUMBER
|
|
||||||
%token T_STRING
|
|
||||||
%token T_STRING_VARNAME
|
|
||||||
%token T_VARIABLE
|
|
||||||
%token T_NUM_STRING
|
|
||||||
%token T_INLINE_HTML
|
|
||||||
%token T_CHARACTER
|
|
||||||
%token T_BAD_CHARACTER
|
|
||||||
%token T_ENCAPSED_AND_WHITESPACE
|
|
||||||
%token T_CONSTANT_ENCAPSED_STRING
|
|
||||||
%token T_ECHO
|
|
||||||
%token T_DO
|
|
||||||
%token T_WHILE
|
|
||||||
%token T_ENDWHILE
|
|
||||||
%token T_FOR
|
|
||||||
%token T_ENDFOR
|
|
||||||
%token T_FOREACH
|
|
||||||
%token T_ENDFOREACH
|
|
||||||
%token T_DECLARE
|
|
||||||
%token T_ENDDECLARE
|
|
||||||
%token T_AS
|
|
||||||
%token T_SWITCH
|
|
||||||
%token T_ENDSWITCH
|
|
||||||
%token T_CASE
|
|
||||||
%token T_DEFAULT
|
|
||||||
%token T_BREAK
|
|
||||||
%token T_CONTINUE
|
|
||||||
%token T_GOTO
|
|
||||||
%token T_FUNCTION
|
|
||||||
%token T_CONST
|
|
||||||
%token T_RETURN
|
|
||||||
%token T_TRY
|
|
||||||
%token T_CATCH
|
|
||||||
%token T_FINALLY
|
|
||||||
%token T_THROW
|
|
||||||
%token T_USE
|
|
||||||
%token T_INSTEADOF
|
|
||||||
%token T_GLOBAL
|
|
||||||
%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC
|
|
||||||
%token T_VAR
|
|
||||||
%token T_UNSET
|
|
||||||
%token T_ISSET
|
|
||||||
%token T_EMPTY
|
|
||||||
%token T_HALT_COMPILER
|
|
||||||
%token T_CLASS
|
|
||||||
%token T_TRAIT
|
|
||||||
%token T_INTERFACE
|
|
||||||
%token T_EXTENDS
|
|
||||||
%token T_IMPLEMENTS
|
|
||||||
%token T_OBJECT_OPERATOR
|
|
||||||
%token T_DOUBLE_ARROW
|
|
||||||
%token T_LIST
|
|
||||||
%token T_ARRAY
|
|
||||||
%token T_CALLABLE
|
|
||||||
%token T_CLASS_C
|
|
||||||
%token T_TRAIT_C
|
|
||||||
%token T_METHOD_C
|
|
||||||
%token T_FUNC_C
|
|
||||||
%token T_LINE
|
|
||||||
%token T_FILE
|
|
||||||
%token T_COMMENT
|
|
||||||
%token T_DOC_COMMENT
|
|
||||||
%token T_OPEN_TAG
|
|
||||||
%token T_OPEN_TAG_WITH_ECHO
|
|
||||||
%token T_CLOSE_TAG
|
|
||||||
%token T_WHITESPACE
|
|
||||||
%token T_START_HEREDOC
|
|
||||||
%token T_END_HEREDOC
|
|
||||||
%token T_DOLLAR_OPEN_CURLY_BRACES
|
|
||||||
%token T_CURLY_OPEN
|
|
||||||
%token T_PAAMAYIM_NEKUDOTAYIM
|
|
||||||
%token T_NAMESPACE
|
|
||||||
%token T_NS_C
|
|
||||||
%token T_DIR
|
|
||||||
%token T_NS_SEPARATOR
|
|
||||||
%token T_ELLIPSIS
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
@ -120,6 +14,26 @@ top_statement_list:
|
|||||||
| /* empty */ { init(); }
|
| /* empty */ { init(); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
reserved_non_modifiers:
|
||||||
|
T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND
|
||||||
|
| T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE
|
||||||
|
| T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH
|
||||||
|
| T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO
|
||||||
|
| T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT
|
||||||
|
| T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS
|
||||||
|
| T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER
|
||||||
|
;
|
||||||
|
|
||||||
|
semi_reserved:
|
||||||
|
reserved_non_modifiers
|
||||||
|
| T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC
|
||||||
|
;
|
||||||
|
|
||||||
|
identifier:
|
||||||
|
T_STRING { $$ = $1; }
|
||||||
|
| semi_reserved { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
namespace_name_parts:
|
namespace_name_parts:
|
||||||
T_STRING { init($1); }
|
T_STRING { init($1); }
|
||||||
| namespace_name_parts T_NS_SEPARATOR T_STRING { push($1, $3); }
|
| namespace_name_parts T_NS_SEPARATOR T_STRING { push($1, $3); }
|
||||||
@ -139,21 +53,57 @@ top_statement:
|
|||||||
| T_NAMESPACE namespace_name '{' top_statement_list '}' { $$ = Stmt\Namespace_[$2, $4]; }
|
| T_NAMESPACE namespace_name '{' top_statement_list '}' { $$ = Stmt\Namespace_[$2, $4]; }
|
||||||
| T_NAMESPACE '{' top_statement_list '}' { $$ = Stmt\Namespace_[null, $3]; }
|
| T_NAMESPACE '{' top_statement_list '}' { $$ = Stmt\Namespace_[null, $3]; }
|
||||||
| T_USE use_declarations ';' { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; }
|
| T_USE use_declarations ';' { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; }
|
||||||
| T_USE T_FUNCTION use_declarations ';' { $$ = Stmt\Use_[$3, Stmt\Use_::TYPE_FUNCTION]; }
|
| T_USE use_type use_declarations ';' { $$ = Stmt\Use_[$3, $2]; }
|
||||||
| T_USE T_CONST use_declarations ';' { $$ = Stmt\Use_[$3, Stmt\Use_::TYPE_CONSTANT]; }
|
| group_use_declaration ';' { $$ = $1; }
|
||||||
| T_CONST constant_declaration_list ';' { $$ = Stmt\Const_[$2]; }
|
| T_CONST constant_declaration_list ';' { $$ = Stmt\Const_[$2]; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
use_type:
|
||||||
|
T_FUNCTION { $$ = Stmt\Use_::TYPE_FUNCTION; }
|
||||||
|
| T_CONST { $$ = Stmt\Use_::TYPE_CONSTANT; }
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Using namespace_name_parts here to avoid s/r conflict on T_NS_SEPARATOR */
|
||||||
|
group_use_declaration:
|
||||||
|
T_USE use_type namespace_name_parts T_NS_SEPARATOR '{' unprefixed_use_declarations '}'
|
||||||
|
{ $$ = Stmt\GroupUse[Name[$3], $6, $2]; }
|
||||||
|
| T_USE use_type T_NS_SEPARATOR namespace_name_parts T_NS_SEPARATOR '{' unprefixed_use_declarations '}'
|
||||||
|
{ $$ = Stmt\GroupUse[Name[$4], $7, $2]; }
|
||||||
|
| T_USE namespace_name_parts T_NS_SEPARATOR '{' inline_use_declarations '}'
|
||||||
|
{ $$ = Stmt\GroupUse[Name[$2], $5, Stmt\Use_::TYPE_UNKNOWN]; }
|
||||||
|
| T_USE T_NS_SEPARATOR namespace_name_parts T_NS_SEPARATOR '{' inline_use_declarations '}'
|
||||||
|
{ $$ = Stmt\GroupUse[Name[$3], $6, Stmt\Use_::TYPE_UNKNOWN]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
unprefixed_use_declarations:
|
||||||
|
unprefixed_use_declarations ',' unprefixed_use_declaration
|
||||||
|
{ push($1, $3); }
|
||||||
|
| unprefixed_use_declaration { init($1); }
|
||||||
|
;
|
||||||
|
|
||||||
use_declarations:
|
use_declarations:
|
||||||
use_declarations ',' use_declaration { push($1, $3); }
|
use_declarations ',' use_declaration { push($1, $3); }
|
||||||
| use_declaration { init($1); }
|
| use_declaration { init($1); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
inline_use_declarations:
|
||||||
|
inline_use_declarations ',' inline_use_declaration { push($1, $3); }
|
||||||
|
| inline_use_declaration { init($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
unprefixed_use_declaration:
|
||||||
|
namespace_name { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; }
|
||||||
|
| namespace_name T_AS T_STRING { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; }
|
||||||
|
;
|
||||||
|
|
||||||
use_declaration:
|
use_declaration:
|
||||||
namespace_name { $$ = Stmt\UseUse[$1, null]; }
|
unprefixed_use_declaration { $$ = $1; }
|
||||||
| namespace_name T_AS T_STRING { $$ = Stmt\UseUse[$1, $3]; }
|
| T_NS_SEPARATOR unprefixed_use_declaration { $$ = $2; }
|
||||||
| T_NS_SEPARATOR namespace_name { $$ = Stmt\UseUse[$2, null]; }
|
;
|
||||||
| T_NS_SEPARATOR namespace_name T_AS T_STRING { $$ = Stmt\UseUse[$2, $4]; }
|
|
||||||
|
inline_use_declaration:
|
||||||
|
unprefixed_use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; }
|
||||||
|
| use_type unprefixed_use_declaration { $$ = $2; $$->type = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
constant_declaration_list:
|
constant_declaration_list:
|
||||||
@ -162,7 +112,16 @@ constant_declaration_list:
|
|||||||
;
|
;
|
||||||
|
|
||||||
constant_declaration:
|
constant_declaration:
|
||||||
T_STRING '=' static_scalar { $$ = Const_[$1, $3]; }
|
T_STRING '=' static_scalar { $$ = Node\Const_[$1, $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
class_const_list:
|
||||||
|
class_const_list ',' class_const { push($1, $3); }
|
||||||
|
| class_const { init($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
class_const:
|
||||||
|
identifier '=' static_scalar { $$ = Node\Const_[$1, $3]; }
|
||||||
;
|
;
|
||||||
|
|
||||||
inner_statement_list:
|
inner_statement_list:
|
||||||
@ -174,19 +133,20 @@ inner_statement:
|
|||||||
statement { $$ = $1; }
|
statement { $$ = $1; }
|
||||||
| function_declaration_statement { $$ = $1; }
|
| function_declaration_statement { $$ = $1; }
|
||||||
| class_declaration_statement { $$ = $1; }
|
| class_declaration_statement { $$ = $1; }
|
||||||
| T_HALT_COMPILER { error('__HALT_COMPILER() can only be used from the outermost scope'); }
|
| T_HALT_COMPILER
|
||||||
|
{ throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); }
|
||||||
;
|
;
|
||||||
|
|
||||||
statement:
|
non_empty_statement:
|
||||||
'{' inner_statement_list '}' { $$ = $2; }
|
'{' inner_statement_list '}' { $$ = $2; }
|
||||||
| T_IF parentheses_expr statement elseif_list else_single
|
| T_IF parentheses_expr statement elseif_list else_single
|
||||||
{ $$ = Stmt\If_[$2, [stmts: toArray($3), elseifs: $4, else: $5]]; }
|
{ $$ = 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 ';'
|
| T_IF parentheses_expr ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';'
|
||||||
{ $$ = Stmt\If_[$2, [stmts: $4, elseifs: $5, else: $6]]; }
|
{ $$ = Stmt\If_[$2, ['stmts' => $4, 'elseifs' => $5, 'else' => $6]]; }
|
||||||
| T_WHILE parentheses_expr while_statement { $$ = Stmt\While_[$2, $3]; }
|
| T_WHILE parentheses_expr while_statement { $$ = Stmt\While_[$2, $3]; }
|
||||||
| T_DO statement T_WHILE parentheses_expr ';' { $$ = Stmt\Do_ [$4, toArray($2)]; }
|
| T_DO statement T_WHILE parentheses_expr ';' { $$ = Stmt\Do_ [$4, toArray($2)]; }
|
||||||
| T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement
|
| T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement
|
||||||
{ $$ = Stmt\For_[[init: $3, cond: $5, loop: $7, stmts: $9]]; }
|
{ $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; }
|
||||||
| T_SWITCH parentheses_expr switch_case_list { $$ = Stmt\Switch_[$2, $3]; }
|
| T_SWITCH parentheses_expr switch_case_list { $$ = Stmt\Switch_[$2, $3]; }
|
||||||
| T_BREAK ';' { $$ = Stmt\Break_[null]; }
|
| T_BREAK ';' { $$ = Stmt\Break_[null]; }
|
||||||
| T_BREAK expr ';' { $$ = Stmt\Break_[$2]; }
|
| T_BREAK expr ';' { $$ = Stmt\Break_[$2]; }
|
||||||
@ -202,16 +162,21 @@ statement:
|
|||||||
| expr ';' { $$ = $1; }
|
| expr ';' { $$ = $1; }
|
||||||
| T_UNSET '(' variables_list ')' ';' { $$ = Stmt\Unset_[$3]; }
|
| T_UNSET '(' variables_list ')' ';' { $$ = Stmt\Unset_[$3]; }
|
||||||
| T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
|
| T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
|
||||||
{ $$ = Stmt\Foreach_[$3, $5[0], [keyVar: null, byRef: $5[1], stmts: $7]]; }
|
{ $$ = 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
|
| T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement
|
||||||
{ $$ = Stmt\Foreach_[$3, $7[0], [keyVar: $5, byRef: $7[1], stmts: $9]]; }
|
{ $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; }
|
||||||
| T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; }
|
| T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; }
|
||||||
| ';' { $$ = array(); /* means: no statement */ }
|
|
||||||
| T_TRY '{' inner_statement_list '}' catches optional_finally
|
| T_TRY '{' inner_statement_list '}' catches optional_finally
|
||||||
{ $$ = Stmt\TryCatch[$3, $5, $6]; }
|
{ $$ = Stmt\TryCatch[$3, $5, $6]; }
|
||||||
| T_THROW expr ';' { $$ = Stmt\Throw_[$2]; }
|
| T_THROW expr ';' { $$ = Stmt\Throw_[$2]; }
|
||||||
| T_GOTO T_STRING ';' { $$ = Stmt\Goto_[$2]; }
|
| T_GOTO T_STRING ';' { $$ = Stmt\Goto_[$2]; }
|
||||||
| T_STRING ':' { $$ = Stmt\Label[$1]; }
|
| T_STRING ':' { $$ = Stmt\Label[$1]; }
|
||||||
|
| error { $$ = array(); /* means: no statement */ }
|
||||||
|
;
|
||||||
|
|
||||||
|
statement:
|
||||||
|
non_empty_statement { $$ = $1; }
|
||||||
|
| ';' { $$ = array(); /* means: no statement */ }
|
||||||
;
|
;
|
||||||
|
|
||||||
catches:
|
catches:
|
||||||
@ -245,15 +210,15 @@ optional_ellipsis:
|
|||||||
;
|
;
|
||||||
|
|
||||||
function_declaration_statement:
|
function_declaration_statement:
|
||||||
T_FUNCTION optional_ref T_STRING '(' parameter_list ')' '{' inner_statement_list '}'
|
T_FUNCTION optional_ref T_STRING '(' parameter_list ')' optional_return_type '{' inner_statement_list '}'
|
||||||
{ $$ = Stmt\Function_[$3, [byRef: $2, params: $5, stmts: $8]]; }
|
{ $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $9]]; }
|
||||||
;
|
;
|
||||||
|
|
||||||
class_declaration_statement:
|
class_declaration_statement:
|
||||||
class_entry_type T_STRING extends_from implements_list '{' class_statement_list '}'
|
class_entry_type T_STRING extends_from implements_list '{' class_statement_list '}'
|
||||||
{ $$ = Stmt\Class_[$2, [type: $1, extends: $3, implements: $4, stmts: $6]]; }
|
{ $$ = Stmt\Class_[$2, ['type' => $1, 'extends' => $3, 'implements' => $4, 'stmts' => $6]]; }
|
||||||
| T_INTERFACE T_STRING interface_extends_list '{' class_statement_list '}'
|
| T_INTERFACE T_STRING interface_extends_list '{' class_statement_list '}'
|
||||||
{ $$ = Stmt\Interface_[$2, [extends: $3, stmts: $5]]; }
|
{ $$ = Stmt\Interface_[$2, ['extends' => $3, 'stmts' => $5]]; }
|
||||||
| T_TRAIT T_STRING '{' class_statement_list '}'
|
| T_TRAIT T_STRING '{' class_statement_list '}'
|
||||||
{ $$ = Stmt\Trait_[$2, $4]; }
|
{ $$ = Stmt\Trait_[$2, $4]; }
|
||||||
;
|
;
|
||||||
@ -295,7 +260,8 @@ foreach_statement:
|
|||||||
;
|
;
|
||||||
|
|
||||||
declare_statement:
|
declare_statement:
|
||||||
statement { $$ = toArray($1); }
|
non_empty_statement { $$ = toArray($1); }
|
||||||
|
| ';' { $$ = null; }
|
||||||
| ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; }
|
| ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -380,23 +346,32 @@ non_empty_parameter_list:
|
|||||||
;
|
;
|
||||||
|
|
||||||
parameter:
|
parameter:
|
||||||
optional_class_type optional_ref optional_ellipsis T_VARIABLE
|
optional_param_type optional_ref optional_ellipsis T_VARIABLE
|
||||||
{ $$ = Param[parseVar($4), null, $1, $2, $3]; }
|
{ $$ = Node\Param[parseVar($4), null, $1, $2, $3]; }
|
||||||
| optional_class_type optional_ref optional_ellipsis T_VARIABLE '=' static_scalar
|
| optional_param_type optional_ref optional_ellipsis T_VARIABLE '=' static_scalar
|
||||||
{ $$ = Param[parseVar($4), $6, $1, $2, $3]; }
|
{ $$ = Node\Param[parseVar($4), $6, $1, $2, $3]; }
|
||||||
;
|
;
|
||||||
|
|
||||||
optional_class_type:
|
type:
|
||||||
/* empty */ { $$ = null; }
|
name { $$ = $1; }
|
||||||
| name { $$ = $1; }
|
|
||||||
| T_ARRAY { $$ = 'array'; }
|
| T_ARRAY { $$ = 'array'; }
|
||||||
| T_CALLABLE { $$ = 'callable'; }
|
| T_CALLABLE { $$ = 'callable'; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
optional_param_type:
|
||||||
|
/* empty */ { $$ = null; }
|
||||||
|
| type { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
optional_return_type:
|
||||||
|
/* empty */ { $$ = null; }
|
||||||
|
| ':' type { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
argument_list:
|
argument_list:
|
||||||
'(' ')' { $$ = array(); }
|
'(' ')' { $$ = array(); }
|
||||||
| '(' non_empty_argument_list ')' { $$ = $2; }
|
| '(' non_empty_argument_list ')' { $$ = $2; }
|
||||||
| '(' yield_expr ')' { $$ = array(Arg[$2, false, false]); }
|
| '(' yield_expr ')' { $$ = array(Node\Arg[$2, false, false]); }
|
||||||
;
|
;
|
||||||
|
|
||||||
non_empty_argument_list:
|
non_empty_argument_list:
|
||||||
@ -405,9 +380,9 @@ non_empty_argument_list:
|
|||||||
;
|
;
|
||||||
|
|
||||||
argument:
|
argument:
|
||||||
expr { $$ = Arg[$1, false, false]; }
|
expr { $$ = Node\Arg[$1, false, false]; }
|
||||||
| '&' variable { $$ = Arg[$2, true, false]; }
|
| '&' variable { $$ = Node\Arg[$2, true, false]; }
|
||||||
| T_ELLIPSIS expr { $$ = Arg[$2, false, true]; }
|
| T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; }
|
||||||
;
|
;
|
||||||
|
|
||||||
global_var_list:
|
global_var_list:
|
||||||
@ -438,9 +413,9 @@ class_statement_list:
|
|||||||
|
|
||||||
class_statement:
|
class_statement:
|
||||||
variable_modifiers property_declaration_list ';' { $$ = Stmt\Property[$1, $2]; }
|
variable_modifiers property_declaration_list ';' { $$ = Stmt\Property[$1, $2]; }
|
||||||
| T_CONST constant_declaration_list ';' { $$ = Stmt\ClassConst[$2]; }
|
| T_CONST class_const_list ';' { $$ = Stmt\ClassConst[$2]; }
|
||||||
| method_modifiers T_FUNCTION optional_ref T_STRING '(' parameter_list ')' method_body
|
| method_modifiers T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type method_body
|
||||||
{ $$ = Stmt\ClassMethod[$4, [type: $1, byRef: $3, params: $6, stmts: $8]]; }
|
{ $$ = Stmt\ClassMethod[$4, ['type' => $1, 'byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9]]; }
|
||||||
| T_USE name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; }
|
| T_USE name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; }
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -457,20 +432,22 @@ trait_adaptation_list:
|
|||||||
trait_adaptation:
|
trait_adaptation:
|
||||||
trait_method_reference_fully_qualified T_INSTEADOF name_list ';'
|
trait_method_reference_fully_qualified T_INSTEADOF name_list ';'
|
||||||
{ $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; }
|
{ $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; }
|
||||||
| trait_method_reference T_AS member_modifier T_STRING ';'
|
| trait_method_reference T_AS member_modifier identifier ';'
|
||||||
{ $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; }
|
{ $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; }
|
||||||
| trait_method_reference T_AS member_modifier ';'
|
| trait_method_reference T_AS member_modifier ';'
|
||||||
{ $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; }
|
{ $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; }
|
||||||
| trait_method_reference T_AS T_STRING ';'
|
| trait_method_reference T_AS T_STRING ';'
|
||||||
{ $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; }
|
{ $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; }
|
||||||
|
| trait_method_reference T_AS reserved_non_modifiers ';'
|
||||||
|
{ $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; }
|
||||||
;
|
;
|
||||||
|
|
||||||
trait_method_reference_fully_qualified:
|
trait_method_reference_fully_qualified:
|
||||||
name T_PAAMAYIM_NEKUDOTAYIM T_STRING { $$ = array($1, $3); }
|
name T_PAAMAYIM_NEKUDOTAYIM identifier { $$ = array($1, $3); }
|
||||||
;
|
;
|
||||||
trait_method_reference:
|
trait_method_reference:
|
||||||
trait_method_reference_fully_qualified { $$ = $1; }
|
trait_method_reference_fully_qualified { $$ = $1; }
|
||||||
| T_STRING { $$ = array(null, $1); }
|
| identifier { $$ = array(null, $1); }
|
||||||
;
|
;
|
||||||
|
|
||||||
method_body:
|
method_body:
|
||||||
@ -480,11 +457,11 @@ method_body:
|
|||||||
|
|
||||||
variable_modifiers:
|
variable_modifiers:
|
||||||
non_empty_member_modifiers { $$ = $1; }
|
non_empty_member_modifiers { $$ = $1; }
|
||||||
| T_VAR { $$ = Stmt\Class_::MODIFIER_PUBLIC; }
|
| T_VAR { $$ = 0; }
|
||||||
;
|
;
|
||||||
|
|
||||||
method_modifiers:
|
method_modifiers:
|
||||||
/* empty */ { $$ = Stmt\Class_::MODIFIER_PUBLIC; }
|
/* empty */ { $$ = 0; }
|
||||||
| non_empty_member_modifiers { $$ = $1; }
|
| non_empty_member_modifiers { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -571,6 +548,7 @@ expr:
|
|||||||
| expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; }
|
| expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; }
|
||||||
| expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; }
|
| expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; }
|
||||||
| expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; }
|
| expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; }
|
||||||
|
| expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; }
|
||||||
| expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; }
|
| expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; }
|
||||||
| expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; }
|
| expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; }
|
||||||
| expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; }
|
| expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; }
|
||||||
@ -581,6 +559,7 @@ expr:
|
|||||||
| '(' new_expr ')' { $$ = $2; }
|
| '(' new_expr ')' { $$ = $2; }
|
||||||
| expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; }
|
| expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; }
|
||||||
| expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; }
|
| expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; }
|
||||||
|
| expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; }
|
||||||
| T_ISSET '(' variables_list ')' { $$ = Expr\Isset_[$3]; }
|
| T_ISSET '(' variables_list ')' { $$ = Expr\Isset_[$3]; }
|
||||||
| T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; }
|
| T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; }
|
||||||
| T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; }
|
| T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; }
|
||||||
@ -588,12 +567,12 @@ expr:
|
|||||||
| T_EVAL parentheses_expr { $$ = Expr\Eval_[$2]; }
|
| T_EVAL parentheses_expr { $$ = Expr\Eval_[$2]; }
|
||||||
| T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; }
|
| T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; }
|
||||||
| T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; }
|
| T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; }
|
||||||
| T_INT_CAST expr { $$ = Expr\Cast\Int [$2]; }
|
| T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; }
|
||||||
| T_DOUBLE_CAST expr { $$ = Expr\Cast\Double [$2]; }
|
| T_DOUBLE_CAST expr { $$ = Expr\Cast\Double [$2]; }
|
||||||
| T_STRING_CAST expr { $$ = Expr\Cast\String [$2]; }
|
| T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; }
|
||||||
| T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; }
|
| T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; }
|
||||||
| T_OBJECT_CAST expr { $$ = Expr\Cast\Object [$2]; }
|
| T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; }
|
||||||
| T_BOOL_CAST expr { $$ = Expr\Cast\Bool [$2]; }
|
| T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; }
|
||||||
| T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; }
|
| T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; }
|
||||||
| T_EXIT exit_expr { $$ = Expr\Exit_ [$2]; }
|
| T_EXIT exit_expr { $$ = Expr\Exit_ [$2]; }
|
||||||
| '@' expr { $$ = Expr\ErrorSuppress[$2]; }
|
| '@' expr { $$ = Expr\ErrorSuppress[$2]; }
|
||||||
@ -603,10 +582,13 @@ expr:
|
|||||||
| '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; }
|
| '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; }
|
||||||
| T_PRINT expr { $$ = Expr\Print_[$2]; }
|
| T_PRINT expr { $$ = Expr\Print_[$2]; }
|
||||||
| T_YIELD { $$ = Expr\Yield_[null, null]; }
|
| T_YIELD { $$ = Expr\Yield_[null, null]; }
|
||||||
| T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars '{' inner_statement_list '}'
|
| T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; }
|
||||||
{ $$ = Expr\Closure[[static: false, byRef: $2, params: $4, uses: $6, stmts: $8]]; }
|
| T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type
|
||||||
| T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars '{' inner_statement_list '}'
|
'{' inner_statement_list '}'
|
||||||
{ $$ = Expr\Closure[[static: true, byRef: $3, params: $5, uses: $7, stmts: $9]]; }
|
{ $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $9]]; }
|
||||||
|
| T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type
|
||||||
|
'{' inner_statement_list '}'
|
||||||
|
{ $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $10]]; }
|
||||||
;
|
;
|
||||||
|
|
||||||
parentheses_expr:
|
parentheses_expr:
|
||||||
@ -627,14 +609,20 @@ array_expr:
|
|||||||
scalar_dereference:
|
scalar_dereference:
|
||||||
array_expr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
array_expr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
||||||
| T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']'
|
| T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']'
|
||||||
{ $$ = Expr\ArrayDimFetch[Scalar\String[Scalar\String::parse($1)], $3]; }
|
{ $$ = Expr\ArrayDimFetch[Scalar\String_[Scalar\String_::parse($1, false)], $3]; }
|
||||||
| constant '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
| constant '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
||||||
| scalar_dereference '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
| scalar_dereference '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
||||||
/* alternative array syntax missing intentionally */
|
/* alternative array syntax missing intentionally */
|
||||||
;
|
;
|
||||||
|
|
||||||
|
anonymous_class:
|
||||||
|
T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}'
|
||||||
|
{ $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $3, 'implements' => $4, 'stmts' => $6]], $2); }
|
||||||
|
|
||||||
new_expr:
|
new_expr:
|
||||||
T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; }
|
T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; }
|
||||||
|
| T_NEW anonymous_class
|
||||||
|
{ list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; }
|
||||||
;
|
;
|
||||||
|
|
||||||
lexical_vars:
|
lexical_vars:
|
||||||
@ -653,7 +641,7 @@ lexical_var:
|
|||||||
|
|
||||||
function_call:
|
function_call:
|
||||||
name argument_list { $$ = Expr\FuncCall[$1, $2]; }
|
name argument_list { $$ = Expr\FuncCall[$1, $2]; }
|
||||||
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM T_STRING argument_list
|
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier argument_list
|
||||||
{ $$ = Expr\StaticCall[$1, $3, $4]; }
|
{ $$ = Expr\StaticCall[$1, $3, $4]; }
|
||||||
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' argument_list
|
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' argument_list
|
||||||
{ $$ = Expr\StaticCall[$1, $4, $6]; }
|
{ $$ = Expr\StaticCall[$1, $4, $6]; }
|
||||||
@ -721,8 +709,9 @@ exit_expr:
|
|||||||
|
|
||||||
backticks_expr:
|
backticks_expr:
|
||||||
/* empty */ { $$ = array(); }
|
/* empty */ { $$ = array(); }
|
||||||
| T_ENCAPSED_AND_WHITESPACE { $$ = array(Scalar\String::parseEscapeSequences($1, '`')); }
|
| T_ENCAPSED_AND_WHITESPACE
|
||||||
| encaps_list { parseEncapsed($1, '`'); $$ = $1; }
|
{ $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`', false)]); }
|
||||||
|
| encaps_list { parseEncapsed($1, '`', false); $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
ctor_arguments:
|
ctor_arguments:
|
||||||
@ -733,7 +722,7 @@ ctor_arguments:
|
|||||||
common_scalar:
|
common_scalar:
|
||||||
T_LNUMBER { $$ = Scalar\LNumber[Scalar\LNumber::parse($1)]; }
|
T_LNUMBER { $$ = Scalar\LNumber[Scalar\LNumber::parse($1)]; }
|
||||||
| T_DNUMBER { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; }
|
| T_DNUMBER { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; }
|
||||||
| T_CONSTANT_ENCAPSED_STRING { $$ = Scalar\String[Scalar\String::parse($1)]; }
|
| T_CONSTANT_ENCAPSED_STRING { $$ = Scalar\String_[Scalar\String_::parse($1, false)]; }
|
||||||
| T_LINE { $$ = Scalar\MagicConst\Line[]; }
|
| T_LINE { $$ = Scalar\MagicConst\Line[]; }
|
||||||
| T_FILE { $$ = Scalar\MagicConst\File[]; }
|
| T_FILE { $$ = Scalar\MagicConst\File[]; }
|
||||||
| T_DIR { $$ = Scalar\MagicConst\Dir[]; }
|
| T_DIR { $$ = Scalar\MagicConst\Dir[]; }
|
||||||
@ -743,14 +732,14 @@ common_scalar:
|
|||||||
| T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; }
|
| T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; }
|
||||||
| T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; }
|
| T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; }
|
||||||
| T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC
|
| T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC
|
||||||
{ $$ = Scalar\String[Scalar\String::parseDocString($1, $2)]; }
|
{ $$ = Scalar\String_[Scalar\String_::parseDocString($1, $2, false)]; }
|
||||||
| T_START_HEREDOC T_END_HEREDOC
|
| T_START_HEREDOC T_END_HEREDOC
|
||||||
{ $$ = Scalar\String['']; }
|
{ $$ = Scalar\String_['']; }
|
||||||
;
|
;
|
||||||
|
|
||||||
static_scalar:
|
static_scalar:
|
||||||
common_scalar { $$ = $1; }
|
common_scalar { $$ = $1; }
|
||||||
| class_name T_PAAMAYIM_NEKUDOTAYIM class_const_name { $$ = Expr\ClassConstFetch[$1, $3]; }
|
| class_name T_PAAMAYIM_NEKUDOTAYIM identifier { $$ = Expr\ClassConstFetch[$1, $3]; }
|
||||||
| name { $$ = Expr\ConstFetch[$1]; }
|
| name { $$ = Expr\ConstFetch[$1]; }
|
||||||
| T_ARRAY '(' static_array_pair_list ')' { $$ = Expr\Array_[$3]; }
|
| T_ARRAY '(' static_array_pair_list ')' { $$ = Expr\Array_[$3]; }
|
||||||
| '[' static_array_pair_list ']' { $$ = Expr\Array_[$2]; }
|
| '[' static_array_pair_list ']' { $$ = Expr\Array_[$2]; }
|
||||||
@ -795,7 +784,7 @@ static_operation:
|
|||||||
|
|
||||||
constant:
|
constant:
|
||||||
name { $$ = Expr\ConstFetch[$1]; }
|
name { $$ = Expr\ConstFetch[$1]; }
|
||||||
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM class_const_name
|
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier
|
||||||
{ $$ = Expr\ClassConstFetch[$1, $3]; }
|
{ $$ = Expr\ClassConstFetch[$1, $3]; }
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -803,14 +792,9 @@ scalar:
|
|||||||
common_scalar { $$ = $1; }
|
common_scalar { $$ = $1; }
|
||||||
| constant { $$ = $1; }
|
| constant { $$ = $1; }
|
||||||
| '"' encaps_list '"'
|
| '"' encaps_list '"'
|
||||||
{ parseEncapsed($2, '"'); $$ = Scalar\Encapsed[$2]; }
|
{ parseEncapsed($2, '"', false); $$ = Scalar\Encapsed[$2]; }
|
||||||
| T_START_HEREDOC encaps_list T_END_HEREDOC
|
| T_START_HEREDOC encaps_list T_END_HEREDOC
|
||||||
{ parseEncapsedDoc($2); $$ = Scalar\Encapsed[$2]; }
|
{ parseEncapsedDoc($2, false); $$ = Scalar\Encapsed[$2]; }
|
||||||
;
|
|
||||||
|
|
||||||
class_const_name:
|
|
||||||
T_STRING { $$ = $1; }
|
|
||||||
| T_CLASS { $$ = 'class'; }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
static_array_pair_list:
|
static_array_pair_list:
|
||||||
@ -938,9 +922,13 @@ array_pair:
|
|||||||
|
|
||||||
encaps_list:
|
encaps_list:
|
||||||
encaps_list encaps_var { push($1, $2); }
|
encaps_list encaps_var { push($1, $2); }
|
||||||
| encaps_list T_ENCAPSED_AND_WHITESPACE { push($1, $2); }
|
| encaps_list encaps_string_part { push($1, $2); }
|
||||||
| encaps_var { init($1); }
|
| encaps_var { init($1); }
|
||||||
| T_ENCAPSED_AND_WHITESPACE encaps_var { init($1, $2); }
|
| encaps_string_part encaps_var { init($1, $2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
encaps_string_part:
|
||||||
|
T_ENCAPSED_AND_WHITESPACE { $$ = Scalar\EncapsedStringPart[$1]; }
|
||||||
;
|
;
|
||||||
|
|
||||||
encaps_var:
|
encaps_var:
|
||||||
@ -955,8 +943,8 @@ encaps_var:
|
|||||||
;
|
;
|
||||||
|
|
||||||
encaps_var_offset:
|
encaps_var_offset:
|
||||||
T_STRING { $$ = Scalar\String[$1]; }
|
T_STRING { $$ = Scalar\String_[$1]; }
|
||||||
| T_NUM_STRING { $$ = Scalar\String[$1]; }
|
| T_NUM_STRING { $$ = Scalar\String_[$1]; }
|
||||||
| T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; }
|
| T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; }
|
||||||
;
|
;
|
||||||
|
|
819
grammar/php7.y
Normal file
819
grammar/php7.y
Normal file
@ -0,0 +1,819 @@
|
|||||||
|
%pure_parser
|
||||||
|
%expect 2
|
||||||
|
|
||||||
|
%tokens
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
start:
|
||||||
|
top_statement_list { $$ = $this->handleNamespaces($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
top_statement_list:
|
||||||
|
top_statement_list top_statement { pushNormalizing($1, $2); }
|
||||||
|
| /* empty */ { init(); }
|
||||||
|
;
|
||||||
|
|
||||||
|
reserved_non_modifiers:
|
||||||
|
T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND
|
||||||
|
| T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE
|
||||||
|
| T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH
|
||||||
|
| T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO
|
||||||
|
| T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT
|
||||||
|
| T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS
|
||||||
|
| T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER
|
||||||
|
;
|
||||||
|
|
||||||
|
semi_reserved:
|
||||||
|
reserved_non_modifiers
|
||||||
|
| T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC
|
||||||
|
;
|
||||||
|
|
||||||
|
identifier:
|
||||||
|
T_STRING { $$ = $1; }
|
||||||
|
| semi_reserved { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
namespace_name_parts:
|
||||||
|
T_STRING { init($1); }
|
||||||
|
| namespace_name_parts T_NS_SEPARATOR T_STRING { push($1, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
namespace_name:
|
||||||
|
namespace_name_parts { $$ = Name[$1]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
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]; }
|
||||||
|
| T_NAMESPACE namespace_name '{' top_statement_list '}' { $$ = Stmt\Namespace_[$2, $4]; }
|
||||||
|
| T_NAMESPACE '{' top_statement_list '}' { $$ = Stmt\Namespace_[null, $3]; }
|
||||||
|
| 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]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
use_type:
|
||||||
|
T_FUNCTION { $$ = Stmt\Use_::TYPE_FUNCTION; }
|
||||||
|
| T_CONST { $$ = Stmt\Use_::TYPE_CONSTANT; }
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Using namespace_name_parts here to avoid s/r conflict on T_NS_SEPARATOR */
|
||||||
|
group_use_declaration:
|
||||||
|
T_USE use_type namespace_name_parts T_NS_SEPARATOR '{' unprefixed_use_declarations '}'
|
||||||
|
{ $$ = Stmt\GroupUse[Name[$3], $6, $2]; }
|
||||||
|
| T_USE use_type T_NS_SEPARATOR namespace_name_parts T_NS_SEPARATOR '{' unprefixed_use_declarations '}'
|
||||||
|
{ $$ = Stmt\GroupUse[Name[$4], $7, $2]; }
|
||||||
|
| T_USE namespace_name_parts T_NS_SEPARATOR '{' inline_use_declarations '}'
|
||||||
|
{ $$ = Stmt\GroupUse[Name[$2], $5, Stmt\Use_::TYPE_UNKNOWN]; }
|
||||||
|
| T_USE T_NS_SEPARATOR namespace_name_parts T_NS_SEPARATOR '{' inline_use_declarations '}'
|
||||||
|
{ $$ = Stmt\GroupUse[Name[$3], $6, Stmt\Use_::TYPE_UNKNOWN]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
unprefixed_use_declarations:
|
||||||
|
unprefixed_use_declarations ',' unprefixed_use_declaration
|
||||||
|
{ push($1, $3); }
|
||||||
|
| unprefixed_use_declaration { init($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
use_declarations:
|
||||||
|
use_declarations ',' use_declaration { push($1, $3); }
|
||||||
|
| use_declaration { init($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
inline_use_declarations:
|
||||||
|
inline_use_declarations ',' inline_use_declaration { push($1, $3); }
|
||||||
|
| inline_use_declaration { init($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
unprefixed_use_declaration:
|
||||||
|
namespace_name { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; }
|
||||||
|
| namespace_name T_AS T_STRING { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
use_declaration:
|
||||||
|
unprefixed_use_declaration { $$ = $1; }
|
||||||
|
| T_NS_SEPARATOR unprefixed_use_declaration { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
inline_use_declaration:
|
||||||
|
unprefixed_use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; }
|
||||||
|
| use_type unprefixed_use_declaration { $$ = $2; $$->type = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
constant_declaration_list:
|
||||||
|
constant_declaration_list ',' constant_declaration { push($1, $3); }
|
||||||
|
| constant_declaration { init($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
constant_declaration:
|
||||||
|
T_STRING '=' expr { $$ = Node\Const_[$1, $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
class_const_list:
|
||||||
|
class_const_list ',' class_const { push($1, $3); }
|
||||||
|
| class_const { init($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
class_const:
|
||||||
|
identifier '=' expr { $$ = Node\Const_[$1, $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
inner_statement_list:
|
||||||
|
inner_statement_list inner_statement { pushNormalizing($1, $2); }
|
||||||
|
| /* empty */ { init(); }
|
||||||
|
;
|
||||||
|
|
||||||
|
inner_statement:
|
||||||
|
statement { $$ = $1; }
|
||||||
|
| function_declaration_statement { $$ = $1; }
|
||||||
|
| class_declaration_statement { $$ = $1; }
|
||||||
|
| T_HALT_COMPILER
|
||||||
|
{ throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); }
|
||||||
|
;
|
||||||
|
|
||||||
|
non_empty_statement:
|
||||||
|
'{' inner_statement_list '}' { $$ = $2; }
|
||||||
|
| 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 ';'
|
||||||
|
{ $$ = Stmt\If_[$3, ['stmts' => $6, 'elseifs' => $7, 'else' => $8]]; }
|
||||||
|
| T_WHILE '(' expr ')' while_statement { $$ = Stmt\While_[$3, $5]; }
|
||||||
|
| T_DO statement T_WHILE '(' expr ')' ';' { $$ = Stmt\Do_ [$5, toArray($2)]; }
|
||||||
|
| 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_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; }
|
||||||
|
| expr ';' { $$ = $1; }
|
||||||
|
| T_UNSET '(' variables_list ')' ';' { $$ = 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
|
||||||
|
{ $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; }
|
||||||
|
| T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; }
|
||||||
|
| T_TRY '{' inner_statement_list '}' catches optional_finally
|
||||||
|
{ $$ = Stmt\TryCatch[$3, $5, $6]; }
|
||||||
|
| T_THROW expr ';' { $$ = Stmt\Throw_[$2]; }
|
||||||
|
| T_GOTO T_STRING ';' { $$ = Stmt\Goto_[$2]; }
|
||||||
|
| T_STRING ':' { $$ = Stmt\Label[$1]; }
|
||||||
|
| error { $$ = array(); /* means: no statement */ }
|
||||||
|
;
|
||||||
|
|
||||||
|
statement:
|
||||||
|
non_empty_statement { $$ = $1; }
|
||||||
|
| ';' { $$ = array(); /* means: no statement */ }
|
||||||
|
;
|
||||||
|
|
||||||
|
catches:
|
||||||
|
/* empty */ { init(); }
|
||||||
|
| catches catch { push($1, $2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
catch:
|
||||||
|
T_CATCH '(' name T_VARIABLE ')' '{' inner_statement_list '}'
|
||||||
|
{ $$ = Stmt\Catch_[$3, parseVar($4), $7]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
optional_finally:
|
||||||
|
/* empty */ { $$ = null; }
|
||||||
|
| T_FINALLY '{' inner_statement_list '}' { $$ = $3; }
|
||||||
|
;
|
||||||
|
|
||||||
|
variables_list:
|
||||||
|
variable { init($1); }
|
||||||
|
| variables_list ',' variable { push($1, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
optional_ref:
|
||||||
|
/* empty */ { $$ = false; }
|
||||||
|
| '&' { $$ = true; }
|
||||||
|
;
|
||||||
|
|
||||||
|
optional_ellipsis:
|
||||||
|
/* empty */ { $$ = false; }
|
||||||
|
| T_ELLIPSIS { $$ = true; }
|
||||||
|
;
|
||||||
|
|
||||||
|
function_declaration_statement:
|
||||||
|
T_FUNCTION optional_ref T_STRING '(' parameter_list ')' optional_return_type '{' inner_statement_list '}'
|
||||||
|
{ $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $9]]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
class_declaration_statement:
|
||||||
|
class_entry_type T_STRING extends_from implements_list '{' class_statement_list '}'
|
||||||
|
{ $$ = Stmt\Class_[$2, ['type' => $1, 'extends' => $3, 'implements' => $4, 'stmts' => $6]]; }
|
||||||
|
| T_INTERFACE T_STRING interface_extends_list '{' class_statement_list '}'
|
||||||
|
{ $$ = Stmt\Interface_[$2, ['extends' => $3, 'stmts' => $5]]; }
|
||||||
|
| T_TRAIT T_STRING '{' class_statement_list '}'
|
||||||
|
{ $$ = Stmt\Trait_[$2, $4]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
class_entry_type:
|
||||||
|
T_CLASS { $$ = 0; }
|
||||||
|
| T_ABSTRACT T_CLASS { $$ = Stmt\Class_::MODIFIER_ABSTRACT; }
|
||||||
|
| T_FINAL T_CLASS { $$ = Stmt\Class_::MODIFIER_FINAL; }
|
||||||
|
;
|
||||||
|
|
||||||
|
extends_from:
|
||||||
|
/* empty */ { $$ = null; }
|
||||||
|
| T_EXTENDS name { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
interface_extends_list:
|
||||||
|
/* empty */ { $$ = array(); }
|
||||||
|
| T_EXTENDS name_list { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
implements_list:
|
||||||
|
/* empty */ { $$ = array(); }
|
||||||
|
| T_IMPLEMENTS name_list { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
name_list:
|
||||||
|
name { init($1); }
|
||||||
|
| name_list ',' name { push($1, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
for_statement:
|
||||||
|
statement { $$ = toArray($1); }
|
||||||
|
| ':' inner_statement_list T_ENDFOR ';' { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
foreach_statement:
|
||||||
|
statement { $$ = toArray($1); }
|
||||||
|
| ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
declare_statement:
|
||||||
|
non_empty_statement { $$ = toArray($1); }
|
||||||
|
| ';' { $$ = null; }
|
||||||
|
| ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
declare_list:
|
||||||
|
declare_list_element { init($1); }
|
||||||
|
| declare_list ',' declare_list_element { push($1, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
declare_list_element:
|
||||||
|
T_STRING '=' expr { $$ = Stmt\DeclareDeclare[$1, $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
switch_case_list:
|
||||||
|
'{' case_list '}' { $$ = $2; }
|
||||||
|
| '{' ';' case_list '}' { $$ = $3; }
|
||||||
|
| ':' case_list T_ENDSWITCH ';' { $$ = $2; }
|
||||||
|
| ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; }
|
||||||
|
;
|
||||||
|
|
||||||
|
case_list:
|
||||||
|
/* empty */ { init(); }
|
||||||
|
| case_list case { push($1, $2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
case:
|
||||||
|
T_CASE expr case_separator inner_statement_list { $$ = Stmt\Case_[$2, $4]; }
|
||||||
|
| T_DEFAULT case_separator inner_statement_list { $$ = Stmt\Case_[null, $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
case_separator:
|
||||||
|
':'
|
||||||
|
| ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
while_statement:
|
||||||
|
statement { $$ = toArray($1); }
|
||||||
|
| ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
elseif_list:
|
||||||
|
/* empty */ { init(); }
|
||||||
|
| elseif_list elseif { push($1, $2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
elseif:
|
||||||
|
T_ELSEIF '(' expr ')' statement { $$ = Stmt\ElseIf_[$3, toArray($5)]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
new_elseif_list:
|
||||||
|
/* empty */ { init(); }
|
||||||
|
| new_elseif_list new_elseif { push($1, $2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
new_elseif:
|
||||||
|
T_ELSEIF '(' expr ')' ':' inner_statement_list { $$ = Stmt\ElseIf_[$3, $6]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
else_single:
|
||||||
|
/* empty */ { $$ = null; }
|
||||||
|
| T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
new_else_single:
|
||||||
|
/* empty */ { $$ = null; }
|
||||||
|
| T_ELSE ':' inner_statement_list { $$ = Stmt\Else_[$3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
foreach_variable:
|
||||||
|
variable { $$ = array($1, false); }
|
||||||
|
| '&' variable { $$ = array($2, true); }
|
||||||
|
| list_expr { $$ = array($1, false); }
|
||||||
|
;
|
||||||
|
|
||||||
|
parameter_list:
|
||||||
|
non_empty_parameter_list { $$ = $1; }
|
||||||
|
| /* empty */ { $$ = array(); }
|
||||||
|
;
|
||||||
|
|
||||||
|
non_empty_parameter_list:
|
||||||
|
parameter { init($1); }
|
||||||
|
| non_empty_parameter_list ',' parameter { push($1, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
parameter:
|
||||||
|
optional_param_type optional_ref optional_ellipsis T_VARIABLE
|
||||||
|
{ $$ = Node\Param[parseVar($4), null, $1, $2, $3]; }
|
||||||
|
| optional_param_type optional_ref optional_ellipsis T_VARIABLE '=' expr
|
||||||
|
{ $$ = Node\Param[parseVar($4), $6, $1, $2, $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
type:
|
||||||
|
name { $$ = $this->handleScalarTypes($1); }
|
||||||
|
| T_ARRAY { $$ = 'array'; }
|
||||||
|
| T_CALLABLE { $$ = 'callable'; }
|
||||||
|
;
|
||||||
|
|
||||||
|
optional_param_type:
|
||||||
|
/* empty */ { $$ = null; }
|
||||||
|
| type { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
optional_return_type:
|
||||||
|
/* empty */ { $$ = null; }
|
||||||
|
| ':' type { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
argument_list:
|
||||||
|
'(' ')' { $$ = array(); }
|
||||||
|
| '(' non_empty_argument_list ')' { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
non_empty_argument_list:
|
||||||
|
argument { init($1); }
|
||||||
|
| non_empty_argument_list ',' argument { push($1, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
argument:
|
||||||
|
expr { $$ = Node\Arg[$1, false, false]; }
|
||||||
|
| '&' variable { $$ = Node\Arg[$2, true, false]; }
|
||||||
|
| T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
global_var_list:
|
||||||
|
global_var_list ',' global_var { push($1, $3); }
|
||||||
|
| global_var { init($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
global_var:
|
||||||
|
simple_variable { $$ = Expr\Variable[$1]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
static_var_list:
|
||||||
|
static_var_list ',' static_var { push($1, $3); }
|
||||||
|
| static_var { init($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
static_var:
|
||||||
|
T_VARIABLE { $$ = Stmt\StaticVar[parseVar($1), null]; }
|
||||||
|
| T_VARIABLE '=' expr { $$ = Stmt\StaticVar[parseVar($1), $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
class_statement_list:
|
||||||
|
class_statement_list class_statement { push($1, $2); }
|
||||||
|
| /* empty */ { init(); }
|
||||||
|
;
|
||||||
|
|
||||||
|
class_statement:
|
||||||
|
variable_modifiers property_declaration_list ';' { $$ = Stmt\Property[$1, $2]; }
|
||||||
|
| T_CONST class_const_list ';' { $$ = Stmt\ClassConst[$2]; }
|
||||||
|
| 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]]; }
|
||||||
|
| T_USE name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
trait_adaptations:
|
||||||
|
';' { $$ = array(); }
|
||||||
|
| '{' trait_adaptation_list '}' { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
trait_adaptation_list:
|
||||||
|
/* empty */ { init(); }
|
||||||
|
| trait_adaptation_list trait_adaptation { push($1, $2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
trait_adaptation:
|
||||||
|
trait_method_reference_fully_qualified T_INSTEADOF 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]; }
|
||||||
|
| trait_method_reference T_AS member_modifier ';'
|
||||||
|
{ $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; }
|
||||||
|
| trait_method_reference T_AS T_STRING ';'
|
||||||
|
{ $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; }
|
||||||
|
| trait_method_reference T_AS reserved_non_modifiers ';'
|
||||||
|
{ $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
trait_method_reference_fully_qualified:
|
||||||
|
name T_PAAMAYIM_NEKUDOTAYIM identifier { $$ = array($1, $3); }
|
||||||
|
;
|
||||||
|
trait_method_reference:
|
||||||
|
trait_method_reference_fully_qualified { $$ = $1; }
|
||||||
|
| identifier { $$ = array(null, $1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
method_body:
|
||||||
|
';' /* abstract method */ { $$ = null; }
|
||||||
|
| '{' inner_statement_list '}' { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
variable_modifiers:
|
||||||
|
non_empty_member_modifiers { $$ = $1; }
|
||||||
|
| T_VAR { $$ = 0; }
|
||||||
|
;
|
||||||
|
|
||||||
|
method_modifiers:
|
||||||
|
/* empty */ { $$ = 0; }
|
||||||
|
| non_empty_member_modifiers { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
non_empty_member_modifiers:
|
||||||
|
member_modifier { $$ = $1; }
|
||||||
|
| non_empty_member_modifiers member_modifier { Stmt\Class_::verifyModifier($1, $2); $$ = $1 | $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
member_modifier:
|
||||||
|
T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; }
|
||||||
|
| T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; }
|
||||||
|
| T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; }
|
||||||
|
| T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; }
|
||||||
|
| T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; }
|
||||||
|
| T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; }
|
||||||
|
;
|
||||||
|
|
||||||
|
property_declaration_list:
|
||||||
|
property_declaration { init($1); }
|
||||||
|
| property_declaration_list ',' property_declaration { push($1, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
property_declaration:
|
||||||
|
T_VARIABLE { $$ = Stmt\PropertyProperty[parseVar($1), null]; }
|
||||||
|
| T_VARIABLE '=' expr { $$ = Stmt\PropertyProperty[parseVar($1), $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
expr_list:
|
||||||
|
expr_list ',' expr { push($1, $3); }
|
||||||
|
| expr { init($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
for_expr:
|
||||||
|
/* empty */ { $$ = array(); }
|
||||||
|
| expr_list { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
expr:
|
||||||
|
variable { $$ = $1; }
|
||||||
|
| list_expr '=' expr { $$ = Expr\Assign[$1, $3]; }
|
||||||
|
| variable '=' expr { $$ = Expr\Assign[$1, $3]; }
|
||||||
|
| variable '=' '&' variable { $$ = Expr\AssignRef[$1, $4]; }
|
||||||
|
| variable '=' '&' new_expr { $$ = Expr\AssignRef[$1, $4]; }
|
||||||
|
| new_expr { $$ = $1; }
|
||||||
|
| T_CLONE expr { $$ = Expr\Clone_[$2]; }
|
||||||
|
| variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; }
|
||||||
|
| variable T_MINUS_EQUAL expr { $$ = Expr\AssignOp\Minus [$1, $3]; }
|
||||||
|
| variable T_MUL_EQUAL expr { $$ = Expr\AssignOp\Mul [$1, $3]; }
|
||||||
|
| variable T_DIV_EQUAL expr { $$ = Expr\AssignOp\Div [$1, $3]; }
|
||||||
|
| variable T_CONCAT_EQUAL expr { $$ = Expr\AssignOp\Concat [$1, $3]; }
|
||||||
|
| variable T_MOD_EQUAL expr { $$ = Expr\AssignOp\Mod [$1, $3]; }
|
||||||
|
| variable T_AND_EQUAL expr { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; }
|
||||||
|
| variable T_OR_EQUAL expr { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; }
|
||||||
|
| variable T_XOR_EQUAL expr { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; }
|
||||||
|
| variable T_SL_EQUAL expr { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; }
|
||||||
|
| variable T_SR_EQUAL expr { $$ = Expr\AssignOp\ShiftRight[$1, $3]; }
|
||||||
|
| variable T_POW_EQUAL expr { $$ = Expr\AssignOp\Pow [$1, $3]; }
|
||||||
|
| variable T_INC { $$ = Expr\PostInc[$1]; }
|
||||||
|
| T_INC variable { $$ = Expr\PreInc [$2]; }
|
||||||
|
| variable T_DEC { $$ = Expr\PostDec[$1]; }
|
||||||
|
| T_DEC variable { $$ = Expr\PreDec [$2]; }
|
||||||
|
| expr T_BOOLEAN_OR expr { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; }
|
||||||
|
| expr T_BOOLEAN_AND expr { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; }
|
||||||
|
| expr T_LOGICAL_OR expr { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; }
|
||||||
|
| expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; }
|
||||||
|
| expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; }
|
||||||
|
| expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; }
|
||||||
|
| expr '&' expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
|
||||||
|
| expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; }
|
||||||
|
| expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; }
|
||||||
|
| expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; }
|
||||||
|
| expr '-' expr { $$ = Expr\BinaryOp\Minus [$1, $3]; }
|
||||||
|
| expr '*' expr { $$ = Expr\BinaryOp\Mul [$1, $3]; }
|
||||||
|
| expr '/' expr { $$ = Expr\BinaryOp\Div [$1, $3]; }
|
||||||
|
| expr '%' expr { $$ = Expr\BinaryOp\Mod [$1, $3]; }
|
||||||
|
| expr T_SL expr { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; }
|
||||||
|
| expr T_SR expr { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; }
|
||||||
|
| expr T_POW expr { $$ = Expr\BinaryOp\Pow [$1, $3]; }
|
||||||
|
| '+' expr %prec T_INC { $$ = Expr\UnaryPlus [$2]; }
|
||||||
|
| '-' expr %prec T_INC { $$ = Expr\UnaryMinus[$2]; }
|
||||||
|
| '!' expr { $$ = Expr\BooleanNot[$2]; }
|
||||||
|
| '~' expr { $$ = Expr\BitwiseNot[$2]; }
|
||||||
|
| expr T_IS_IDENTICAL expr { $$ = Expr\BinaryOp\Identical [$1, $3]; }
|
||||||
|
| expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; }
|
||||||
|
| expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; }
|
||||||
|
| expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; }
|
||||||
|
| expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; }
|
||||||
|
| expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; }
|
||||||
|
| expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; }
|
||||||
|
| expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; }
|
||||||
|
| expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; }
|
||||||
|
| expr T_INSTANCEOF class_name_reference { $$ = Expr\Instanceof_[$1, $3]; }
|
||||||
|
| '(' expr ')' { $$ = $2; }
|
||||||
|
| expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; }
|
||||||
|
| expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; }
|
||||||
|
| expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; }
|
||||||
|
| T_ISSET '(' variables_list ')' { $$ = Expr\Isset_[$3]; }
|
||||||
|
| T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; }
|
||||||
|
| T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; }
|
||||||
|
| T_INCLUDE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; }
|
||||||
|
| T_EVAL '(' expr ')' { $$ = Expr\Eval_[$3]; }
|
||||||
|
| T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; }
|
||||||
|
| T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; }
|
||||||
|
| T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; }
|
||||||
|
| T_DOUBLE_CAST expr { $$ = Expr\Cast\Double [$2]; }
|
||||||
|
| T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; }
|
||||||
|
| T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; }
|
||||||
|
| T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; }
|
||||||
|
| T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; }
|
||||||
|
| T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; }
|
||||||
|
| T_EXIT exit_expr { $$ = Expr\Exit_ [$2]; }
|
||||||
|
| '@' expr { $$ = Expr\ErrorSuppress[$2]; }
|
||||||
|
| scalar { $$ = $1; }
|
||||||
|
| '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; }
|
||||||
|
| T_PRINT expr { $$ = Expr\Print_[$2]; }
|
||||||
|
| T_YIELD { $$ = Expr\Yield_[null, null]; }
|
||||||
|
| T_YIELD expr { $$ = Expr\Yield_[$2, null]; }
|
||||||
|
| T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; }
|
||||||
|
| T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; }
|
||||||
|
| T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type
|
||||||
|
'{' inner_statement_list '}'
|
||||||
|
{ $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $9]]; }
|
||||||
|
| T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type
|
||||||
|
'{' inner_statement_list '}'
|
||||||
|
{ $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $10]]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
anonymous_class:
|
||||||
|
T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}'
|
||||||
|
{ $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $3, 'implements' => $4, 'stmts' => $6]], $2); }
|
||||||
|
|
||||||
|
new_expr:
|
||||||
|
T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; }
|
||||||
|
| T_NEW anonymous_class
|
||||||
|
{ list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
lexical_vars:
|
||||||
|
/* empty */ { $$ = array(); }
|
||||||
|
| T_USE '(' lexical_var_list ')' { $$ = $3; }
|
||||||
|
;
|
||||||
|
|
||||||
|
lexical_var_list:
|
||||||
|
lexical_var { init($1); }
|
||||||
|
| lexical_var_list ',' lexical_var { push($1, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
lexical_var:
|
||||||
|
optional_ref T_VARIABLE { $$ = Expr\ClosureUse[parseVar($2), $1]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
function_call:
|
||||||
|
name argument_list { $$ = Expr\FuncCall[$1, $2]; }
|
||||||
|
| callable_expr argument_list { $$ = Expr\FuncCall[$1, $2]; }
|
||||||
|
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
|
||||||
|
{ $$ = Expr\StaticCall[$1, $3, $4]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
class_name:
|
||||||
|
T_STATIC { $$ = Name[$1]; }
|
||||||
|
| name { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
name:
|
||||||
|
namespace_name_parts { $$ = Name[$1]; }
|
||||||
|
| T_NS_SEPARATOR namespace_name_parts { $$ = Name\FullyQualified[$2]; }
|
||||||
|
| T_NAMESPACE T_NS_SEPARATOR namespace_name_parts { $$ = Name\Relative[$3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
class_name_reference:
|
||||||
|
class_name { $$ = $1; }
|
||||||
|
| new_variable { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
class_name_or_var:
|
||||||
|
class_name { $$ = $1; }
|
||||||
|
| dereferencable { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
exit_expr:
|
||||||
|
/* empty */ { $$ = null; }
|
||||||
|
| '(' optional_expr ')' { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
backticks_expr:
|
||||||
|
/* empty */ { $$ = array(); }
|
||||||
|
| T_ENCAPSED_AND_WHITESPACE
|
||||||
|
{ $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`')]); }
|
||||||
|
| encaps_list { parseEncapsed($1, '`', true); $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
ctor_arguments:
|
||||||
|
/* empty */ { $$ = array(); }
|
||||||
|
| argument_list { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
constant:
|
||||||
|
name { $$ = Expr\ConstFetch[$1]; }
|
||||||
|
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier
|
||||||
|
{ $$ = Expr\ClassConstFetch[$1, $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
dereferencable_scalar:
|
||||||
|
T_ARRAY '(' array_pair_list ')' { $$ = Expr\Array_[$3]; }
|
||||||
|
| '[' array_pair_list ']' { $$ = Expr\Array_[$2]; }
|
||||||
|
| T_CONSTANT_ENCAPSED_STRING { $$ = Scalar\String_[Scalar\String_::parse($1)]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
scalar:
|
||||||
|
T_LNUMBER { $$ = Scalar\LNumber[Scalar\LNumber::parse($1)]; }
|
||||||
|
| T_DNUMBER { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; }
|
||||||
|
| T_LINE { $$ = Scalar\MagicConst\Line[]; }
|
||||||
|
| T_FILE { $$ = Scalar\MagicConst\File[]; }
|
||||||
|
| T_DIR { $$ = Scalar\MagicConst\Dir[]; }
|
||||||
|
| T_CLASS_C { $$ = Scalar\MagicConst\Class_[]; }
|
||||||
|
| T_TRAIT_C { $$ = Scalar\MagicConst\Trait_[]; }
|
||||||
|
| T_METHOD_C { $$ = Scalar\MagicConst\Method[]; }
|
||||||
|
| T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; }
|
||||||
|
| T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; }
|
||||||
|
| dereferencable_scalar { $$ = $1; }
|
||||||
|
| constant { $$ = $1; }
|
||||||
|
| T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC
|
||||||
|
{ $$ = Scalar\String_[Scalar\String_::parseDocString($1, $2)]; }
|
||||||
|
| T_START_HEREDOC T_END_HEREDOC
|
||||||
|
{ $$ = Scalar\String_['']; }
|
||||||
|
| '"' encaps_list '"'
|
||||||
|
{ parseEncapsed($2, '"', true); $$ = Scalar\Encapsed[$2]; }
|
||||||
|
| T_START_HEREDOC encaps_list T_END_HEREDOC
|
||||||
|
{ parseEncapsedDoc($2, true); $$ = Scalar\Encapsed[$2]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
optional_comma:
|
||||||
|
/* empty */
|
||||||
|
| ','
|
||||||
|
;
|
||||||
|
|
||||||
|
optional_expr:
|
||||||
|
/* empty */ { $$ = null; }
|
||||||
|
| expr { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
dereferencable:
|
||||||
|
variable { $$ = $1; }
|
||||||
|
| '(' expr ')' { $$ = $2; }
|
||||||
|
| dereferencable_scalar { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
callable_expr:
|
||||||
|
callable_variable { $$ = $1; }
|
||||||
|
| '(' expr ')' { $$ = $2; }
|
||||||
|
| dereferencable_scalar { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
callable_variable:
|
||||||
|
simple_variable { $$ = Expr\Variable[$1]; }
|
||||||
|
| dereferencable '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
||||||
|
| constant '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
||||||
|
| dereferencable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
||||||
|
| function_call { $$ = $1; }
|
||||||
|
| dereferencable T_OBJECT_OPERATOR property_name argument_list
|
||||||
|
{ $$ = Expr\MethodCall[$1, $3, $4]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
variable:
|
||||||
|
callable_variable { $$ = $1; }
|
||||||
|
| static_member { $$ = $1; }
|
||||||
|
| dereferencable T_OBJECT_OPERATOR property_name { $$ = Expr\PropertyFetch[$1, $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
simple_variable:
|
||||||
|
T_VARIABLE { $$ = parseVar($1); }
|
||||||
|
| '$' '{' expr '}' { $$ = $3; }
|
||||||
|
| '$' simple_variable { $$ = Expr\Variable[$2]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
static_member:
|
||||||
|
class_name_or_var T_PAAMAYIM_NEKUDOTAYIM simple_variable
|
||||||
|
{ $$ = Expr\StaticPropertyFetch[$1, $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
new_variable:
|
||||||
|
simple_variable { $$ = Expr\Variable[$1]; }
|
||||||
|
| new_variable '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
||||||
|
| new_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
||||||
|
| new_variable T_OBJECT_OPERATOR property_name { $$ = Expr\PropertyFetch[$1, $3]; }
|
||||||
|
| class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable { $$ = Expr\StaticPropertyFetch[$1, $3]; }
|
||||||
|
| new_variable T_PAAMAYIM_NEKUDOTAYIM simple_variable { $$ = Expr\StaticPropertyFetch[$1, $3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
member_name:
|
||||||
|
identifier { $$ = $1; }
|
||||||
|
| '{' expr '}' { $$ = $2; }
|
||||||
|
| simple_variable { $$ = Expr\Variable[$1]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
property_name:
|
||||||
|
T_STRING { $$ = $1; }
|
||||||
|
| '{' expr '}' { $$ = $2; }
|
||||||
|
| simple_variable { $$ = Expr\Variable[$1]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
list_expr:
|
||||||
|
T_LIST '(' list_expr_elements ')' { $$ = Expr\List_[$3]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
list_expr_elements:
|
||||||
|
list_expr_elements ',' list_expr_element { push($1, $3); }
|
||||||
|
| list_expr_element { init($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
list_expr_element:
|
||||||
|
variable { $$ = $1; }
|
||||||
|
| list_expr { $$ = $1; }
|
||||||
|
| /* empty */ { $$ = null; }
|
||||||
|
;
|
||||||
|
|
||||||
|
array_pair_list:
|
||||||
|
/* empty */ { $$ = array(); }
|
||||||
|
| non_empty_array_pair_list optional_comma { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
non_empty_array_pair_list:
|
||||||
|
non_empty_array_pair_list ',' array_pair { push($1, $3); }
|
||||||
|
| array_pair { init($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
array_pair:
|
||||||
|
expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; }
|
||||||
|
| expr { $$ = Expr\ArrayItem[$1, null, false]; }
|
||||||
|
| expr T_DOUBLE_ARROW '&' variable { $$ = Expr\ArrayItem[$4, $1, true]; }
|
||||||
|
| '&' variable { $$ = Expr\ArrayItem[$2, null, true]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
encaps_list:
|
||||||
|
encaps_list encaps_var { push($1, $2); }
|
||||||
|
| encaps_list encaps_string_part { push($1, $2); }
|
||||||
|
| encaps_var { init($1); }
|
||||||
|
| encaps_string_part encaps_var { init($1, $2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
encaps_string_part:
|
||||||
|
T_ENCAPSED_AND_WHITESPACE { $$ = Scalar\EncapsedStringPart[$1]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
encaps_var:
|
||||||
|
T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; }
|
||||||
|
| T_VARIABLE '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[Expr\Variable[parseVar($1)], $3]; }
|
||||||
|
| T_VARIABLE T_OBJECT_OPERATOR T_STRING { $$ = Expr\PropertyFetch[Expr\Variable[parseVar($1)], $3]; }
|
||||||
|
| T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; }
|
||||||
|
| T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; }
|
||||||
|
| T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
|
||||||
|
{ $$ = Expr\ArrayDimFetch[Expr\Variable[$2], $4]; }
|
||||||
|
| T_CURLY_OPEN variable '}' { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
encaps_var_offset:
|
||||||
|
T_STRING { $$ = Scalar\String_[$1]; }
|
||||||
|
| T_NUM_STRING { $$ = Scalar\String_[$1]; }
|
||||||
|
| T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
@ -1,10 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
$grammarFile = __DIR__ . '/zend_language_parser.phpy';
|
$grammarFileToName = [
|
||||||
$skeletonFile = __DIR__ . '/kmyacc.php.parser';
|
__DIR__ . '/php5.y' => 'Php5',
|
||||||
|
__DIR__ . '/php7.y' => 'Php7',
|
||||||
|
];
|
||||||
|
|
||||||
|
$tokensFile = __DIR__ . '/tokens.y';
|
||||||
|
$tokensTemplate = __DIR__ . '/tokens.template';
|
||||||
|
$skeletonFile = __DIR__ . '/parser.template';
|
||||||
$tmpGrammarFile = __DIR__ . '/tmp_parser.phpy';
|
$tmpGrammarFile = __DIR__ . '/tmp_parser.phpy';
|
||||||
$tmpResultFile = __DIR__ . '/tmp_parser.php';
|
$tmpResultFile = __DIR__ . '/tmp_parser.php';
|
||||||
$parserResultFile = __DIR__ . '/../lib/PhpParser/Parser.php';
|
$resultDir = __DIR__ . '/../lib/PhpParser/Parser';
|
||||||
|
$tokensResultsFile = $resultDir . '/Tokens.php';
|
||||||
|
|
||||||
// check for kmyacc.exe binary in this directory, otherwise fall back to global name
|
// check for kmyacc.exe binary in this directory, otherwise fall back to global name
|
||||||
$kmyacc = __DIR__ . '/kmyacc.exe';
|
$kmyacc = __DIR__ . '/kmyacc.exe';
|
||||||
@ -35,37 +42,47 @@ const ARGS = '\((?<args>[^()]*+(?:\((?&args)\)[^()]*+)*+)\)';
|
|||||||
/// Main script ///
|
/// Main script ///
|
||||||
///////////////////
|
///////////////////
|
||||||
|
|
||||||
echo 'Building temporary preproprocessed grammar file.', "\n";
|
$tokens = file_get_contents($tokensFile);
|
||||||
|
|
||||||
|
foreach ($grammarFileToName as $grammarFile => $name) {
|
||||||
|
echo "Building temporary $name grammar file.\n";
|
||||||
|
|
||||||
$grammarCode = file_get_contents($grammarFile);
|
$grammarCode = file_get_contents($grammarFile);
|
||||||
|
$grammarCode = str_replace('%tokens', $tokens, $grammarCode);
|
||||||
|
|
||||||
$grammarCode = resolveConstants($grammarCode);
|
|
||||||
$grammarCode = resolveNodes($grammarCode);
|
$grammarCode = resolveNodes($grammarCode);
|
||||||
$grammarCode = resolveMacros($grammarCode);
|
$grammarCode = resolveMacros($grammarCode);
|
||||||
$grammarCode = resolveArrays($grammarCode);
|
$grammarCode = resolveStackAccess($grammarCode);
|
||||||
|
|
||||||
file_put_contents($tmpGrammarFile, $grammarCode);
|
file_put_contents($tmpGrammarFile, $grammarCode);
|
||||||
|
|
||||||
$additionalArgs = $optionDebug ? '-t -v' : '';
|
$additionalArgs = $optionDebug ? '-t -v' : '';
|
||||||
|
|
||||||
echo "Building parser.\n";
|
echo "Building $name parser.\n";
|
||||||
$output = trim(shell_exec("$kmyacc $additionalArgs -l -m $skeletonFile $tmpGrammarFile 2>&1"));
|
$output = trim(shell_exec("$kmyacc $additionalArgs -l -m $skeletonFile -p $name $tmpGrammarFile 2>&1"));
|
||||||
echo "Output: \"$output\"\n";
|
echo "Output: \"$output\"\n";
|
||||||
|
|
||||||
moveFileWithDirCheck($tmpResultFile, $parserResultFile);
|
$resultCode = file_get_contents($tmpResultFile);
|
||||||
|
$resultCode = removeTrailingWhitespace($resultCode);
|
||||||
|
|
||||||
|
ensureDirExists($resultDir);
|
||||||
|
file_put_contents("$resultDir/$name.php", $resultCode);
|
||||||
|
unlink($tmpResultFile);
|
||||||
|
|
||||||
|
echo "Building token definition.\n";
|
||||||
|
$output = trim(shell_exec("$kmyacc -l -m $tokensTemplate $tmpGrammarFile 2>&1"));
|
||||||
|
assert($output === '');
|
||||||
|
rename($tmpResultFile, $tokensResultsFile);
|
||||||
|
|
||||||
if (!$optionKeepTmpGrammar) {
|
if (!$optionKeepTmpGrammar) {
|
||||||
unlink($tmpGrammarFile);
|
unlink($tmpGrammarFile);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
/// Preprocessing functions ///
|
/// Preprocessing functions ///
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
function resolveConstants($code) {
|
|
||||||
return preg_replace('~[A-Z][a-zA-Z_\\\\]++::~', 'Node\\\\$0', $code);
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveNodes($code) {
|
function resolveNodes($code) {
|
||||||
return preg_replace_callback(
|
return preg_replace_callback(
|
||||||
'~(?<name>[A-Z][a-zA-Z_\\\\]++)\s*' . PARAMS . '~',
|
'~(?<name>[A-Z][a-zA-Z_\\\\]++)\s*' . PARAMS . '~',
|
||||||
@ -83,7 +100,7 @@ function resolveNodes($code) {
|
|||||||
$paramCode .= $param . ', ';
|
$paramCode .= $param . ', ';
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'new Node\\' . $matches['name'] . '(' . $paramCode . '$attributes)';
|
return 'new ' . $matches['name'] . '(' . $paramCode . 'attributes())';
|
||||||
},
|
},
|
||||||
$code
|
$code
|
||||||
);
|
);
|
||||||
@ -102,10 +119,9 @@ function resolveMacros($code) {
|
|||||||
$matches['args']
|
$matches['args']
|
||||||
);
|
);
|
||||||
|
|
||||||
if ('error' == $name) {
|
if ('attributes' == $name) {
|
||||||
assertArgs(1, $args, $name);
|
assertArgs(0, $args, $name);
|
||||||
|
return '$this->startAttributeStack[#1] + $this->endAttributes';
|
||||||
return 'throw new Error(' . $args[0] . ')';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('init' == $name) {
|
if ('init' == $name) {
|
||||||
@ -121,7 +137,8 @@ function resolveMacros($code) {
|
|||||||
if ('pushNormalizing' == $name) {
|
if ('pushNormalizing' == $name) {
|
||||||
assertArgs(2, $args, $name);
|
assertArgs(2, $args, $name);
|
||||||
|
|
||||||
return 'if (is_array(' . $args[1] . ')) { $$ = array_merge(' . $args[0] . ', ' . $args[1] . '); } else { ' . $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0] . '; }';
|
return 'if (is_array(' . $args[1] . ')) { $$ = array_merge(' . $args[0] . ', ' . $args[1] . '); }'
|
||||||
|
. ' else { ' . $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0] . '; }';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('toArray' == $name) {
|
if ('toArray' == $name) {
|
||||||
@ -137,18 +154,22 @@ function resolveMacros($code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ('parseEncapsed' == $name) {
|
if ('parseEncapsed' == $name) {
|
||||||
assertArgs(2, $args, $name);
|
assertArgs(3, $args, $name);
|
||||||
|
|
||||||
return 'foreach (' . $args[0] . ' as &$s) { if (is_string($s)) { $s = Node\Scalar\String::parseEscapeSequences($s, ' . $args[1] . '); } }';
|
return 'foreach (' . $args[0] . ' as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) {'
|
||||||
|
. ' $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, ' . $args[1] . ', ' . $args[2] . '); } }';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('parseEncapsedDoc' == $name) {
|
if ('parseEncapsedDoc' == $name) {
|
||||||
assertArgs(1, $args, $name);
|
assertArgs(2, $args, $name);
|
||||||
|
|
||||||
return 'foreach (' . $args[0] . ' as &$s) { if (is_string($s)) { $s = Node\Scalar\String::parseEscapeSequences($s, null); } } $s = preg_replace(\'~(\r\n|\n|\r)$~\', \'\', $s); if (\'\' === $s) array_pop(' . $args[0] . ');';
|
return 'foreach (' . $args[0] . ' as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) {'
|
||||||
|
. ' $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, null, ' . $args[1] . '); } }'
|
||||||
|
. ' $s->value = preg_replace(\'~(\r\n|\n|\r)\z~\', \'\', $s->value);'
|
||||||
|
. ' if (\'\' === $s->value) array_pop(' . $args[0] . ');';
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception(sprintf('Unknown macro "%s"', $name));
|
return $matches[0];
|
||||||
},
|
},
|
||||||
$code
|
$code
|
||||||
);
|
);
|
||||||
@ -160,43 +181,22 @@ function assertArgs($num, $args, $name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveArrays($code) {
|
function resolveStackAccess($code) {
|
||||||
return preg_replace_callback(
|
$code = preg_replace('/\$\d+/', '$this->semStack[$0]', $code);
|
||||||
'~' . PARAMS . '~',
|
$code = preg_replace('/#(\d+)/', '$$1', $code);
|
||||||
function ($matches) {
|
return $code;
|
||||||
$elements = magicSplit(
|
|
||||||
'(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,',
|
|
||||||
$matches['params']
|
|
||||||
);
|
|
||||||
|
|
||||||
// don't convert [] to array, it might have different meaning
|
|
||||||
if (empty($elements)) {
|
|
||||||
return $matches[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$elementCodes = array();
|
function removeTrailingWhitespace($code) {
|
||||||
foreach ($elements as $element) {
|
$lines = explode("\n", $code);
|
||||||
// convert only arrays where all elements have keys
|
$lines = array_map('rtrim', $lines);
|
||||||
if (false === strpos($element, ':')) {
|
return implode("\n", $lines);
|
||||||
return $matches[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
list($key, $value) = explode(':', $element, 2);
|
function ensureDirExists($dir) {
|
||||||
$elementCodes[] = "'" . $key . "' =>" . $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'array(' . implode(', ', $elementCodes) . ')';
|
|
||||||
},
|
|
||||||
$code
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function moveFileWithDirCheck($fromPath, $toPath) {
|
|
||||||
$dir = dirname($toPath);
|
|
||||||
if (!is_dir($dir)) {
|
if (!is_dir($dir)) {
|
||||||
mkdir($dir, 0777, true);
|
mkdir($dir, 0777, true);
|
||||||
}
|
}
|
||||||
rename($fromPath, $toPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
@ -214,5 +214,9 @@ function magicSplit($regex, $string) {
|
|||||||
$piece = trim($piece);
|
$piece = trim($piece);
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_filter($pieces);
|
if ($pieces === ['']) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pieces;
|
||||||
}
|
}
|
17
grammar/tokens.template
Normal file
17
grammar/tokens.template
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
$meta #
|
||||||
|
#semval($) $this->semValue
|
||||||
|
#semval($,%t) $this->semValue
|
||||||
|
#semval(%n) $this->stackPos-(%l-%n)
|
||||||
|
#semval(%n,%t) $this->stackPos-(%l-%n)
|
||||||
|
|
||||||
|
namespace PhpParser\Parser;
|
||||||
|
#include;
|
||||||
|
|
||||||
|
/* GENERATED file based on grammar/tokens.y */
|
||||||
|
final class Tokens
|
||||||
|
{
|
||||||
|
#tokenval
|
||||||
|
const %s = %n;
|
||||||
|
#endtokenval
|
||||||
|
}
|
113
grammar/tokens.y
Normal file
113
grammar/tokens.y
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/* We currently rely on the token ID mapping to be the same between PHP 5 and PHP 7 - so the same lexer can be used for
|
||||||
|
* both. This is enforced by sharing this token file. */
|
||||||
|
|
||||||
|
%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
|
||||||
|
%left ','
|
||||||
|
%left T_LOGICAL_OR
|
||||||
|
%left T_LOGICAL_XOR
|
||||||
|
%left T_LOGICAL_AND
|
||||||
|
%right T_PRINT
|
||||||
|
%right T_YIELD
|
||||||
|
%right T_DOUBLE_ARROW
|
||||||
|
%right T_YIELD_FROM
|
||||||
|
%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL
|
||||||
|
%left '?' ':'
|
||||||
|
%right T_COALESCE
|
||||||
|
%left T_BOOLEAN_OR
|
||||||
|
%left T_BOOLEAN_AND
|
||||||
|
%left '|'
|
||||||
|
%left '^'
|
||||||
|
%left '&'
|
||||||
|
%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP
|
||||||
|
%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL
|
||||||
|
%left T_SL T_SR
|
||||||
|
%left '+' '-' '.'
|
||||||
|
%left '*' '/' '%'
|
||||||
|
%right '!'
|
||||||
|
%nonassoc T_INSTANCEOF
|
||||||
|
%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
|
||||||
|
%right T_POW
|
||||||
|
%right '['
|
||||||
|
%nonassoc T_NEW T_CLONE
|
||||||
|
%token T_EXIT
|
||||||
|
%token T_IF
|
||||||
|
%left T_ELSEIF
|
||||||
|
%left T_ELSE
|
||||||
|
%left T_ENDIF
|
||||||
|
%token T_LNUMBER
|
||||||
|
%token T_DNUMBER
|
||||||
|
%token T_STRING
|
||||||
|
%token T_STRING_VARNAME
|
||||||
|
%token T_VARIABLE
|
||||||
|
%token T_NUM_STRING
|
||||||
|
%token T_INLINE_HTML
|
||||||
|
%token T_CHARACTER
|
||||||
|
%token T_BAD_CHARACTER
|
||||||
|
%token T_ENCAPSED_AND_WHITESPACE
|
||||||
|
%token T_CONSTANT_ENCAPSED_STRING
|
||||||
|
%token T_ECHO
|
||||||
|
%token T_DO
|
||||||
|
%token T_WHILE
|
||||||
|
%token T_ENDWHILE
|
||||||
|
%token T_FOR
|
||||||
|
%token T_ENDFOR
|
||||||
|
%token T_FOREACH
|
||||||
|
%token T_ENDFOREACH
|
||||||
|
%token T_DECLARE
|
||||||
|
%token T_ENDDECLARE
|
||||||
|
%token T_AS
|
||||||
|
%token T_SWITCH
|
||||||
|
%token T_ENDSWITCH
|
||||||
|
%token T_CASE
|
||||||
|
%token T_DEFAULT
|
||||||
|
%token T_BREAK
|
||||||
|
%token T_CONTINUE
|
||||||
|
%token T_GOTO
|
||||||
|
%token T_FUNCTION
|
||||||
|
%token T_CONST
|
||||||
|
%token T_RETURN
|
||||||
|
%token T_TRY
|
||||||
|
%token T_CATCH
|
||||||
|
%token T_FINALLY
|
||||||
|
%token T_THROW
|
||||||
|
%token T_USE
|
||||||
|
%token T_INSTEADOF
|
||||||
|
%token T_GLOBAL
|
||||||
|
%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC
|
||||||
|
%token T_VAR
|
||||||
|
%token T_UNSET
|
||||||
|
%token T_ISSET
|
||||||
|
%token T_EMPTY
|
||||||
|
%token T_HALT_COMPILER
|
||||||
|
%token T_CLASS
|
||||||
|
%token T_TRAIT
|
||||||
|
%token T_INTERFACE
|
||||||
|
%token T_EXTENDS
|
||||||
|
%token T_IMPLEMENTS
|
||||||
|
%token T_OBJECT_OPERATOR
|
||||||
|
%token T_DOUBLE_ARROW
|
||||||
|
%token T_LIST
|
||||||
|
%token T_ARRAY
|
||||||
|
%token T_CALLABLE
|
||||||
|
%token T_CLASS_C
|
||||||
|
%token T_TRAIT_C
|
||||||
|
%token T_METHOD_C
|
||||||
|
%token T_FUNC_C
|
||||||
|
%token T_LINE
|
||||||
|
%token T_FILE
|
||||||
|
%token T_COMMENT
|
||||||
|
%token T_DOC_COMMENT
|
||||||
|
%token T_OPEN_TAG
|
||||||
|
%token T_OPEN_TAG_WITH_ECHO
|
||||||
|
%token T_CLOSE_TAG
|
||||||
|
%token T_WHITESPACE
|
||||||
|
%token T_START_HEREDOC
|
||||||
|
%token T_END_HEREDOC
|
||||||
|
%token T_DOLLAR_OPEN_CURLY_BRACES
|
||||||
|
%token T_CURLY_OPEN
|
||||||
|
%token T_PAAMAYIM_NEKUDOTAYIM
|
||||||
|
%token T_NAMESPACE
|
||||||
|
%token T_NS_C
|
||||||
|
%token T_DIR
|
||||||
|
%token T_NS_SEPARATOR
|
||||||
|
%token T_ELLIPSIS
|
@ -7,14 +7,21 @@ namespace PhpParser;
|
|||||||
*/
|
*/
|
||||||
class Autoloader
|
class Autoloader
|
||||||
{
|
{
|
||||||
|
/** @var bool Whether the autoloader has been registered. */
|
||||||
|
private static $registered = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers PhpParser\Autoloader as an SPL autoloader.
|
* Registers PhpParser\Autoloader as an SPL autoloader.
|
||||||
*
|
*
|
||||||
* @param bool $prepend Whether to prepend the autoloader instead of appending
|
* @param bool $prepend Whether to prepend the autoloader instead of appending
|
||||||
*/
|
*/
|
||||||
static public function register($prepend = false) {
|
static public function register($prepend = false) {
|
||||||
ini_set('unserialize_callback_func', 'spl_autoload_call');
|
if (self::$registered === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
|
spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
|
||||||
|
self::$registered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,203 +35,6 @@ class Autoloader
|
|||||||
if (file_exists($fileName)) {
|
if (file_exists($fileName)) {
|
||||||
require $fileName;
|
require $fileName;
|
||||||
}
|
}
|
||||||
} else if (0 === strpos($class, 'PHPParser_')) {
|
|
||||||
if (isset(self::$oldToNewMap[$class])) {
|
|
||||||
self::registerLegacyAliases();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function registerLegacyAliases() {
|
|
||||||
foreach (self::$oldToNewMap as $old => $new) {
|
|
||||||
class_alias($new, $old);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static $oldToNewMap = array(
|
|
||||||
'PHPParser_Builder' => 'PhpParser\Builder',
|
|
||||||
'PHPParser_BuilderAbstract' => 'PhpParser\BuilderAbstract',
|
|
||||||
'PHPParser_BuilderFactory' => 'PhpParser\BuilderFactory',
|
|
||||||
'PHPParser_Comment' => 'PhpParser\Comment',
|
|
||||||
'PHPParser_Comment_Doc' => 'PhpParser\Comment\Doc',
|
|
||||||
'PHPParser_Error' => 'PhpParser\Error',
|
|
||||||
'PHPParser_Lexer' => 'PhpParser\Lexer',
|
|
||||||
'PHPParser_Lexer_Emulative' => 'PhpParser\Lexer\Emulative',
|
|
||||||
'PHPParser_Node' => 'PhpParser\Node',
|
|
||||||
'PHPParser_NodeAbstract' => 'PhpParser\NodeAbstract',
|
|
||||||
'PHPParser_NodeDumper' => 'PhpParser\NodeDumper',
|
|
||||||
'PHPParser_NodeTraverser' => 'PhpParser\NodeTraverser',
|
|
||||||
'PHPParser_NodeTraverserInterface' => 'PhpParser\NodeTraverserInterface',
|
|
||||||
'PHPParser_NodeVisitor' => 'PhpParser\NodeVisitor',
|
|
||||||
'PHPParser_NodeVisitor_NameResolver' => 'PhpParser\NodeVisitor\NameResolver',
|
|
||||||
'PHPParser_NodeVisitorAbstract' => 'PhpParser\NodeVisitorAbstract',
|
|
||||||
'PHPParser_Parser' => 'PhpParser\Parser',
|
|
||||||
'PHPParser_PrettyPrinterAbstract' => 'PhpParser\PrettyPrinterAbstract',
|
|
||||||
'PHPParser_PrettyPrinter_Default' => 'PhpParser\PrettyPrinter\Standard',
|
|
||||||
'PHPParser_PrettyPrinter_Zend' => 'PhpParser\PrettyPrinter\Standard',
|
|
||||||
'PHPParser_Serializer' => 'PhpParser\Serializer',
|
|
||||||
'PHPParser_Serializer_XML' => 'PhpParser\Serializer\XML',
|
|
||||||
'PHPParser_Unserializer' => 'PhpParser\Unserializer',
|
|
||||||
'PHPParser_Unserializer_XML' => 'PhpParser\Unserializer\XML',
|
|
||||||
|
|
||||||
'PHPParser_Builder_Class' => 'PhpParser\Builder\Class_',
|
|
||||||
'PHPParser_Builder_Function' => 'PhpParser\Builder\Function_',
|
|
||||||
'PHPParser_Builder_Interface' => 'PhpParser\Builder\Interface_',
|
|
||||||
'PHPParser_Builder_Method' => 'PhpParser\Builder\Method',
|
|
||||||
'PHPParser_Builder_Param' => 'PhpParser\Builder\Param',
|
|
||||||
'PHPParser_Builder_Property' => 'PhpParser\Builder\Property',
|
|
||||||
|
|
||||||
'PHPParser_Node_Arg' => 'PhpParser\Node\Arg',
|
|
||||||
'PHPParser_Node_Const' => 'PhpParser\Node\Const_',
|
|
||||||
'PHPParser_Node_Expr' => 'PhpParser\Node\Expr',
|
|
||||||
'PHPParser_Node_Name' => 'PhpParser\Node\Name',
|
|
||||||
'PHPParser_Node_Name_FullyQualified' => 'PhpParser\Node\Name\FullyQualified',
|
|
||||||
'PHPParser_Node_Name_Relative' => 'PhpParser\Node\Name\Relative',
|
|
||||||
'PHPParser_Node_Param' => 'PhpParser\Node\Param',
|
|
||||||
'PHPParser_Node_Scalar' => 'PhpParser\Node\Scalar',
|
|
||||||
'PHPParser_Node_Stmt' => 'PhpParser\Node\Stmt',
|
|
||||||
|
|
||||||
'PHPParser_Node_Stmt_Break' => 'PhpParser\Node\Stmt\Break_',
|
|
||||||
'PHPParser_Node_Stmt_Case' => 'PhpParser\Node\Stmt\Case_',
|
|
||||||
'PHPParser_Node_Stmt_Catch' => 'PhpParser\Node\Stmt\Catch_',
|
|
||||||
'PHPParser_Node_Stmt_Class' => 'PhpParser\Node\Stmt\Class_',
|
|
||||||
'PHPParser_Node_Stmt_ClassConst' => 'PhpParser\Node\Stmt\ClassConst',
|
|
||||||
'PHPParser_Node_Stmt_ClassMethod' => 'PhpParser\Node\Stmt\ClassMethod',
|
|
||||||
'PHPParser_Node_Stmt_Const' => 'PhpParser\Node\Stmt\Const_',
|
|
||||||
'PHPParser_Node_Stmt_Continue' => 'PhpParser\Node\Stmt\Continue_',
|
|
||||||
'PHPParser_Node_Stmt_Declare' => 'PhpParser\Node\Stmt\Declare_',
|
|
||||||
'PHPParser_Node_Stmt_DeclareDeclare' => 'PhpParser\Node\Stmt\DeclareDeclare',
|
|
||||||
'PHPParser_Node_Stmt_Do' => 'PhpParser\Node\Stmt\Do_',
|
|
||||||
'PHPParser_Node_Stmt_Echo' => 'PhpParser\Node\Stmt\Echo_',
|
|
||||||
'PHPParser_Node_Stmt_Else' => 'PhpParser\Node\Stmt\Else_',
|
|
||||||
'PHPParser_Node_Stmt_ElseIf' => 'PhpParser\Node\Stmt\ElseIf_',
|
|
||||||
'PHPParser_Node_Stmt_For' => 'PhpParser\Node\Stmt\For_',
|
|
||||||
'PHPParser_Node_Stmt_Foreach' => 'PhpParser\Node\Stmt\Foreach_',
|
|
||||||
'PHPParser_Node_Stmt_Function' => 'PhpParser\Node\Stmt\Function_',
|
|
||||||
'PHPParser_Node_Stmt_Global' => 'PhpParser\Node\Stmt\Global_',
|
|
||||||
'PHPParser_Node_Stmt_Goto' => 'PhpParser\Node\Stmt\Goto_',
|
|
||||||
'PHPParser_Node_Stmt_HaltCompiler' => 'PhpParser\Node\Stmt\HaltCompiler',
|
|
||||||
'PHPParser_Node_Stmt_If' => 'PhpParser\Node\Stmt\If_',
|
|
||||||
'PHPParser_Node_Stmt_InlineHTML' => 'PhpParser\Node\Stmt\InlineHTML',
|
|
||||||
'PHPParser_Node_Stmt_Interface' => 'PhpParser\Node\Stmt\Interface_',
|
|
||||||
'PHPParser_Node_Stmt_Label' => 'PhpParser\Node\Stmt\Label',
|
|
||||||
'PHPParser_Node_Stmt_Namespace' => 'PhpParser\Node\Stmt\Namespace_',
|
|
||||||
'PHPParser_Node_Stmt_Property' => 'PhpParser\Node\Stmt\Property',
|
|
||||||
'PHPParser_Node_Stmt_PropertyProperty' => 'PhpParser\Node\Stmt\PropertyProperty',
|
|
||||||
'PHPParser_Node_Stmt_Return' => 'PhpParser\Node\Stmt\Return_',
|
|
||||||
'PHPParser_Node_Stmt_Static' => 'PhpParser\Node\Stmt\Static_',
|
|
||||||
'PHPParser_Node_Stmt_StaticVar' => 'PhpParser\Node\Stmt\StaticVar',
|
|
||||||
'PHPParser_Node_Stmt_Switch' => 'PhpParser\Node\Stmt\Switch_',
|
|
||||||
'PHPParser_Node_Stmt_Throw' => 'PhpParser\Node\Stmt\Throw_',
|
|
||||||
'PHPParser_Node_Stmt_Trait' => 'PhpParser\Node\Stmt\Trait_',
|
|
||||||
'PHPParser_Node_Stmt_TraitUse' => 'PhpParser\Node\Stmt\TraitUse',
|
|
||||||
'PHPParser_Node_Stmt_TraitUseAdaptation' => 'PhpParser\Node\Stmt\TraitUseAdaptation',
|
|
||||||
'PHPParser_Node_Stmt_TraitUseAdaptation_Alias' => 'PhpParser\Node\Stmt\TraitUseAdaptation\Alias',
|
|
||||||
'PHPParser_Node_Stmt_TraitUseAdaptation_Precedence' => 'PhpParser\Node\Stmt\TraitUseAdaptation\Precedence',
|
|
||||||
'PHPParser_Node_Stmt_TryCatch' => 'PhpParser\Node\Stmt\TryCatch',
|
|
||||||
'PHPParser_Node_Stmt_Unset' => 'PhpParser\Node\Stmt\Unset_',
|
|
||||||
'PHPParser_Node_Stmt_UseUse' => 'PhpParser\Node\Stmt\UseUse',
|
|
||||||
'PHPParser_Node_Stmt_Use' => 'PhpParser\Node\Stmt\Use_',
|
|
||||||
'PHPParser_Node_Stmt_While' => 'PhpParser\Node\Stmt\While_',
|
|
||||||
|
|
||||||
'PHPParser_Node_Expr_AssignBitwiseAnd' => 'PhpParser\Node\Expr\AssignOp\BitwiseAnd',
|
|
||||||
'PHPParser_Node_Expr_AssignBitwiseOr' => 'PhpParser\Node\Expr\AssignOp\BitwiseOr',
|
|
||||||
'PHPParser_Node_Expr_AssignBitwiseXor' => 'PhpParser\Node\Expr\AssignOp\BitwiseXor',
|
|
||||||
'PHPParser_Node_Expr_AssignConcat' => 'PhpParser\Node\Expr\AssignOp\Concat',
|
|
||||||
'PHPParser_Node_Expr_AssignDiv' => 'PhpParser\Node\Expr\AssignOp\Div',
|
|
||||||
'PHPParser_Node_Expr_AssignMinus' => 'PhpParser\Node\Expr\AssignOp\Minus',
|
|
||||||
'PHPParser_Node_Expr_AssignMod' => 'PhpParser\Node\Expr\AssignOp\Mod',
|
|
||||||
'PHPParser_Node_Expr_AssignMul' => 'PhpParser\Node\Expr\AssignOp\Mul',
|
|
||||||
'PHPParser_Node_Expr_AssignPlus' => 'PhpParser\Node\Expr\AssignOp\Plus',
|
|
||||||
'PHPParser_Node_Expr_AssignShiftLeft' => 'PhpParser\Node\Expr\AssignOp\ShiftLeft',
|
|
||||||
'PHPParser_Node_Expr_AssignShiftRight' => 'PhpParser\Node\Expr\AssignOp\ShiftRight',
|
|
||||||
|
|
||||||
'PHPParser_Node_Expr_Cast' => 'PhpParser\Node\Expr\Cast',
|
|
||||||
'PHPParser_Node_Expr_Cast_Array' => 'PhpParser\Node\Expr\Cast\Array_',
|
|
||||||
'PHPParser_Node_Expr_Cast_Bool' => 'PhpParser\Node\Expr\Cast\Bool',
|
|
||||||
'PHPParser_Node_Expr_Cast_Double' => 'PhpParser\Node\Expr\Cast\Double',
|
|
||||||
'PHPParser_Node_Expr_Cast_Int' => 'PhpParser\Node\Expr\Cast\Int',
|
|
||||||
'PHPParser_Node_Expr_Cast_Object' => 'PhpParser\Node\Expr\Cast\Object',
|
|
||||||
'PHPParser_Node_Expr_Cast_String' => 'PhpParser\Node\Expr\Cast\String',
|
|
||||||
'PHPParser_Node_Expr_Cast_Unset' => 'PhpParser\Node\Expr\Cast\Unset_',
|
|
||||||
|
|
||||||
'PHPParser_Node_Expr_BitwiseAnd' => 'PhpParser\Node\Expr\BinaryOp\BitwiseAnd',
|
|
||||||
'PHPParser_Node_Expr_BitwiseOr' => 'PhpParser\Node\Expr\BinaryOp\BitwiseOr',
|
|
||||||
'PHPParser_Node_Expr_BitwiseXor' => 'PhpParser\Node\Expr\BinaryOp\BitwiseXor',
|
|
||||||
'PHPParser_Node_Expr_BooleanAnd' => 'PhpParser\Node\Expr\BinaryOp\BooleanAnd',
|
|
||||||
'PHPParser_Node_Expr_BooleanOr' => 'PhpParser\Node\Expr\BinaryOp\BooleanOr',
|
|
||||||
'PHPParser_Node_Expr_Concat' => 'PhpParser\Node\Expr\BinaryOp\Concat',
|
|
||||||
'PHPParser_Node_Expr_Div' => 'PhpParser\Node\Expr\BinaryOp\Div',
|
|
||||||
'PHPParser_Node_Expr_Equal' => 'PhpParser\Node\Expr\BinaryOp\Equal',
|
|
||||||
'PHPParser_Node_Expr_Greater' => 'PhpParser\Node\Expr\BinaryOp\Greater',
|
|
||||||
'PHPParser_Node_Expr_GreaterOrEqual' => 'PhpParser\Node\Expr\BinaryOp\GreaterOrEqual',
|
|
||||||
'PHPParser_Node_Expr_Identical' => 'PhpParser\Node\Expr\BinaryOp\Identical',
|
|
||||||
'PHPParser_Node_Expr_LogicalAnd' => 'PhpParser\Node\Expr\BinaryOp\LogicalAnd',
|
|
||||||
'PHPParser_Node_Expr_LogicalOr' => 'PhpParser\Node\Expr\BinaryOp\LogicalOr',
|
|
||||||
'PHPParser_Node_Expr_LogicalXor' => 'PhpParser\Node\Expr\BinaryOp\LogicalXor',
|
|
||||||
'PHPParser_Node_Expr_Minus' => 'PhpParser\Node\Expr\BinaryOp\Minus',
|
|
||||||
'PHPParser_Node_Expr_Mod' => 'PhpParser\Node\Expr\BinaryOp\Mod',
|
|
||||||
'PHPParser_Node_Expr_Mul' => 'PhpParser\Node\Expr\BinaryOp\Mul',
|
|
||||||
'PHPParser_Node_Expr_NotEqual' => 'PhpParser\Node\Expr\BinaryOp\NotEqual',
|
|
||||||
'PHPParser_Node_Expr_NotIdentical' => 'PhpParser\Node\Expr\BinaryOp\NotIdentical',
|
|
||||||
'PHPParser_Node_Expr_Plus' => 'PhpParser\Node\Expr\BinaryOp\Plus',
|
|
||||||
'PHPParser_Node_Expr_ShiftLeft' => 'PhpParser\Node\Expr\BinaryOp\ShiftLeft',
|
|
||||||
'PHPParser_Node_Expr_ShiftRight' => 'PhpParser\Node\Expr\BinaryOp\ShiftRight',
|
|
||||||
'PHPParser_Node_Expr_Smaller' => 'PhpParser\Node\Expr\BinaryOp\Smaller',
|
|
||||||
'PHPParser_Node_Expr_SmallerOrEqual' => 'PhpParser\Node\Expr\BinaryOp\SmallerOrEqual',
|
|
||||||
|
|
||||||
'PHPParser_Node_Expr_Array' => 'PhpParser\Node\Expr\Array_',
|
|
||||||
'PHPParser_Node_Expr_ArrayDimFetch' => 'PhpParser\Node\Expr\ArrayDimFetch',
|
|
||||||
'PHPParser_Node_Expr_ArrayItem' => 'PhpParser\Node\Expr\ArrayItem',
|
|
||||||
'PHPParser_Node_Expr_Assign' => 'PhpParser\Node\Expr\Assign',
|
|
||||||
'PHPParser_Node_Expr_AssignRef' => 'PhpParser\Node\Expr\AssignRef',
|
|
||||||
'PHPParser_Node_Expr_BitwiseNot' => 'PhpParser\Node\Expr\BitwiseNot',
|
|
||||||
'PHPParser_Node_Expr_BooleanNot' => 'PhpParser\Node\Expr\BooleanNot',
|
|
||||||
'PHPParser_Node_Expr_ClassConstFetch' => 'PhpParser\Node\Expr\ClassConstFetch',
|
|
||||||
'PHPParser_Node_Expr_Clone' => 'PhpParser\Node\Expr\Clone_',
|
|
||||||
'PHPParser_Node_Expr_Closure' => 'PhpParser\Node\Expr\Closure',
|
|
||||||
'PHPParser_Node_Expr_ClosureUse' => 'PhpParser\Node\Expr\ClosureUse',
|
|
||||||
'PHPParser_Node_Expr_ConstFetch' => 'PhpParser\Node\Expr\ConstFetch',
|
|
||||||
'PHPParser_Node_Expr_Empty' => 'PhpParser\Node\Expr\Empty_',
|
|
||||||
'PHPParser_Node_Expr_ErrorSuppress' => 'PhpParser\Node\Expr\ErrorSuppress',
|
|
||||||
'PHPParser_Node_Expr_Eval' => 'PhpParser\Node\Expr\Eval_',
|
|
||||||
'PHPParser_Node_Expr_Exit' => 'PhpParser\Node\Expr\Exit_',
|
|
||||||
'PHPParser_Node_Expr_FuncCall' => 'PhpParser\Node\Expr\FuncCall',
|
|
||||||
'PHPParser_Node_Expr_Include' => 'PhpParser\Node\Expr\Include_',
|
|
||||||
'PHPParser_Node_Expr_Instanceof' => 'PhpParser\Node\Expr\Instanceof_',
|
|
||||||
'PHPParser_Node_Expr_Isset' => 'PhpParser\Node\Expr\Isset_',
|
|
||||||
'PHPParser_Node_Expr_List' => 'PhpParser\Node\Expr\List_',
|
|
||||||
'PHPParser_Node_Expr_MethodCall' => 'PhpParser\Node\Expr\MethodCall',
|
|
||||||
'PHPParser_Node_Expr_New' => 'PhpParser\Node\Expr\New_',
|
|
||||||
'PHPParser_Node_Expr_PostDec' => 'PhpParser\Node\Expr\PostDec',
|
|
||||||
'PHPParser_Node_Expr_PostInc' => 'PhpParser\Node\Expr\PostInc',
|
|
||||||
'PHPParser_Node_Expr_PreDec' => 'PhpParser\Node\Expr\PreDec',
|
|
||||||
'PHPParser_Node_Expr_PreInc' => 'PhpParser\Node\Expr\PreInc',
|
|
||||||
'PHPParser_Node_Expr_Print' => 'PhpParser\Node\Expr\Print_',
|
|
||||||
'PHPParser_Node_Expr_PropertyFetch' => 'PhpParser\Node\Expr\PropertyFetch',
|
|
||||||
'PHPParser_Node_Expr_ShellExec' => 'PhpParser\Node\Expr\ShellExec',
|
|
||||||
'PHPParser_Node_Expr_StaticCall' => 'PhpParser\Node\Expr\StaticCall',
|
|
||||||
'PHPParser_Node_Expr_StaticPropertyFetch' => 'PhpParser\Node\Expr\StaticPropertyFetch',
|
|
||||||
'PHPParser_Node_Expr_Ternary' => 'PhpParser\Node\Expr\Ternary',
|
|
||||||
'PHPParser_Node_Expr_UnaryMinus' => 'PhpParser\Node\Expr\UnaryMinus',
|
|
||||||
'PHPParser_Node_Expr_UnaryPlus' => 'PhpParser\Node\Expr\UnaryPlus',
|
|
||||||
'PHPParser_Node_Expr_Variable' => 'PhpParser\Node\Expr\Variable',
|
|
||||||
'PHPParser_Node_Expr_Yield' => 'PhpParser\Node\Expr\Yield_',
|
|
||||||
|
|
||||||
'PHPParser_Node_Scalar_ClassConst' => 'PhpParser\Node\Scalar\MagicConst\Class_',
|
|
||||||
'PHPParser_Node_Scalar_DirConst' => 'PhpParser\Node\Scalar\MagicConst\Dir',
|
|
||||||
'PHPParser_Node_Scalar_FileConst' => 'PhpParser\Node\Scalar\MagicConst\File',
|
|
||||||
'PHPParser_Node_Scalar_FuncConst' => 'PhpParser\Node\Scalar\MagicConst\Function_',
|
|
||||||
'PHPParser_Node_Scalar_LineConst' => 'PhpParser\Node\Scalar\MagicConst\Line',
|
|
||||||
'PHPParser_Node_Scalar_MethodConst' => 'PhpParser\Node\Scalar\MagicConst\Method',
|
|
||||||
'PHPParser_Node_Scalar_NSConst' => 'PhpParser\Node\Scalar\MagicConst\Namespace_',
|
|
||||||
'PHPParser_Node_Scalar_TraitConst' => 'PhpParser\Node\Scalar\MagicConst\Trait_',
|
|
||||||
|
|
||||||
'PHPParser_Node_Scalar_DNumber' => 'PhpParser\Node\Scalar\DNumber',
|
|
||||||
'PHPParser_Node_Scalar_Encapsed' => 'PhpParser\Node\Scalar\Encapsed',
|
|
||||||
'PHPParser_Node_Scalar_LNumber' => 'PhpParser\Node\Scalar\LNumber',
|
|
||||||
'PHPParser_Node_Scalar_String' => 'PhpParser\Node\Scalar\String',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class_alias('PhpParser\Autoloader', 'PHPParser_Autoloader');
|
|
@ -6,18 +6,18 @@ use PhpParser;
|
|||||||
use PhpParser\Node\Name;
|
use PhpParser\Node\Name;
|
||||||
use PhpParser\Node\Stmt;
|
use PhpParser\Node\Stmt;
|
||||||
|
|
||||||
class Class_ extends PhpParser\BuilderAbstract
|
class Class_ extends Declaration
|
||||||
{
|
{
|
||||||
protected $name;
|
protected $name;
|
||||||
|
|
||||||
protected $extends;
|
protected $extends = null;
|
||||||
protected $implements;
|
protected $implements = array();
|
||||||
protected $type;
|
protected $type = 0;
|
||||||
|
|
||||||
protected $uses;
|
protected $uses = array();
|
||||||
protected $constants;
|
protected $constants = array();
|
||||||
protected $properties;
|
protected $properties = array();
|
||||||
protected $methods;
|
protected $methods = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a class builder.
|
* Creates a class builder.
|
||||||
@ -26,12 +26,6 @@ class Class_ extends PhpParser\BuilderAbstract
|
|||||||
*/
|
*/
|
||||||
public function __construct($name) {
|
public function __construct($name) {
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
|
|
||||||
$this->type = 0;
|
|
||||||
$this->extends = null;
|
|
||||||
$this->implements = array();
|
|
||||||
|
|
||||||
$this->uses = $this->constants = $this->properties = $this->methods = array();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,7 +33,7 @@ class Class_ extends PhpParser\BuilderAbstract
|
|||||||
*
|
*
|
||||||
* @param Name|string $class Name of class to extend
|
* @param Name|string $class Name of class to extend
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function extend($class) {
|
public function extend($class) {
|
||||||
$this->extends = $this->normalizeName($class);
|
$this->extends = $this->normalizeName($class);
|
||||||
@ -50,10 +44,9 @@ class Class_ extends PhpParser\BuilderAbstract
|
|||||||
/**
|
/**
|
||||||
* Implements one or more interfaces.
|
* Implements one or more interfaces.
|
||||||
*
|
*
|
||||||
* @param Name|string $interface Name of interface to implement
|
* @param Name|string ...$interfaces Names of interfaces to implement
|
||||||
* @param Name|string $... More interfaces to implement
|
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function implement() {
|
public function implement() {
|
||||||
foreach (func_get_args() as $interface) {
|
foreach (func_get_args() as $interface) {
|
||||||
@ -66,7 +59,7 @@ class Class_ extends PhpParser\BuilderAbstract
|
|||||||
/**
|
/**
|
||||||
* Makes the class abstract.
|
* Makes the class abstract.
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function makeAbstract() {
|
public function makeAbstract() {
|
||||||
$this->setModifier(Stmt\Class_::MODIFIER_ABSTRACT);
|
$this->setModifier(Stmt\Class_::MODIFIER_ABSTRACT);
|
||||||
@ -77,7 +70,7 @@ class Class_ extends PhpParser\BuilderAbstract
|
|||||||
/**
|
/**
|
||||||
* Makes the class final.
|
* Makes the class final.
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function makeFinal() {
|
public function makeFinal() {
|
||||||
$this->setModifier(Stmt\Class_::MODIFIER_FINAL);
|
$this->setModifier(Stmt\Class_::MODIFIER_FINAL);
|
||||||
@ -90,7 +83,7 @@ class Class_ extends PhpParser\BuilderAbstract
|
|||||||
*
|
*
|
||||||
* @param Stmt|PhpParser\Builder $stmt The statement to add
|
* @param Stmt|PhpParser\Builder $stmt The statement to add
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function addStmt($stmt) {
|
public function addStmt($stmt) {
|
||||||
$stmt = $this->normalizeNode($stmt);
|
$stmt = $this->normalizeNode($stmt);
|
||||||
@ -112,21 +105,6 @@ class Class_ extends PhpParser\BuilderAbstract
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds multiple statements.
|
|
||||||
*
|
|
||||||
* @param array $stmts The statements to add
|
|
||||||
*
|
|
||||||
* @return self The builder instance (for fluid interface)
|
|
||||||
*/
|
|
||||||
public function addStmts(array $stmts) {
|
|
||||||
foreach ($stmts as $stmt) {
|
|
||||||
$this->addStmt($stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the built class node.
|
* Returns the built class node.
|
||||||
*
|
*
|
||||||
@ -138,6 +116,6 @@ class Class_ extends PhpParser\BuilderAbstract
|
|||||||
'extends' => $this->extends,
|
'extends' => $this->extends,
|
||||||
'implements' => $this->implements,
|
'implements' => $this->implements,
|
||||||
'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods),
|
'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods),
|
||||||
));
|
), $this->attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
44
lib/PhpParser/Builder/Declaration.php
Normal file
44
lib/PhpParser/Builder/Declaration.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpParser\Builder;
|
||||||
|
|
||||||
|
use PhpParser;
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\Node\Stmt;
|
||||||
|
|
||||||
|
abstract class Declaration extends PhpParser\BuilderAbstract
|
||||||
|
{
|
||||||
|
protected $attributes = array();
|
||||||
|
|
||||||
|
abstract public function addStmt($stmt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets doc comment for the declaration.
|
||||||
|
*
|
||||||
|
* @param PhpParser\Comment\Doc|string $docComment Doc comment to set
|
||||||
|
*
|
||||||
|
* @return $this The builder instance (for fluid interface)
|
||||||
|
*/
|
||||||
|
public function setDocComment($docComment) {
|
||||||
|
$this->attributes['comments'] = array(
|
||||||
|
$this->normalizeDocComment($docComment)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
58
lib/PhpParser/Builder/FunctionLike.php
Normal file
58
lib/PhpParser/Builder/FunctionLike.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpParser\Builder;
|
||||||
|
|
||||||
|
use PhpParser;
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\Node\Stmt;
|
||||||
|
|
||||||
|
abstract class FunctionLike extends Declaration
|
||||||
|
{
|
||||||
|
protected $returnByRef = false;
|
||||||
|
protected $params = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the function return by reference.
|
||||||
|
*
|
||||||
|
* @return $this The builder instance (for fluid interface)
|
||||||
|
*/
|
||||||
|
public function makeReturnByRef() {
|
||||||
|
$this->returnByRef = true;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a parameter.
|
||||||
|
*
|
||||||
|
* @param Node\Param|Param $param The parameter to add
|
||||||
|
*
|
||||||
|
* @return $this The builder instance (for fluid interface)
|
||||||
|
*/
|
||||||
|
public function addParam($param) {
|
||||||
|
$param = $this->normalizeNode($param);
|
||||||
|
|
||||||
|
if (!$param instanceof Node\Param) {
|
||||||
|
throw new \LogicException(sprintf('Expected parameter node, got "%s"', $param->getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->params[] = $param;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds multiple parameters.
|
||||||
|
*
|
||||||
|
* @param array $params The parameters to add
|
||||||
|
*
|
||||||
|
* @return $this The builder instance (for fluid interface)
|
||||||
|
*/
|
||||||
|
public function addParams(array $params) {
|
||||||
|
foreach ($params as $param) {
|
||||||
|
$this->addParam($param);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
@ -6,13 +6,10 @@ use PhpParser;
|
|||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\Node\Stmt;
|
use PhpParser\Node\Stmt;
|
||||||
|
|
||||||
class Function_ extends PhpParser\BuilderAbstract
|
class Function_ extends FunctionLike
|
||||||
{
|
{
|
||||||
protected $name;
|
protected $name;
|
||||||
|
protected $stmts = array();
|
||||||
protected $returnByRef;
|
|
||||||
protected $params;
|
|
||||||
protected $stmts;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a function builder.
|
* Creates a function builder.
|
||||||
@ -21,55 +18,6 @@ class Function_ extends PhpParser\BuilderAbstract
|
|||||||
*/
|
*/
|
||||||
public function __construct($name) {
|
public function __construct($name) {
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
|
|
||||||
$this->returnByRef = false;
|
|
||||||
$this->params = array();
|
|
||||||
$this->stmts = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make the function return by reference.
|
|
||||||
*
|
|
||||||
* @return self The builder instance (for fluid interface)
|
|
||||||
*/
|
|
||||||
public function makeReturnByRef() {
|
|
||||||
$this->returnByRef = true;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a parameter.
|
|
||||||
*
|
|
||||||
* @param Node\Param|Param $param The parameter to add
|
|
||||||
*
|
|
||||||
* @return self The builder instance (for fluid interface)
|
|
||||||
*/
|
|
||||||
public function addParam($param) {
|
|
||||||
$param = $this->normalizeNode($param);
|
|
||||||
|
|
||||||
if (!$param instanceof Node\Param) {
|
|
||||||
throw new \LogicException(sprintf('Expected parameter node, got "%s"', $param->getType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->params[] = $param;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds multiple parameters.
|
|
||||||
*
|
|
||||||
* @param array $params The parameters to add
|
|
||||||
*
|
|
||||||
* @return self The builder instance (for fluid interface)
|
|
||||||
*/
|
|
||||||
public function addParams(array $params) {
|
|
||||||
foreach ($params as $param) {
|
|
||||||
$this->addParam($param);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,7 +25,7 @@ class Function_ extends PhpParser\BuilderAbstract
|
|||||||
*
|
*
|
||||||
* @param Node|PhpParser\Builder $stmt The statement to add
|
* @param Node|PhpParser\Builder $stmt The statement to add
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function addStmt($stmt) {
|
public function addStmt($stmt) {
|
||||||
$this->stmts[] = $this->normalizeNode($stmt);
|
$this->stmts[] = $this->normalizeNode($stmt);
|
||||||
@ -85,21 +33,6 @@ class Function_ extends PhpParser\BuilderAbstract
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds multiple statements.
|
|
||||||
*
|
|
||||||
* @param array $stmts The statements to add
|
|
||||||
*
|
|
||||||
* @return self The builder instance (for fluid interface)
|
|
||||||
*/
|
|
||||||
public function addStmts(array $stmts) {
|
|
||||||
foreach ($stmts as $stmt) {
|
|
||||||
$this->addStmt($stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the built function node.
|
* Returns the built function node.
|
||||||
*
|
*
|
||||||
@ -110,6 +43,6 @@ class Function_ extends PhpParser\BuilderAbstract
|
|||||||
'byRef' => $this->returnByRef,
|
'byRef' => $this->returnByRef,
|
||||||
'params' => $this->params,
|
'params' => $this->params,
|
||||||
'stmts' => $this->stmts,
|
'stmts' => $this->stmts,
|
||||||
));
|
), $this->attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,12 +6,12 @@ use PhpParser;
|
|||||||
use PhpParser\Node\Name;
|
use PhpParser\Node\Name;
|
||||||
use PhpParser\Node\Stmt;
|
use PhpParser\Node\Stmt;
|
||||||
|
|
||||||
class Interface_ extends PhpParser\BuilderAbstract
|
class Interface_ extends Declaration
|
||||||
{
|
{
|
||||||
protected $name;
|
protected $name;
|
||||||
protected $extends;
|
protected $extends = array();
|
||||||
protected $constants;
|
protected $constants = array();
|
||||||
protected $methods;
|
protected $methods = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an interface builder.
|
* Creates an interface builder.
|
||||||
@ -20,17 +20,14 @@ class Interface_ extends PhpParser\BuilderAbstract
|
|||||||
*/
|
*/
|
||||||
public function __construct($name) {
|
public function __construct($name) {
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
$this->extends = array();
|
|
||||||
$this->constants = $this->methods = array();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends one or more interfaces.
|
* Extends one or more interfaces.
|
||||||
*
|
*
|
||||||
* @param Name|string $interface Name of interface to extend
|
* @param Name|string ...$interfaces Names of interfaces to extend
|
||||||
* @param Name|string $... More interfaces to extend
|
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function extend() {
|
public function extend() {
|
||||||
foreach (func_get_args() as $interface) {
|
foreach (func_get_args() as $interface) {
|
||||||
@ -45,7 +42,7 @@ class Interface_ extends PhpParser\BuilderAbstract
|
|||||||
*
|
*
|
||||||
* @param Stmt|PhpParser\Builder $stmt The statement to add
|
* @param Stmt|PhpParser\Builder $stmt The statement to add
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function addStmt($stmt) {
|
public function addStmt($stmt) {
|
||||||
$stmt = $this->normalizeNode($stmt);
|
$stmt = $this->normalizeNode($stmt);
|
||||||
@ -70,22 +67,7 @@ class Interface_ extends PhpParser\BuilderAbstract
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds multiple statements.
|
* Returns the built interface node.
|
||||||
*
|
|
||||||
* @param array $stmts The statements to add
|
|
||||||
*
|
|
||||||
* @return self The builder instance (for fluid interface)
|
|
||||||
*/
|
|
||||||
public function addStmts(array $stmts) {
|
|
||||||
foreach ($stmts as $stmt) {
|
|
||||||
$this->addStmt($stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the built class node.
|
|
||||||
*
|
*
|
||||||
* @return Stmt\Interface_ The built interface node
|
* @return Stmt\Interface_ The built interface node
|
||||||
*/
|
*/
|
||||||
@ -93,6 +75,6 @@ class Interface_ extends PhpParser\BuilderAbstract
|
|||||||
return new Stmt\Interface_($this->name, array(
|
return new Stmt\Interface_($this->name, array(
|
||||||
'extends' => $this->extends,
|
'extends' => $this->extends,
|
||||||
'stmts' => array_merge($this->constants, $this->methods),
|
'stmts' => array_merge($this->constants, $this->methods),
|
||||||
));
|
), $this->attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,14 +6,11 @@ use PhpParser;
|
|||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\Node\Stmt;
|
use PhpParser\Node\Stmt;
|
||||||
|
|
||||||
class Method extends PhpParser\BuilderAbstract
|
class Method extends FunctionLike
|
||||||
{
|
{
|
||||||
protected $name;
|
protected $name;
|
||||||
|
protected $type = 0;
|
||||||
protected $type;
|
protected $stmts = array();
|
||||||
protected $returnByRef;
|
|
||||||
protected $params;
|
|
||||||
protected $stmts;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a method builder.
|
* Creates a method builder.
|
||||||
@ -22,17 +19,12 @@ class Method extends PhpParser\BuilderAbstract
|
|||||||
*/
|
*/
|
||||||
public function __construct($name) {
|
public function __construct($name) {
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
|
|
||||||
$this->type = 0;
|
|
||||||
$this->returnByRef = false;
|
|
||||||
$this->params = array();
|
|
||||||
$this->stmts = array();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes the method public.
|
* Makes the method public.
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function makePublic() {
|
public function makePublic() {
|
||||||
$this->setModifier(Stmt\Class_::MODIFIER_PUBLIC);
|
$this->setModifier(Stmt\Class_::MODIFIER_PUBLIC);
|
||||||
@ -43,7 +35,7 @@ class Method extends PhpParser\BuilderAbstract
|
|||||||
/**
|
/**
|
||||||
* Makes the method protected.
|
* Makes the method protected.
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function makeProtected() {
|
public function makeProtected() {
|
||||||
$this->setModifier(Stmt\Class_::MODIFIER_PROTECTED);
|
$this->setModifier(Stmt\Class_::MODIFIER_PROTECTED);
|
||||||
@ -54,7 +46,7 @@ class Method extends PhpParser\BuilderAbstract
|
|||||||
/**
|
/**
|
||||||
* Makes the method private.
|
* Makes the method private.
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function makePrivate() {
|
public function makePrivate() {
|
||||||
$this->setModifier(Stmt\Class_::MODIFIER_PRIVATE);
|
$this->setModifier(Stmt\Class_::MODIFIER_PRIVATE);
|
||||||
@ -65,7 +57,7 @@ class Method extends PhpParser\BuilderAbstract
|
|||||||
/**
|
/**
|
||||||
* Makes the method static.
|
* Makes the method static.
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function makeStatic() {
|
public function makeStatic() {
|
||||||
$this->setModifier(Stmt\Class_::MODIFIER_STATIC);
|
$this->setModifier(Stmt\Class_::MODIFIER_STATIC);
|
||||||
@ -76,7 +68,7 @@ class Method extends PhpParser\BuilderAbstract
|
|||||||
/**
|
/**
|
||||||
* Makes the method abstract.
|
* Makes the method abstract.
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function makeAbstract() {
|
public function makeAbstract() {
|
||||||
if (!empty($this->stmts)) {
|
if (!empty($this->stmts)) {
|
||||||
@ -92,7 +84,7 @@ class Method extends PhpParser\BuilderAbstract
|
|||||||
/**
|
/**
|
||||||
* Makes the method final.
|
* Makes the method final.
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function makeFinal() {
|
public function makeFinal() {
|
||||||
$this->setModifier(Stmt\Class_::MODIFIER_FINAL);
|
$this->setModifier(Stmt\Class_::MODIFIER_FINAL);
|
||||||
@ -100,57 +92,12 @@ class Method extends PhpParser\BuilderAbstract
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Make the method return by reference.
|
|
||||||
*
|
|
||||||
* @return self The builder instance (for fluid interface)
|
|
||||||
*/
|
|
||||||
public function makeReturnByRef() {
|
|
||||||
$this->returnByRef = true;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a parameter.
|
|
||||||
*
|
|
||||||
* @param Node\Param|Param $param The parameter to add
|
|
||||||
*
|
|
||||||
* @return self The builder instance (for fluid interface)
|
|
||||||
*/
|
|
||||||
public function addParam($param) {
|
|
||||||
$param = $this->normalizeNode($param);
|
|
||||||
|
|
||||||
if (!$param instanceof Node\Param) {
|
|
||||||
throw new \LogicException(sprintf('Expected parameter node, got "%s"', $param->getType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->params[] = $param;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds multiple parameters.
|
|
||||||
*
|
|
||||||
* @param array $params The parameters to add
|
|
||||||
*
|
|
||||||
* @return self The builder instance (for fluid interface)
|
|
||||||
*/
|
|
||||||
public function addParams(array $params) {
|
|
||||||
foreach ($params as $param) {
|
|
||||||
$this->addParam($param);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a statement.
|
* Adds a statement.
|
||||||
*
|
*
|
||||||
* @param Node|PhpParser\Builder $stmt The statement to add
|
* @param Node|PhpParser\Builder $stmt The statement to add
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function addStmt($stmt) {
|
public function addStmt($stmt) {
|
||||||
if (null === $this->stmts) {
|
if (null === $this->stmts) {
|
||||||
@ -162,21 +109,6 @@ class Method extends PhpParser\BuilderAbstract
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds multiple statements.
|
|
||||||
*
|
|
||||||
* @param array $stmts The statements to add
|
|
||||||
*
|
|
||||||
* @return self The builder instance (for fluid interface)
|
|
||||||
*/
|
|
||||||
public function addStmts(array $stmts) {
|
|
||||||
foreach ($stmts as $stmt) {
|
|
||||||
$this->addStmt($stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the built method node.
|
* Returns the built method node.
|
||||||
*
|
*
|
||||||
@ -184,10 +116,10 @@ class Method extends PhpParser\BuilderAbstract
|
|||||||
*/
|
*/
|
||||||
public function getNode() {
|
public function getNode() {
|
||||||
return new Stmt\ClassMethod($this->name, array(
|
return new Stmt\ClassMethod($this->name, array(
|
||||||
'type' => $this->type !== 0 ? $this->type : Stmt\Class_::MODIFIER_PUBLIC,
|
'type' => $this->type,
|
||||||
'byRef' => $this->returnByRef,
|
'byRef' => $this->returnByRef,
|
||||||
'params' => $this->params,
|
'params' => $this->params,
|
||||||
'stmts' => $this->stmts,
|
'stmts' => $this->stmts,
|
||||||
));
|
), $this->attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
59
lib/PhpParser/Builder/Namespace_.php
Normal file
59
lib/PhpParser/Builder/Namespace_.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpParser\Builder;
|
||||||
|
|
||||||
|
use PhpParser;
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\Node\Stmt;
|
||||||
|
|
||||||
|
class Namespace_ extends PhpParser\BuilderAbstract
|
||||||
|
{
|
||||||
|
private $name;
|
||||||
|
private $stmts = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a namespace builder.
|
||||||
|
*
|
||||||
|
* @param Node\Name|string|null $name Name of the namespace
|
||||||
|
*/
|
||||||
|
public function __construct($name) {
|
||||||
|
$this->name = null !== $name ? $this->normalizeName($name) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a statement.
|
||||||
|
*
|
||||||
|
* @param Node|PhpParser\Builder $stmt The statement to add
|
||||||
|
*
|
||||||
|
* @return $this The builder instance (for fluid interface)
|
||||||
|
*/
|
||||||
|
public function addStmt($stmt) {
|
||||||
|
$this->stmts[] = $this->normalizeNode($stmt);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -9,9 +9,9 @@ class Param extends PhpParser\BuilderAbstract
|
|||||||
{
|
{
|
||||||
protected $name;
|
protected $name;
|
||||||
|
|
||||||
protected $default;
|
protected $default = null;
|
||||||
protected $type;
|
protected $type = null;
|
||||||
protected $byRef;
|
protected $byRef = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a parameter builder.
|
* Creates a parameter builder.
|
||||||
@ -20,10 +20,6 @@ class Param extends PhpParser\BuilderAbstract
|
|||||||
*/
|
*/
|
||||||
public function __construct($name) {
|
public function __construct($name) {
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
|
|
||||||
$this->default = null;
|
|
||||||
$this->type = null;
|
|
||||||
$this->byRef = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,7 +27,7 @@ class Param extends PhpParser\BuilderAbstract
|
|||||||
*
|
*
|
||||||
* @param mixed $value Default value to use
|
* @param mixed $value Default value to use
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function setDefault($value) {
|
public function setDefault($value) {
|
||||||
$this->default = $this->normalizeValue($value);
|
$this->default = $this->normalizeValue($value);
|
||||||
@ -44,7 +40,7 @@ class Param extends PhpParser\BuilderAbstract
|
|||||||
*
|
*
|
||||||
* @param string|Node\Name $type Type hint to use
|
* @param string|Node\Name $type Type hint to use
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function setTypeHint($type) {
|
public function setTypeHint($type) {
|
||||||
if ($type === 'array' || $type === 'callable') {
|
if ($type === 'array' || $type === 'callable') {
|
||||||
@ -59,7 +55,7 @@ class Param extends PhpParser\BuilderAbstract
|
|||||||
/**
|
/**
|
||||||
* Make the parameter accept the value by reference.
|
* Make the parameter accept the value by reference.
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function makeByRef() {
|
public function makeByRef() {
|
||||||
$this->byRef = true;
|
$this->byRef = true;
|
||||||
|
@ -9,8 +9,9 @@ class Property extends PhpParser\BuilderAbstract
|
|||||||
{
|
{
|
||||||
protected $name;
|
protected $name;
|
||||||
|
|
||||||
protected $type;
|
protected $type = 0;
|
||||||
protected $default;
|
protected $default = null;
|
||||||
|
protected $attributes = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a property builder.
|
* Creates a property builder.
|
||||||
@ -19,15 +20,12 @@ class Property extends PhpParser\BuilderAbstract
|
|||||||
*/
|
*/
|
||||||
public function __construct($name) {
|
public function __construct($name) {
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
|
|
||||||
$this->type = 0;
|
|
||||||
$this->default = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes the property public.
|
* Makes the property public.
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function makePublic() {
|
public function makePublic() {
|
||||||
$this->setModifier(Stmt\Class_::MODIFIER_PUBLIC);
|
$this->setModifier(Stmt\Class_::MODIFIER_PUBLIC);
|
||||||
@ -38,7 +36,7 @@ class Property extends PhpParser\BuilderAbstract
|
|||||||
/**
|
/**
|
||||||
* Makes the property protected.
|
* Makes the property protected.
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function makeProtected() {
|
public function makeProtected() {
|
||||||
$this->setModifier(Stmt\Class_::MODIFIER_PROTECTED);
|
$this->setModifier(Stmt\Class_::MODIFIER_PROTECTED);
|
||||||
@ -49,7 +47,7 @@ class Property extends PhpParser\BuilderAbstract
|
|||||||
/**
|
/**
|
||||||
* Makes the property private.
|
* Makes the property private.
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function makePrivate() {
|
public function makePrivate() {
|
||||||
$this->setModifier(Stmt\Class_::MODIFIER_PRIVATE);
|
$this->setModifier(Stmt\Class_::MODIFIER_PRIVATE);
|
||||||
@ -60,7 +58,7 @@ class Property extends PhpParser\BuilderAbstract
|
|||||||
/**
|
/**
|
||||||
* Makes the property static.
|
* Makes the property static.
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function makeStatic() {
|
public function makeStatic() {
|
||||||
$this->setModifier(Stmt\Class_::MODIFIER_STATIC);
|
$this->setModifier(Stmt\Class_::MODIFIER_STATIC);
|
||||||
@ -73,7 +71,7 @@ class Property extends PhpParser\BuilderAbstract
|
|||||||
*
|
*
|
||||||
* @param mixed $value Default value to use
|
* @param mixed $value Default value to use
|
||||||
*
|
*
|
||||||
* @return self The builder instance (for fluid interface)
|
* @return $this The builder instance (for fluid interface)
|
||||||
*/
|
*/
|
||||||
public function setDefault($value) {
|
public function setDefault($value) {
|
||||||
$this->default = $this->normalizeValue($value);
|
$this->default = $this->normalizeValue($value);
|
||||||
@ -81,6 +79,21 @@ class Property extends PhpParser\BuilderAbstract
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets doc comment for the property.
|
||||||
|
*
|
||||||
|
* @param PhpParser\Comment\Doc|string $docComment Doc comment to set
|
||||||
|
*
|
||||||
|
* @return $this The builder instance (for fluid interface)
|
||||||
|
*/
|
||||||
|
public function setDocComment($docComment) {
|
||||||
|
$this->attributes = array(
|
||||||
|
'comments' => array($this->normalizeDocComment($docComment))
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the built class node.
|
* Returns the built class node.
|
||||||
*
|
*
|
||||||
@ -91,7 +104,8 @@ class Property extends PhpParser\BuilderAbstract
|
|||||||
$this->type !== 0 ? $this->type : Stmt\Class_::MODIFIER_PUBLIC,
|
$this->type !== 0 ? $this->type : Stmt\Class_::MODIFIER_PUBLIC,
|
||||||
array(
|
array(
|
||||||
new Stmt\PropertyProperty($this->name, $this->default)
|
new Stmt\PropertyProperty($this->name, $this->default)
|
||||||
)
|
),
|
||||||
|
$this->attributes
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
55
lib/PhpParser/Builder/Trait_.php
Normal file
55
lib/PhpParser/Builder/Trait_.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpParser\Builder;
|
||||||
|
|
||||||
|
use PhpParser;
|
||||||
|
use PhpParser\Node\Name;
|
||||||
|
use PhpParser\Node\Stmt;
|
||||||
|
|
||||||
|
class Trait_ extends Declaration
|
||||||
|
{
|
||||||
|
protected $name;
|
||||||
|
protected $properties = array();
|
||||||
|
protected $methods = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an interface builder.
|
||||||
|
*
|
||||||
|
* @param string $name Name of the interface
|
||||||
|
*/
|
||||||
|
public function __construct($name) {
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a statement.
|
||||||
|
*
|
||||||
|
* @param Stmt|PhpParser\Builder $stmt The statement to add
|
||||||
|
*
|
||||||
|
* @return $this The builder instance (for fluid interface)
|
||||||
|
*/
|
||||||
|
public function addStmt($stmt) {
|
||||||
|
$stmt = $this->normalizeNode($stmt);
|
||||||
|
|
||||||
|
if ($stmt instanceof Stmt\Property) {
|
||||||
|
$this->properties[] = $stmt;
|
||||||
|
} else if ($stmt instanceof Stmt\ClassMethod) {
|
||||||
|
$this->methods[] = $stmt;
|
||||||
|
} else {
|
||||||
|
throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the built trait node.
|
||||||
|
*
|
||||||
|
* @return Stmt\Trait_ The built interface node
|
||||||
|
*/
|
||||||
|
public function getNode() {
|
||||||
|
return new Stmt\Trait_(
|
||||||
|
$this->name, array_merge($this->properties, $this->methods), $this->attributes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
58
lib/PhpParser/Builder/Use_.php
Normal file
58
lib/PhpParser/Builder/Use_.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpParser\Builder;
|
||||||
|
|
||||||
|
use PhpParser\BuilderAbstract;
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\Node\Stmt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method $this as(string $alias) Sets alias for used name.
|
||||||
|
*/
|
||||||
|
class Use_ extends BuilderAbstract {
|
||||||
|
protected $name;
|
||||||
|
protected $type;
|
||||||
|
protected $alias = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a name use (alias) builder.
|
||||||
|
*
|
||||||
|
* @param Node\Name|string $name Name of the entity (namespace, class, function, constant) to alias
|
||||||
|
* @param int $type One of the Stmt\Use_::TYPE_* constants
|
||||||
|
*/
|
||||||
|
public function __construct($name, $type) {
|
||||||
|
$this->name = $this->normalizeName($name);
|
||||||
|
$this->type = $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets alias for used name.
|
||||||
|
*
|
||||||
|
* @param string $alias Alias to use (last component of full name by default)
|
||||||
|
*
|
||||||
|
* @return $this The builder instance (for fluid interface)
|
||||||
|
*/
|
||||||
|
protected function as_($alias) {
|
||||||
|
$this->alias = $alias;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
public function __call($name, $args) {
|
||||||
|
if (method_exists($this, $name . '_')) {
|
||||||
|
return call_user_func_array(array($this, $name . '_'), $args);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \LogicException(sprintf('Method "%s" does not exist', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the built node.
|
||||||
|
*
|
||||||
|
* @return Node The built node
|
||||||
|
*/
|
||||||
|
public function getNode() {
|
||||||
|
$alias = null !== $this->alias ? $this->alias : $this->name->getLast();
|
||||||
|
return new Stmt\Use_(array(
|
||||||
|
new Stmt\UseUse($this->name, $alias)
|
||||||
|
), $this->type);
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ use PhpParser\Node\Name;
|
|||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
use PhpParser\Node\Stmt;
|
use PhpParser\Node\Stmt;
|
||||||
use PhpParser\Node\Scalar;
|
use PhpParser\Node\Scalar;
|
||||||
|
use PhpParser\Comment;
|
||||||
|
|
||||||
abstract class BuilderAbstract implements Builder {
|
abstract class BuilderAbstract implements Builder {
|
||||||
/**
|
/**
|
||||||
@ -35,11 +36,23 @@ abstract class BuilderAbstract implements Builder {
|
|||||||
protected function normalizeName($name) {
|
protected function normalizeName($name) {
|
||||||
if ($name instanceof Name) {
|
if ($name instanceof Name) {
|
||||||
return $name;
|
return $name;
|
||||||
|
} elseif (is_string($name)) {
|
||||||
|
if (!$name) {
|
||||||
|
throw new \LogicException('Name cannot be empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($name[0] == '\\') {
|
||||||
|
return new Name\FullyQualified(substr($name, 1));
|
||||||
|
} elseif (0 === strpos($name, 'namespace\\')) {
|
||||||
|
return new Name\Relative(substr($name, strlen('namespace\\')));
|
||||||
} else {
|
} else {
|
||||||
return new Name($name);
|
return new Name($name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new \LogicException('Name must be a string or an instance of PhpParser\Node\Name');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalizes a value: Converts nulls, booleans, integers,
|
* Normalizes a value: Converts nulls, booleans, integers,
|
||||||
* floats, strings and arrays into their respective nodes
|
* floats, strings and arrays into their respective nodes
|
||||||
@ -64,7 +77,7 @@ abstract class BuilderAbstract implements Builder {
|
|||||||
} elseif (is_float($value)) {
|
} elseif (is_float($value)) {
|
||||||
return new Scalar\DNumber($value);
|
return new Scalar\DNumber($value);
|
||||||
} elseif (is_string($value)) {
|
} elseif (is_string($value)) {
|
||||||
return new Scalar\String($value);
|
return new Scalar\String_($value);
|
||||||
} elseif (is_array($value)) {
|
} elseif (is_array($value)) {
|
||||||
$items = array();
|
$items = array();
|
||||||
$lastKey = -1;
|
$lastKey = -1;
|
||||||
@ -89,6 +102,23 @@ abstract class BuilderAbstract implements Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc.
|
||||||
|
*
|
||||||
|
* @param Comment\Doc|string $docComment The doc comment to normalize
|
||||||
|
*
|
||||||
|
* @return Comment\Doc The normalized doc comment
|
||||||
|
*/
|
||||||
|
protected function normalizeDocComment($docComment) {
|
||||||
|
if ($docComment instanceof Comment\Doc) {
|
||||||
|
return $docComment;
|
||||||
|
} else if (is_string($docComment)) {
|
||||||
|
return new Comment\Doc($docComment);
|
||||||
|
} else {
|
||||||
|
throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a modifier in the $this->type property.
|
* Sets a modifier in the $this->type property.
|
||||||
*
|
*
|
||||||
|
@ -3,18 +3,32 @@
|
|||||||
namespace PhpParser;
|
namespace PhpParser;
|
||||||
|
|
||||||
use PhpParser\Builder;
|
use PhpParser\Builder;
|
||||||
|
use PhpParser\Node\Stmt\Use_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "class", "interface" and "function" are reserved keywords, so the methods are defined as _class(),
|
* The following methods use reserved keywords, so their implementation is defined with an underscore and made available
|
||||||
* _interface() and _function() in the class and are made available as class(), interface() and function()
|
* with the reserved name through __call() magic.
|
||||||
* through __call() magic.
|
|
||||||
*
|
*
|
||||||
|
* @method Builder\Namespace_ namespace(string $name) Creates a namespace builder.
|
||||||
* @method Builder\Class_ class(string $name) Creates a class builder.
|
* @method Builder\Class_ class(string $name) Creates a class builder.
|
||||||
* @method Builder\Function_ function(string $name) Creates a function builder
|
|
||||||
* @method Builder\Interface_ interface(string $name) Creates an interface builder.
|
* @method Builder\Interface_ interface(string $name) Creates an interface builder.
|
||||||
|
* @method Builder\Trait_ trait(string $name) Creates a trait builder.
|
||||||
|
* @method Builder\Function_ function(string $name) Creates a function builder.
|
||||||
|
* @method Builder\Use_ use(string $name) Creates a namespace/class use builder.
|
||||||
*/
|
*/
|
||||||
class BuilderFactory
|
class BuilderFactory
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a namespace builder.
|
||||||
|
*
|
||||||
|
* @param null|string|Node\Name $name Name of the namespace
|
||||||
|
*
|
||||||
|
* @return Builder\Namespace_ The created namespace builder
|
||||||
|
*/
|
||||||
|
protected function _namespace($name) {
|
||||||
|
return new Builder\Namespace_($name);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a class builder.
|
* Creates a class builder.
|
||||||
*
|
*
|
||||||
@ -27,7 +41,7 @@ class BuilderFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a interface builder.
|
* Creates an interface builder.
|
||||||
*
|
*
|
||||||
* @param string $name Name of the interface
|
* @param string $name Name of the interface
|
||||||
*
|
*
|
||||||
@ -37,6 +51,17 @@ class BuilderFactory
|
|||||||
return new Builder\Interface_($name);
|
return new Builder\Interface_($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a trait builder.
|
||||||
|
*
|
||||||
|
* @param string $name Name of the trait
|
||||||
|
*
|
||||||
|
* @return Builder\Trait_ The created trait builder
|
||||||
|
*/
|
||||||
|
protected function _trait($name) {
|
||||||
|
return new Builder\Trait_($name);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a method builder.
|
* Creates a method builder.
|
||||||
*
|
*
|
||||||
@ -81,6 +106,17 @@ class BuilderFactory
|
|||||||
return new Builder\Function_($name);
|
return new Builder\Function_($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a namespace/class use builder.
|
||||||
|
*
|
||||||
|
* @param string|Node\Name Name to alias
|
||||||
|
*
|
||||||
|
* @return Builder\Use_ The create use builder
|
||||||
|
*/
|
||||||
|
protected function _use($name) {
|
||||||
|
return new Builder\Use_($name, Use_::TYPE_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
public function __call($name, array $args) {
|
public function __call($name, array $args) {
|
||||||
if (method_exists($this, '_' . $name)) {
|
if (method_exists($this, '_' . $name)) {
|
||||||
return call_user_func_array(array($this, '_' . $name), $args);
|
return call_user_func_array(array($this, '_' . $name), $args);
|
||||||
|
@ -5,17 +5,22 @@ namespace PhpParser;
|
|||||||
class Error extends \RuntimeException
|
class Error extends \RuntimeException
|
||||||
{
|
{
|
||||||
protected $rawMessage;
|
protected $rawMessage;
|
||||||
protected $rawLine;
|
protected $attributes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an Exception signifying a parse error.
|
* Creates an Exception signifying a parse error.
|
||||||
*
|
*
|
||||||
* @param string $message Error message
|
* @param string $message Error message
|
||||||
* @param int $line Error line in PHP file
|
* @param array|int $attributes Attributes of node/token where error occurred
|
||||||
|
* (or start line of error -- deprecated)
|
||||||
*/
|
*/
|
||||||
public function __construct($message, $line = -1) {
|
public function __construct($message, $attributes = array()) {
|
||||||
$this->rawMessage = (string) $message;
|
$this->rawMessage = (string) $message;
|
||||||
$this->rawLine = (int) $line;
|
if (is_array($attributes)) {
|
||||||
|
$this->attributes = $attributes;
|
||||||
|
} else {
|
||||||
|
$this->attributes = array('startLine' => $attributes);
|
||||||
|
}
|
||||||
$this->updateMessage();
|
$this->updateMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,6 +33,34 @@ class Error extends \RuntimeException
|
|||||||
return $this->rawMessage;
|
return $this->rawMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the line the error starts in.
|
||||||
|
*
|
||||||
|
* @return int Error start line
|
||||||
|
*/
|
||||||
|
public function getStartLine() {
|
||||||
|
return isset($this->attributes['startLine']) ? $this->attributes['startLine'] : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the line the error ends in.
|
||||||
|
*
|
||||||
|
* @return int Error end line
|
||||||
|
*/
|
||||||
|
public function getEndLine() {
|
||||||
|
return isset($this->attributes['endLine']) ? $this->attributes['endLine'] : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the attributes of the node/token the error occurred at.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAttributes() {
|
||||||
|
return $this->attributes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the line of the PHP file the error occurred in.
|
* Sets the line of the PHP file the error occurred in.
|
||||||
*
|
*
|
||||||
@ -39,22 +72,65 @@ class Error extends \RuntimeException
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the error line in the PHP file.
|
* Sets the line the error starts in.
|
||||||
*
|
*
|
||||||
* @return int Error line in the PHP file
|
* @param int $line Error start line
|
||||||
*/
|
*/
|
||||||
public function getRawLine() {
|
public function setStartLine($line) {
|
||||||
return $this->rawLine;
|
$this->attributes['startLine'] = (int) $line;
|
||||||
|
$this->updateMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the line of the PHP file the error occurred in.
|
* Returns whether the error has start and end column information.
|
||||||
*
|
*
|
||||||
* @param int $line Error line in the PHP file
|
* For column information enable the startFilePos and endFilePos in the lexer options.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function setRawLine($line) {
|
public function hasColumnInfo() {
|
||||||
$this->rawLine = (int) $line;
|
return isset($this->attributes['startFilePos']) && isset($this->attributes['endFilePos']);
|
||||||
$this->updateMessage();
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the start column (1-based) into the line where the error started.
|
||||||
|
*
|
||||||
|
* @param string $code Source code of the file
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getStartColumn($code) {
|
||||||
|
if (!$this->hasColumnInfo()) {
|
||||||
|
throw new \RuntimeException('Error does not have column information');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->toColumn($code, $this->attributes['startFilePos']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the end column (1-based) into the line where the error ended.
|
||||||
|
*
|
||||||
|
* @param string $code Source code of the file
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getEndColumn($code) {
|
||||||
|
if (!$this->hasColumnInfo()) {
|
||||||
|
throw new \RuntimeException('Error does not have column information');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->toColumn($code, $this->attributes['endFilePos']);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function toColumn($code, $pos) {
|
||||||
|
if ($pos > strlen($code)) {
|
||||||
|
throw new \RuntimeException('Invalid position information');
|
||||||
|
}
|
||||||
|
|
||||||
|
$lineStartPos = strrpos($code, "\n", $pos - strlen($code));
|
||||||
|
if (false === $lineStartPos) {
|
||||||
|
$lineStartPos = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pos - $lineStartPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,10 +139,20 @@ class Error extends \RuntimeException
|
|||||||
protected function updateMessage() {
|
protected function updateMessage() {
|
||||||
$this->message = $this->rawMessage;
|
$this->message = $this->rawMessage;
|
||||||
|
|
||||||
if (-1 === $this->rawLine) {
|
if (-1 === $this->getStartLine()) {
|
||||||
$this->message .= ' on unknown line';
|
$this->message .= ' on unknown line';
|
||||||
} else {
|
} else {
|
||||||
$this->message .= ' on line ' . $this->rawLine;
|
$this->message .= ' on line ' . $this->getStartLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @deprecated Use getStartLine() instead */
|
||||||
|
public function getRawLine() {
|
||||||
|
return $this->getStartLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @deprecated Use setStartLine() instead */
|
||||||
|
public function setRawLine($line) {
|
||||||
|
$this->setStartLine($line);
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,26 +2,44 @@
|
|||||||
|
|
||||||
namespace PhpParser;
|
namespace PhpParser;
|
||||||
|
|
||||||
|
use PhpParser\Parser\Tokens;
|
||||||
|
|
||||||
class Lexer
|
class Lexer
|
||||||
{
|
{
|
||||||
protected $code;
|
protected $code;
|
||||||
protected $tokens;
|
protected $tokens;
|
||||||
protected $pos;
|
protected $pos;
|
||||||
protected $line;
|
protected $line;
|
||||||
|
protected $filePos;
|
||||||
|
|
||||||
protected $tokenMap;
|
protected $tokenMap;
|
||||||
protected $dropTokens;
|
protected $dropTokens;
|
||||||
|
|
||||||
|
protected $usedAttributes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a Lexer.
|
* Creates a Lexer.
|
||||||
|
*
|
||||||
|
* @param array $options Options array. Currently only the 'usedAttributes' option is supported,
|
||||||
|
* which is an array of attributes to add to the AST nodes. Possible attributes
|
||||||
|
* are: 'comments', 'startLine', 'endLine', 'startTokenPos', 'endTokenPos',
|
||||||
|
* 'startFilePos', 'endFilePos'. The option defaults to the first three.
|
||||||
|
* For more info see getNextToken() docs.
|
||||||
*/
|
*/
|
||||||
public function __construct() {
|
public function __construct(array $options = array()) {
|
||||||
// map from internal tokens to PhpParser tokens
|
// map from internal tokens to PhpParser tokens
|
||||||
$this->tokenMap = $this->createTokenMap();
|
$this->tokenMap = $this->createTokenMap();
|
||||||
|
|
||||||
// map of tokens to drop while lexing (the map is only used for isset lookup,
|
// map of tokens to drop while lexing (the map is only used for isset lookup,
|
||||||
// that's why the value is simply set to 1; the value is never actually used.)
|
// that's why the value is simply set to 1; the value is never actually used.)
|
||||||
$this->dropTokens = array_fill_keys(array(T_WHITESPACE, T_OPEN_TAG), 1);
|
$this->dropTokens = array_fill_keys(array(T_WHITESPACE, T_OPEN_TAG), 1);
|
||||||
|
|
||||||
|
// the usedAttributes member is a map of the used attribute names to a dummy
|
||||||
|
// value (here "true")
|
||||||
|
$options += array(
|
||||||
|
'usedAttributes' => array('comments', 'startLine', 'endLine'),
|
||||||
|
);
|
||||||
|
$this->usedAttributes = array_fill_keys($options['usedAttributes'], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,34 +50,44 @@ class Lexer
|
|||||||
* @throws Error on lexing errors (unterminated comment or unexpected character)
|
* @throws Error on lexing errors (unterminated comment or unexpected character)
|
||||||
*/
|
*/
|
||||||
public function startLexing($code) {
|
public function startLexing($code) {
|
||||||
$scream = ini_set('xdebug.scream', 0);
|
$scream = ini_set('xdebug.scream', '0');
|
||||||
|
|
||||||
$this->resetErrors();
|
$this->resetErrors();
|
||||||
$this->tokens = @token_get_all($code);
|
$this->tokens = @token_get_all($code);
|
||||||
$this->handleErrors();
|
$this->handleErrors();
|
||||||
|
|
||||||
|
if (false !== $scream) {
|
||||||
ini_set('xdebug.scream', $scream);
|
ini_set('xdebug.scream', $scream);
|
||||||
|
}
|
||||||
|
|
||||||
$this->code = $code; // keep the code around for __halt_compiler() handling
|
$this->code = $code; // keep the code around for __halt_compiler() handling
|
||||||
$this->pos = -1;
|
$this->pos = -1;
|
||||||
$this->line = 1;
|
$this->line = 1;
|
||||||
|
$this->filePos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function resetErrors() {
|
protected function resetErrors() {
|
||||||
|
if (function_exists('error_clear_last')) {
|
||||||
|
error_clear_last();
|
||||||
|
} else {
|
||||||
// set error_get_last() to defined state by forcing an undefined variable error
|
// set error_get_last() to defined state by forcing an undefined variable error
|
||||||
set_error_handler(function() { return false; }, 0);
|
set_error_handler(function() { return false; }, 0);
|
||||||
@$undefinedVariable;
|
@$undefinedVariable;
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function handleErrors() {
|
protected function handleErrors() {
|
||||||
$error = error_get_last();
|
$error = error_get_last();
|
||||||
|
if (null === $error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (preg_match(
|
if (preg_match(
|
||||||
'~^Unterminated comment starting line ([0-9]+)$~',
|
'~^Unterminated comment starting line ([0-9]+)$~',
|
||||||
$error['message'], $matches
|
$error['message'], $matches
|
||||||
)) {
|
)) {
|
||||||
throw new Error('Unterminated comment', $matches[1]);
|
throw new Error('Unterminated comment', (int) $matches[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preg_match(
|
if (preg_match(
|
||||||
@ -81,6 +109,19 @@ class Lexer
|
|||||||
/**
|
/**
|
||||||
* Fetches the next token.
|
* Fetches the next token.
|
||||||
*
|
*
|
||||||
|
* The available attributes are determined by the 'usedAttributes' option, which can
|
||||||
|
* be specified in the constructor. The following attributes are supported:
|
||||||
|
*
|
||||||
|
* * 'comments' => Array of PhpParser\Comment or PhpParser\Comment\Doc instances,
|
||||||
|
* representing all comments that occurred between the previous
|
||||||
|
* non-discarded token and the current one.
|
||||||
|
* * 'startLine' => Line in which the node starts.
|
||||||
|
* * 'endLine' => Line in which the node ends.
|
||||||
|
* * 'startTokenPos' => Offset into the token array of the first token in the node.
|
||||||
|
* * 'endTokenPos' => Offset into the token array of the last token in the node.
|
||||||
|
* * 'startFilePos' => Offset into the code string of the first character that is part of the node.
|
||||||
|
* * 'endFilePos' => Offset into the code string of the last character that is part of the node
|
||||||
|
*
|
||||||
* @param mixed $value Variable to store token content in
|
* @param mixed $value Variable to store token content in
|
||||||
* @param mixed $startAttributes Variable to store start attributes in
|
* @param mixed $startAttributes Variable to store start attributes in
|
||||||
* @param mixed $endAttributes Variable to store end attributes in
|
* @param mixed $endAttributes Variable to store end attributes in
|
||||||
@ -91,42 +132,95 @@ class Lexer
|
|||||||
$startAttributes = array();
|
$startAttributes = array();
|
||||||
$endAttributes = array();
|
$endAttributes = array();
|
||||||
|
|
||||||
while (isset($this->tokens[++$this->pos])) {
|
while (1) {
|
||||||
|
if (isset($this->tokens[++$this->pos])) {
|
||||||
$token = $this->tokens[$this->pos];
|
$token = $this->tokens[$this->pos];
|
||||||
|
} else {
|
||||||
|
// EOF token with ID 0
|
||||||
|
$token = "\0";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->usedAttributes['startTokenPos'])) {
|
||||||
|
$startAttributes['startTokenPos'] = $this->pos;
|
||||||
|
}
|
||||||
|
if (isset($this->usedAttributes['startFilePos'])) {
|
||||||
|
$startAttributes['startFilePos'] = $this->filePos;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_string($token)) {
|
if (is_string($token)) {
|
||||||
$startAttributes['startLine'] = $this->line;
|
|
||||||
$endAttributes['endLine'] = $this->line;
|
|
||||||
|
|
||||||
// bug in token_get_all
|
// bug in token_get_all
|
||||||
if ('b"' === $token) {
|
if ('b"' === $token) {
|
||||||
$value = 'b"';
|
$value = 'b"';
|
||||||
return ord('"');
|
$this->filePos += 2;
|
||||||
|
$id = ord('"');
|
||||||
} else {
|
} else {
|
||||||
$value = $token;
|
$value = $token;
|
||||||
return ord($token);
|
$this->filePos += 1;
|
||||||
|
$id = ord($token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($this->usedAttributes['startLine'])) {
|
||||||
|
$startAttributes['startLine'] = $this->line;
|
||||||
|
}
|
||||||
|
if (isset($this->usedAttributes['endLine'])) {
|
||||||
|
$endAttributes['endLine'] = $this->line;
|
||||||
|
}
|
||||||
|
if (isset($this->usedAttributes['endTokenPos'])) {
|
||||||
|
$endAttributes['endTokenPos'] = $this->pos;
|
||||||
|
}
|
||||||
|
if (isset($this->usedAttributes['endFilePos'])) {
|
||||||
|
$endAttributes['endFilePos'] = $this->filePos - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $id;
|
||||||
} else {
|
} else {
|
||||||
$this->line += substr_count($token[1], "\n");
|
$this->line += substr_count($token[1], "\n");
|
||||||
|
$this->filePos += strlen($token[1]);
|
||||||
|
|
||||||
if (T_COMMENT === $token[0]) {
|
if (T_COMMENT === $token[0]) {
|
||||||
|
if (isset($this->usedAttributes['comments'])) {
|
||||||
$startAttributes['comments'][] = new Comment($token[1], $token[2]);
|
$startAttributes['comments'][] = new Comment($token[1], $token[2]);
|
||||||
|
}
|
||||||
} elseif (T_DOC_COMMENT === $token[0]) {
|
} elseif (T_DOC_COMMENT === $token[0]) {
|
||||||
|
if (isset($this->usedAttributes['comments'])) {
|
||||||
$startAttributes['comments'][] = new Comment\Doc($token[1], $token[2]);
|
$startAttributes['comments'][] = new Comment\Doc($token[1], $token[2]);
|
||||||
|
}
|
||||||
} elseif (!isset($this->dropTokens[$token[0]])) {
|
} elseif (!isset($this->dropTokens[$token[0]])) {
|
||||||
$value = $token[1];
|
$value = $token[1];
|
||||||
|
|
||||||
|
if (isset($this->usedAttributes['startLine'])) {
|
||||||
$startAttributes['startLine'] = $token[2];
|
$startAttributes['startLine'] = $token[2];
|
||||||
|
}
|
||||||
|
if (isset($this->usedAttributes['endLine'])) {
|
||||||
$endAttributes['endLine'] = $this->line;
|
$endAttributes['endLine'] = $this->line;
|
||||||
|
}
|
||||||
|
if (isset($this->usedAttributes['endTokenPos'])) {
|
||||||
|
$endAttributes['endTokenPos'] = $this->pos;
|
||||||
|
}
|
||||||
|
if (isset($this->usedAttributes['endFilePos'])) {
|
||||||
|
$endAttributes['endFilePos'] = $this->filePos - 1;
|
||||||
|
}
|
||||||
|
|
||||||
return $this->tokenMap[$token[0]];
|
return $this->tokenMap[$token[0]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$startAttributes['startLine'] = $this->line;
|
throw new \RuntimeException('Reached end of lexer loop');
|
||||||
|
}
|
||||||
|
|
||||||
// 0 is the EOF token
|
/**
|
||||||
return 0;
|
* Returns the token array for current code.
|
||||||
|
*
|
||||||
|
* The token array is in the same format as provided by the
|
||||||
|
* token_get_all() function and does not discard tokens (i.e.
|
||||||
|
* whitespace and comments are included). The token position
|
||||||
|
* attributes are against this token array.
|
||||||
|
*
|
||||||
|
* @return array Array of tokens in token_get_all() format
|
||||||
|
*/
|
||||||
|
public function getTokens() {
|
||||||
|
return $this->tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,23 +229,13 @@ class Lexer
|
|||||||
* @return string Remaining text
|
* @return string Remaining text
|
||||||
*/
|
*/
|
||||||
public function handleHaltCompiler() {
|
public function handleHaltCompiler() {
|
||||||
// get the length of the text before the T_HALT_COMPILER token
|
|
||||||
$textBefore = '';
|
|
||||||
for ($i = 0; $i <= $this->pos; ++$i) {
|
|
||||||
if (is_string($this->tokens[$i])) {
|
|
||||||
$textBefore .= $this->tokens[$i];
|
|
||||||
} else {
|
|
||||||
$textBefore .= $this->tokens[$i][1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// text after T_HALT_COMPILER, still including ();
|
// text after T_HALT_COMPILER, still including ();
|
||||||
$textAfter = substr($this->code, strlen($textBefore));
|
$textAfter = substr($this->code, $this->filePos);
|
||||||
|
|
||||||
// ensure that it is followed by ();
|
// ensure that it is followed by ();
|
||||||
// this simplifies the situation, by not allowing any comments
|
// this simplifies the situation, by not allowing any comments
|
||||||
// in between of the tokens.
|
// in between of the tokens.
|
||||||
if (!preg_match('~\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) {
|
if (!preg_match('~^\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) {
|
||||||
throw new Error('__HALT_COMPILER must be followed by "();"');
|
throw new Error('__HALT_COMPILER must be followed by "();"');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,26 +261,33 @@ class Lexer
|
|||||||
// 256 is the minimum possible token number, as everything below
|
// 256 is the minimum possible token number, as everything below
|
||||||
// it is an ASCII value
|
// it is an ASCII value
|
||||||
for ($i = 256; $i < 1000; ++$i) {
|
for ($i = 256; $i < 1000; ++$i) {
|
||||||
// T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM
|
|
||||||
if (T_DOUBLE_COLON === $i) {
|
if (T_DOUBLE_COLON === $i) {
|
||||||
$tokenMap[$i] = Parser::T_PAAMAYIM_NEKUDOTAYIM;
|
// T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM
|
||||||
// T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO
|
$tokenMap[$i] = Tokens::T_PAAMAYIM_NEKUDOTAYIM;
|
||||||
} elseif(T_OPEN_TAG_WITH_ECHO === $i) {
|
} elseif(T_OPEN_TAG_WITH_ECHO === $i) {
|
||||||
$tokenMap[$i] = Parser::T_ECHO;
|
// T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO
|
||||||
// T_CLOSE_TAG is equivalent to ';'
|
$tokenMap[$i] = Tokens::T_ECHO;
|
||||||
} elseif(T_CLOSE_TAG === $i) {
|
} elseif(T_CLOSE_TAG === $i) {
|
||||||
|
// T_CLOSE_TAG is equivalent to ';'
|
||||||
$tokenMap[$i] = ord(';');
|
$tokenMap[$i] = ord(';');
|
||||||
// and the others can be mapped directly
|
} elseif ('UNKNOWN' !== $name = token_name($i)) {
|
||||||
} elseif ('UNKNOWN' !== ($name = token_name($i))
|
if ('T_HASHBANG' === $name) {
|
||||||
&& defined($name = 'PhpParser\Parser::' . $name)
|
// HHVM uses a special token for #! hashbang lines
|
||||||
) {
|
$tokenMap[$i] = Tokens::T_INLINE_HTML;
|
||||||
|
} else if (defined($name = 'PhpParser\Parser\Tokens::' . $name)) {
|
||||||
|
// Other tokens can be mapped directly
|
||||||
$tokenMap[$i] = constant($name);
|
$tokenMap[$i] = constant($name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// HHVM uses a special token for numbers that overflow to double
|
// HHVM uses a special token for numbers that overflow to double
|
||||||
if (defined('T_ONUMBER')) {
|
if (defined('T_ONUMBER')) {
|
||||||
$tokenMap[T_ONUMBER] = Parser::T_DNUMBER;
|
$tokenMap[T_ONUMBER] = Tokens::T_DNUMBER;
|
||||||
|
}
|
||||||
|
// HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant
|
||||||
|
if (defined('T_COMPILER_HALT_OFFSET')) {
|
||||||
|
$tokenMap[T_COMPILER_HALT_OFFSET] = Tokens::T_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $tokenMap;
|
return $tokenMap;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace PhpParser\Lexer;
|
namespace PhpParser\Lexer;
|
||||||
|
|
||||||
use PhpParser\Parser;
|
use PhpParser\Parser\Tokens;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ATTENTION: This code is WRITE-ONLY. Do not try to read it.
|
* ATTENTION: This code is WRITE-ONLY. Do not try to read it.
|
||||||
@ -15,24 +15,21 @@ class Emulative extends \PhpParser\Lexer
|
|||||||
const T_ELLIPSIS = 1001;
|
const T_ELLIPSIS = 1001;
|
||||||
const T_POW = 1002;
|
const T_POW = 1002;
|
||||||
const T_POW_EQUAL = 1003;
|
const T_POW_EQUAL = 1003;
|
||||||
|
const T_COALESCE = 1004;
|
||||||
|
const T_SPACESHIP = 1005;
|
||||||
|
const T_YIELD_FROM = 1006;
|
||||||
|
|
||||||
|
const PHP_7_0 = '7.0.0dev';
|
||||||
const PHP_5_6 = '5.6.0rc1';
|
const PHP_5_6 = '5.6.0rc1';
|
||||||
const PHP_5_5 = '5.5.0beta1';
|
const PHP_5_5 = '5.5.0beta1';
|
||||||
const PHP_5_4 = '5.4.0beta1';
|
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct(array $options = array()) {
|
||||||
parent::__construct();
|
parent::__construct($options);
|
||||||
|
|
||||||
$newKeywordsPerVersion = array(
|
$newKeywordsPerVersion = array(
|
||||||
self::PHP_5_5 => array(
|
self::PHP_5_5 => array(
|
||||||
'finally' => Parser::T_FINALLY,
|
'finally' => Tokens::T_FINALLY,
|
||||||
'yield' => Parser::T_YIELD,
|
'yield' => Tokens::T_YIELD,
|
||||||
),
|
|
||||||
self::PHP_5_4 => array(
|
|
||||||
'callable' => Parser::T_CALLABLE,
|
|
||||||
'insteadof' => Parser::T_INSTEADOF,
|
|
||||||
'trait' => Parser::T_TRAIT,
|
|
||||||
'__trait__' => Parser::T_TRAIT_C,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -45,11 +42,19 @@ class Emulative extends \PhpParser\Lexer
|
|||||||
$this->newKeywords += $newKeywords;
|
$this->newKeywords += $newKeywords;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version_compare(PHP_VERSION, self::PHP_5_6, '<')) {
|
if (version_compare(PHP_VERSION, self::PHP_7_0, '>=')) {
|
||||||
$this->tokenMap[self::T_ELLIPSIS] = Parser::T_ELLIPSIS;
|
return;
|
||||||
$this->tokenMap[self::T_POW] = Parser::T_POW;
|
|
||||||
$this->tokenMap[self::T_POW_EQUAL] = Parser::T_POW_EQUAL;
|
|
||||||
}
|
}
|
||||||
|
$this->tokenMap[self::T_COALESCE] = Tokens::T_COALESCE;
|
||||||
|
$this->tokenMap[self::T_SPACESHIP] = Tokens::T_SPACESHIP;
|
||||||
|
$this->tokenMap[self::T_YIELD_FROM] = Tokens::T_YIELD_FROM;
|
||||||
|
|
||||||
|
if (version_compare(PHP_VERSION, self::PHP_5_6, '>=')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->tokenMap[self::T_ELLIPSIS] = Tokens::T_ELLIPSIS;
|
||||||
|
$this->tokenMap[self::T_POW] = Tokens::T_POW;
|
||||||
|
$this->tokenMap[self::T_POW_EQUAL] = Tokens::T_POW_EQUAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function startLexing($code) {
|
public function startLexing($code) {
|
||||||
@ -60,6 +65,10 @@ class Emulative extends \PhpParser\Lexer
|
|||||||
if ($preprocessedCode !== $code) {
|
if ($preprocessedCode !== $code) {
|
||||||
$this->postprocessTokens();
|
$this->postprocessTokens();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set code property back to the original code, so __halt_compiler()
|
||||||
|
// handling and (start|end)FilePos attributes use the correct offsets
|
||||||
|
$this->code = $code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -71,6 +80,17 @@ class Emulative extends \PhpParser\Lexer
|
|||||||
* inside a string, i.e. a place where they don't have a special meaning).
|
* inside a string, i.e. a place where they don't have a special meaning).
|
||||||
*/
|
*/
|
||||||
protected function preprocessCode($code) {
|
protected function preprocessCode($code) {
|
||||||
|
if (version_compare(PHP_VERSION, self::PHP_7_0, '>=')) {
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
$code = str_replace('??', '~__EMU__COALESCE__~', $code);
|
||||||
|
$code = str_replace('<=>', '~__EMU__SPACESHIP__~', $code);
|
||||||
|
$code = preg_replace_callback('(yield[ \n\r\t]+from)', function($matches) {
|
||||||
|
// Encoding $0 in order to preserve exact whitespace
|
||||||
|
return '~__EMU__YIELDFROM__' . bin2hex($matches[0]) . '__~';
|
||||||
|
}, $code);
|
||||||
|
|
||||||
if (version_compare(PHP_VERSION, self::PHP_5_6, '>=')) {
|
if (version_compare(PHP_VERSION, self::PHP_5_6, '>=')) {
|
||||||
return $code;
|
return $code;
|
||||||
}
|
}
|
||||||
@ -79,14 +99,9 @@ class Emulative extends \PhpParser\Lexer
|
|||||||
$code = preg_replace('((?<!/)\*\*=)', '~__EMU__POWEQUAL__~', $code);
|
$code = preg_replace('((?<!/)\*\*=)', '~__EMU__POWEQUAL__~', $code);
|
||||||
$code = preg_replace('((?<!/)\*\*(?!/))', '~__EMU__POW__~', $code);
|
$code = preg_replace('((?<!/)\*\*(?!/))', '~__EMU__POW__~', $code);
|
||||||
|
|
||||||
if (version_compare(PHP_VERSION, self::PHP_5_4, '>=')) {
|
|
||||||
return $code;
|
return $code;
|
||||||
}
|
}
|
||||||
|
|
||||||
// binary notation (0b010101101001...)
|
|
||||||
return preg_replace('(\b0b[01]+\b)', '~__EMU__BINARY__$0__~', $code);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Replaces the ~__EMU__...~ sequences with real tokens or their original
|
* Replaces the ~__EMU__...~ sequences with real tokens or their original
|
||||||
* value.
|
* value.
|
||||||
@ -103,13 +118,7 @@ class Emulative extends \PhpParser\Lexer
|
|||||||
&& T_STRING === $this->tokens[$i + 1][0]
|
&& T_STRING === $this->tokens[$i + 1][0]
|
||||||
&& preg_match('(^__EMU__([A-Z]++)__(?:([A-Za-z0-9]++)__)?$)', $this->tokens[$i + 1][1], $matches)
|
&& preg_match('(^__EMU__([A-Z]++)__(?:([A-Za-z0-9]++)__)?$)', $this->tokens[$i + 1][1], $matches)
|
||||||
) {
|
) {
|
||||||
if ('BINARY' === $matches[1]) {
|
if ('ELLIPSIS' === $matches[1]) {
|
||||||
// the binary number can either be an integer or a double, so return a LNUMBER
|
|
||||||
// or DNUMBER respectively
|
|
||||||
$replace = array(
|
|
||||||
array(is_int(bindec($matches[2])) ? T_LNUMBER : T_DNUMBER, $matches[2], $this->tokens[$i + 1][2])
|
|
||||||
);
|
|
||||||
} else if ('ELLIPSIS' === $matches[1]) {
|
|
||||||
$replace = array(
|
$replace = array(
|
||||||
array(self::T_ELLIPSIS, '...', $this->tokens[$i + 1][2])
|
array(self::T_ELLIPSIS, '...', $this->tokens[$i + 1][2])
|
||||||
);
|
);
|
||||||
@ -121,9 +130,21 @@ class Emulative extends \PhpParser\Lexer
|
|||||||
$replace = array(
|
$replace = array(
|
||||||
array(self::T_POW_EQUAL, '**=', $this->tokens[$i + 1][2])
|
array(self::T_POW_EQUAL, '**=', $this->tokens[$i + 1][2])
|
||||||
);
|
);
|
||||||
|
} else if ('COALESCE' === $matches[1]) {
|
||||||
|
$replace = array(
|
||||||
|
array(self::T_COALESCE, '??', $this->tokens[$i + 1][2])
|
||||||
|
);
|
||||||
|
} else if ('SPACESHIP' === $matches[1]) {
|
||||||
|
$replace = array(
|
||||||
|
array(self::T_SPACESHIP, '<=>', $this->tokens[$i + 1][2]),
|
||||||
|
);
|
||||||
|
} else if ('YIELDFROM' === $matches[1]) {
|
||||||
|
$content = hex2bin($matches[2]);
|
||||||
|
$replace = array(
|
||||||
|
array(self::T_YIELD_FROM, $content, $this->tokens[$i + 1][2] - substr_count($content, "\n"))
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// just ignore all other __EMU__ sequences
|
throw new \RuntimeException('Invalid __EMU__ sequence');
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
array_splice($this->tokens, $i, 3, $replace);
|
array_splice($this->tokens, $i, 3, $replace);
|
||||||
@ -147,14 +168,18 @@ class Emulative extends \PhpParser\Lexer
|
|||||||
* multichar tokens (like strings) to their original value.
|
* multichar tokens (like strings) to their original value.
|
||||||
*/
|
*/
|
||||||
public function restoreContentCallback(array $matches) {
|
public function restoreContentCallback(array $matches) {
|
||||||
if ('BINARY' === $matches[1]) {
|
if ('ELLIPSIS' === $matches[1]) {
|
||||||
return $matches[2];
|
|
||||||
} else if ('ELLIPSIS' === $matches[1]) {
|
|
||||||
return '...';
|
return '...';
|
||||||
} else if ('POW' === $matches[1]) {
|
} else if ('POW' === $matches[1]) {
|
||||||
return '**';
|
return '**';
|
||||||
} else if ('POWEQUAL' === $matches[1]) {
|
} else if ('POWEQUAL' === $matches[1]) {
|
||||||
return '**=';
|
return '**=';
|
||||||
|
} else if ('COALESCE' === $matches[1]) {
|
||||||
|
return '??';
|
||||||
|
} else if ('SPACESHIP' === $matches[1]) {
|
||||||
|
return '<=>';
|
||||||
|
} else if ('YIELDFROM' === $matches[1]) {
|
||||||
|
return hex2bin($matches[2]);
|
||||||
} else {
|
} else {
|
||||||
return $matches[0];
|
return $matches[0];
|
||||||
}
|
}
|
||||||
@ -166,15 +191,13 @@ class Emulative extends \PhpParser\Lexer
|
|||||||
// replace new keywords by their respective tokens. This is not done
|
// replace new keywords by their respective tokens. This is not done
|
||||||
// if we currently are in an object access (e.g. in $obj->namespace
|
// if we currently are in an object access (e.g. in $obj->namespace
|
||||||
// "namespace" stays a T_STRING tokens and isn't converted to T_NAMESPACE)
|
// "namespace" stays a T_STRING tokens and isn't converted to T_NAMESPACE)
|
||||||
if (Parser::T_STRING === $token && !$this->inObjectAccess) {
|
if (Tokens::T_STRING === $token && !$this->inObjectAccess) {
|
||||||
if (isset($this->newKeywords[strtolower($value)])) {
|
if (isset($this->newKeywords[strtolower($value)])) {
|
||||||
return $this->newKeywords[strtolower($value)];
|
return $this->newKeywords[strtolower($value)];
|
||||||
}
|
}
|
||||||
// keep track of whether we currently are in an object access (after ->)
|
|
||||||
} elseif (Parser::T_OBJECT_OPERATOR === $token) {
|
|
||||||
$this->inObjectAccess = true;
|
|
||||||
} else {
|
} else {
|
||||||
$this->inObjectAccess = false;
|
// keep track of whether we currently are in an object access (after ->)
|
||||||
|
$this->inObjectAccess = Tokens::T_OBJECT_OPERATOR === $token;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $token;
|
return $token;
|
||||||
|
@ -4,13 +4,15 @@ namespace PhpParser\Node;
|
|||||||
|
|
||||||
use PhpParser\NodeAbstract;
|
use PhpParser\NodeAbstract;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $value Value to pass
|
|
||||||
* @property bool $byRef Whether to pass by ref
|
|
||||||
* @property bool $unpack Whether to unpack the argument
|
|
||||||
*/
|
|
||||||
class Arg extends NodeAbstract
|
class Arg extends NodeAbstract
|
||||||
{
|
{
|
||||||
|
/** @var Expr Value to pass */
|
||||||
|
public $value;
|
||||||
|
/** @var bool Whether to pass by ref */
|
||||||
|
public $byRef;
|
||||||
|
/** @var bool Whether to unpack the argument */
|
||||||
|
public $unpack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a function call argument node.
|
* Constructs a function call argument node.
|
||||||
*
|
*
|
||||||
@ -20,13 +22,13 @@ class Arg extends NodeAbstract
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $value, $byRef = false, $unpack = false, array $attributes = array()) {
|
public function __construct(Expr $value, $byRef = false, $unpack = false, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->value = $value;
|
||||||
'value' => $value,
|
$this->byRef = $byRef;
|
||||||
'byRef' => $byRef,
|
$this->unpack = $unpack;
|
||||||
'unpack' => $unpack,
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('value', 'byRef', 'unpack');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,12 +4,13 @@ namespace PhpParser\Node;
|
|||||||
|
|
||||||
use PhpParser\NodeAbstract;
|
use PhpParser\NodeAbstract;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property string $name Name
|
|
||||||
* @property Expr $value Value
|
|
||||||
*/
|
|
||||||
class Const_ extends NodeAbstract
|
class Const_ extends NodeAbstract
|
||||||
{
|
{
|
||||||
|
/** @var string Name */
|
||||||
|
public $name;
|
||||||
|
/** @var Expr Value */
|
||||||
|
public $value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a const node for use in class const and const statements.
|
* Constructs a const node for use in class const and const statements.
|
||||||
*
|
*
|
||||||
@ -18,12 +19,12 @@ class Const_ extends NodeAbstract
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct($name, Expr $value, array $attributes = array()) {
|
public function __construct($name, Expr $value, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->name = $name;
|
||||||
'name' => $name,
|
$this->value = $value;
|
||||||
'value' => $value,
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('name', 'value');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,12 +4,13 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $var Variable
|
|
||||||
* @property null|Expr $dim Array index / dim
|
|
||||||
*/
|
|
||||||
class ArrayDimFetch extends Expr
|
class ArrayDimFetch extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Variable */
|
||||||
|
public $var;
|
||||||
|
/** @var null|Expr Array index / dim */
|
||||||
|
public $dim;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an array index fetch node.
|
* Constructs an array index fetch node.
|
||||||
*
|
*
|
||||||
@ -18,12 +19,12 @@ class ArrayDimFetch extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $var, Expr $dim = null, array $attributes = array()) {
|
public function __construct(Expr $var, Expr $dim = null, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->var = $var;
|
||||||
'var' => $var,
|
$this->dim = $dim;
|
||||||
'dim' => $dim
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubnodeNames() {
|
||||||
);
|
return array('var', 'dim');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,13 +4,15 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $value Value
|
|
||||||
* @property null|Expr $key Key
|
|
||||||
* @property bool $byRef Whether to assign by reference
|
|
||||||
*/
|
|
||||||
class ArrayItem extends Expr
|
class ArrayItem extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var null|Expr Key */
|
||||||
|
public $key;
|
||||||
|
/** @var Expr Value */
|
||||||
|
public $value;
|
||||||
|
/** @var bool Whether to assign by reference */
|
||||||
|
public $byRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an array item node.
|
* Constructs an array item node.
|
||||||
*
|
*
|
||||||
@ -20,13 +22,13 @@ class ArrayItem extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $value, Expr $key = null, $byRef = false, array $attributes = array()) {
|
public function __construct(Expr $value, Expr $key = null, $byRef = false, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->key = $key;
|
||||||
'key' => $key,
|
$this->value = $value;
|
||||||
'value' => $value,
|
$this->byRef = $byRef;
|
||||||
'byRef' => $byRef
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('key', 'value', 'byRef');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property ArrayItem[] $items Items
|
|
||||||
*/
|
|
||||||
class Array_ extends Expr
|
class Array_ extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var ArrayItem[] Items */
|
||||||
|
public $items;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an array node.
|
* Constructs an array node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class Array_ extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(array $items = array(), array $attributes = array()) {
|
public function __construct(array $items = array(), array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->items = $items;
|
||||||
'items' => $items
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('items');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,12 +4,13 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $var Variable
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
*/
|
|
||||||
class Assign extends Expr
|
class Assign extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Variable */
|
||||||
|
public $var;
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an assignment node.
|
* Constructs an assignment node.
|
||||||
*
|
*
|
||||||
@ -18,12 +19,12 @@ class Assign extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $var, Expr $expr, array $attributes = array()) {
|
public function __construct(Expr $var, Expr $expr, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->var = $var;
|
||||||
'var' => $var,
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('var', 'expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,12 +4,13 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $var Variable
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
*/
|
|
||||||
abstract class AssignOp extends Expr
|
abstract class AssignOp extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Variable */
|
||||||
|
public $var;
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a compound assignment operation node.
|
* Constructs a compound assignment operation node.
|
||||||
*
|
*
|
||||||
@ -18,12 +19,12 @@ abstract class AssignOp extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $var, Expr $expr, array $attributes = array()) {
|
public function __construct(Expr $var, Expr $expr, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->var = $var;
|
||||||
'var' => $var,
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('var', 'expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,12 +4,13 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $var Variable reference is assigned to
|
|
||||||
* @property Expr $expr Variable which is referenced
|
|
||||||
*/
|
|
||||||
class AssignRef extends Expr
|
class AssignRef extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Variable reference is assigned to */
|
||||||
|
public $var;
|
||||||
|
/** @var Expr Variable which is referenced */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an assignment node.
|
* Constructs an assignment node.
|
||||||
*
|
*
|
||||||
@ -18,12 +19,12 @@ class AssignRef extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $var, Expr $expr, array $attributes = array()) {
|
public function __construct(Expr $var, Expr $expr, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->var = $var;
|
||||||
'var' => $var,
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('var', 'expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,12 +4,13 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
abstract class BinaryOp extends Expr
|
||||||
* @property Expr $left The left hand side expression
|
|
||||||
* @property Expr $right The right hand side expression
|
|
||||||
*/
|
|
||||||
class BinaryOp extends Expr
|
|
||||||
{
|
{
|
||||||
|
/** @var Expr The left hand side expression */
|
||||||
|
public $left;
|
||||||
|
/** @var Expr The right hand side expression */
|
||||||
|
public $right;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a bitwise and node.
|
* Constructs a bitwise and node.
|
||||||
*
|
*
|
||||||
@ -18,12 +19,12 @@ class BinaryOp extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $left, Expr $right, array $attributes = array()) {
|
public function __construct(Expr $left, Expr $right, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->left = $left;
|
||||||
'left' => $left,
|
$this->right = $right;
|
||||||
'right' => $right
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('left', 'right');
|
||||||
}
|
}
|
||||||
}
|
}
|
9
lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php
Normal file
9
lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpParser\Node\Expr\BinaryOp;
|
||||||
|
|
||||||
|
use PhpParser\Node\Expr\BinaryOp;
|
||||||
|
|
||||||
|
class Coalesce extends BinaryOp
|
||||||
|
{
|
||||||
|
}
|
9
lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php
Normal file
9
lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpParser\Node\Expr\BinaryOp;
|
||||||
|
|
||||||
|
use PhpParser\Node\Expr\BinaryOp;
|
||||||
|
|
||||||
|
class Spaceship extends BinaryOp
|
||||||
|
{
|
||||||
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
*/
|
|
||||||
class BitwiseNot extends Expr
|
class BitwiseNot extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a bitwise not node.
|
* Constructs a bitwise not node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class BitwiseNot extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $expr, array $attributes = array()) {
|
public function __construct(Expr $expr, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
*/
|
|
||||||
class BooleanNot extends Expr
|
class BooleanNot extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a boolean not node.
|
* Constructs a boolean not node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class BooleanNot extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $expr, array $attributes = array()) {
|
public function __construct(Expr $expr, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
*/
|
|
||||||
abstract class Cast extends Expr
|
abstract class Cast extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a cast node.
|
* Constructs a cast node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ abstract class Cast extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $expr, array $attributes = array()) {
|
public function __construct(Expr $expr, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,6 +4,6 @@ namespace PhpParser\Node\Expr\Cast;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr\Cast;
|
use PhpParser\Node\Expr\Cast;
|
||||||
|
|
||||||
class Int extends Cast
|
class Bool_ extends Cast
|
||||||
{
|
{
|
||||||
}
|
}
|
@ -4,6 +4,6 @@ namespace PhpParser\Node\Expr\Cast;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr\Cast;
|
use PhpParser\Node\Expr\Cast;
|
||||||
|
|
||||||
class Bool extends Cast
|
class Int_ extends Cast
|
||||||
{
|
{
|
||||||
}
|
}
|
@ -4,6 +4,6 @@ namespace PhpParser\Node\Expr\Cast;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr\Cast;
|
use PhpParser\Node\Expr\Cast;
|
||||||
|
|
||||||
class Object extends Cast
|
class Object_ extends Cast
|
||||||
{
|
{
|
||||||
}
|
}
|
@ -4,6 +4,6 @@ namespace PhpParser\Node\Expr\Cast;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr\Cast;
|
use PhpParser\Node\Expr\Cast;
|
||||||
|
|
||||||
class String extends Cast
|
class String_ extends Cast
|
||||||
{
|
{
|
||||||
}
|
}
|
@ -5,12 +5,13 @@ namespace PhpParser\Node\Expr;
|
|||||||
use PhpParser\Node\Name;
|
use PhpParser\Node\Name;
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Name|Expr $class Class name
|
|
||||||
* @property string $name Constant name
|
|
||||||
*/
|
|
||||||
class ClassConstFetch extends Expr
|
class ClassConstFetch extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Name|Expr Class name */
|
||||||
|
public $class;
|
||||||
|
/** @var string Constant name */
|
||||||
|
public $name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a class const fetch node.
|
* Constructs a class const fetch node.
|
||||||
*
|
*
|
||||||
@ -19,12 +20,12 @@ class ClassConstFetch extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct($class, $name, array $attributes = array()) {
|
public function __construct($class, $name, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->class = $class;
|
||||||
'class' => $class,
|
$this->name = $name;
|
||||||
'name' => $name
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('class', 'name');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
*/
|
|
||||||
class Clone_ extends Expr
|
class Clone_ extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a clone node.
|
* Constructs a clone node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class Clone_ extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $expr, array $attributes = array()) {
|
public function __construct(Expr $expr, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,16 +4,23 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
use PhpParser\Node\FunctionLike;
|
||||||
|
|
||||||
/**
|
class Closure extends Expr implements FunctionLike
|
||||||
* @property Node[] $stmts Statements
|
|
||||||
* @property Node\Param[] $params Parameters
|
|
||||||
* @property ClosureUse[] $uses use()s
|
|
||||||
* @property bool $byRef Whether to return by reference
|
|
||||||
* @property bool $static Whether the closure is static
|
|
||||||
*/
|
|
||||||
class Closure extends Expr
|
|
||||||
{
|
{
|
||||||
|
/** @var bool Whether the closure is static */
|
||||||
|
public $static;
|
||||||
|
/** @var bool Whether to return by reference */
|
||||||
|
public $byRef;
|
||||||
|
/** @var Node\Param[] Parameters */
|
||||||
|
public $params;
|
||||||
|
/** @var ClosureUse[] use()s */
|
||||||
|
public $uses;
|
||||||
|
/** @var null|string|Node\Name Return type */
|
||||||
|
public $returnType;
|
||||||
|
/** @var Node[] Statements */
|
||||||
|
public $stmts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a lambda function node.
|
* Constructs a lambda function node.
|
||||||
*
|
*
|
||||||
@ -22,19 +29,37 @@ class Closure extends Expr
|
|||||||
* 'byRef' => false : Whether to return by reference
|
* 'byRef' => false : Whether to return by reference
|
||||||
* 'params' => array(): Parameters
|
* 'params' => array(): Parameters
|
||||||
* 'uses' => array(): use()s
|
* 'uses' => array(): use()s
|
||||||
|
* 'returnType' => null : Return type
|
||||||
* 'stmts' => array(): Statements
|
* 'stmts' => array(): Statements
|
||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(array $subNodes = array(), array $attributes = array()) {
|
public function __construct(array $subNodes = array(), array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->static = isset($subNodes['static']) ? $subNodes['static'] : false;
|
||||||
'static' => isset($subNodes['static']) ? $subNodes['static'] : false,
|
$this->byRef = isset($subNodes['byRef']) ? $subNodes['byRef'] : false;
|
||||||
'byRef' => isset($subNodes['byRef']) ? $subNodes['byRef'] : false,
|
$this->params = isset($subNodes['params']) ? $subNodes['params'] : array();
|
||||||
'params' => isset($subNodes['params']) ? $subNodes['params'] : array(),
|
$this->uses = isset($subNodes['uses']) ? $subNodes['uses'] : array();
|
||||||
'uses' => isset($subNodes['uses']) ? $subNodes['uses'] : array(),
|
$this->returnType = isset($subNodes['returnType']) ? $subNodes['returnType'] : null;
|
||||||
'stmts' => isset($subNodes['stmts']) ? $subNodes['stmts'] : array(),
|
$this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array();
|
||||||
),
|
}
|
||||||
$attributes
|
|
||||||
);
|
public function getSubNodeNames() {
|
||||||
|
return array('static', 'byRef', 'params', 'uses', 'returnType', 'stmts');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function returnsByRef() {
|
||||||
|
return $this->byRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParams() {
|
||||||
|
return $this->params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getReturnType() {
|
||||||
|
return $this->returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStmts() {
|
||||||
|
return $this->stmts;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,12 +4,13 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property string $var Name of variable
|
|
||||||
* @property bool $byRef Whether to use by reference
|
|
||||||
*/
|
|
||||||
class ClosureUse extends Expr
|
class ClosureUse extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var string Name of variable */
|
||||||
|
public $var;
|
||||||
|
/** @var bool Whether to use by reference */
|
||||||
|
public $byRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a closure use node.
|
* Constructs a closure use node.
|
||||||
*
|
*
|
||||||
@ -18,12 +19,12 @@ class ClosureUse extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct($var, $byRef = false, array $attributes = array()) {
|
public function __construct($var, $byRef = false, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->var = $var;
|
||||||
'var' => $var,
|
$this->byRef = $byRef;
|
||||||
'byRef' => $byRef
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('var', 'byRef');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,11 +5,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
use PhpParser\Node\Name;
|
use PhpParser\Node\Name;
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Name $name Constant name
|
|
||||||
*/
|
|
||||||
class ConstFetch extends Expr
|
class ConstFetch extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Name Constant name */
|
||||||
|
public $name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a const fetch node.
|
* Constructs a const fetch node.
|
||||||
*
|
*
|
||||||
@ -17,11 +17,11 @@ class ConstFetch extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Name $name, array $attributes = array()) {
|
public function __construct(Name $name, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->name = $name;
|
||||||
'name' => $name
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('name');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
*/
|
|
||||||
class Empty_ extends Expr
|
class Empty_ extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an empty() node.
|
* Constructs an empty() node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class Empty_ extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $expr, array $attributes = array()) {
|
public function __construct(Expr $expr, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
*/
|
|
||||||
class ErrorSuppress extends Expr
|
class ErrorSuppress extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an error suppress node.
|
* Constructs an error suppress node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class ErrorSuppress extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $expr, array $attributes = array()) {
|
public function __construct(Expr $expr, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
*/
|
|
||||||
class Eval_ extends Expr
|
class Eval_ extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an eval() node.
|
* Constructs an eval() node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class Eval_ extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $expr, array $attributes = array()) {
|
public function __construct(Expr $expr, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property null|Expr $expr Expression
|
|
||||||
*/
|
|
||||||
class Exit_ extends Expr
|
class Exit_ extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var null|Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an exit() node.
|
* Constructs an exit() node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class Exit_ extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $expr = null, array $attributes = array()) {
|
public function __construct(Expr $expr = null, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,12 +5,13 @@ namespace PhpParser\Node\Expr;
|
|||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Node\Name|Expr $name Function name
|
|
||||||
* @property Node\Arg[] $args Arguments
|
|
||||||
*/
|
|
||||||
class FuncCall extends Expr
|
class FuncCall extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Node\Name|Expr Function name */
|
||||||
|
public $name;
|
||||||
|
/** @var Node\Arg[] Arguments */
|
||||||
|
public $args;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a function call node.
|
* Constructs a function call node.
|
||||||
*
|
*
|
||||||
@ -19,12 +20,12 @@ class FuncCall extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct($name, array $args = array(), array $attributes = array()) {
|
public function __construct($name, array $args = array(), array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->name = $name;
|
||||||
'name' => $name,
|
$this->args = $args;
|
||||||
'args' => $args
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('name', 'args');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,10 +4,6 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
* @property int $type Type of include
|
|
||||||
*/
|
|
||||||
class Include_ extends Expr
|
class Include_ extends Expr
|
||||||
{
|
{
|
||||||
const TYPE_INCLUDE = 1;
|
const TYPE_INCLUDE = 1;
|
||||||
@ -15,6 +11,11 @@ class Include_ extends Expr
|
|||||||
const TYPE_REQUIRE = 3;
|
const TYPE_REQUIRE = 3;
|
||||||
const TYPE_REQUIRE_ONCE = 4;
|
const TYPE_REQUIRE_ONCE = 4;
|
||||||
|
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
/** @var int Type of include */
|
||||||
|
public $type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an include node.
|
* Constructs an include node.
|
||||||
*
|
*
|
||||||
@ -23,12 +24,12 @@ class Include_ extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $expr, $type, array $attributes = array()) {
|
public function __construct(Expr $expr, $type, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->expr = $expr;
|
||||||
'expr' => $expr,
|
$this->type = $type;
|
||||||
'type' => $type
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('expr', 'type');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,12 +5,13 @@ namespace PhpParser\Node\Expr;
|
|||||||
use PhpParser\Node\Name;
|
use PhpParser\Node\Name;
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
* @property Name|Expr $class Class name
|
|
||||||
*/
|
|
||||||
class Instanceof_ extends Expr
|
class Instanceof_ extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
/** @var Name|Expr Class name */
|
||||||
|
public $class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instanceof check node.
|
* Constructs an instanceof check node.
|
||||||
*
|
*
|
||||||
@ -19,12 +20,12 @@ class Instanceof_ extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $expr, $class, array $attributes = array()) {
|
public function __construct(Expr $expr, $class, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->expr = $expr;
|
||||||
'expr' => $expr,
|
$this->class = $class;
|
||||||
'class' => $class
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('expr', 'class');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr[] $vars Variables
|
|
||||||
*/
|
|
||||||
class Isset_ extends Expr
|
class Isset_ extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr[] Variables */
|
||||||
|
public $vars;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an array node.
|
* Constructs an array node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class Isset_ extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(array $vars, array $attributes = array()) {
|
public function __construct(array $vars, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->vars = $vars;
|
||||||
'vars' => $vars
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('vars');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr[] $vars List of variables to assign to
|
|
||||||
*/
|
|
||||||
class List_ extends Expr
|
class List_ extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr[] List of variables to assign to */
|
||||||
|
public $vars;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a list() destructuring node.
|
* Constructs a list() destructuring node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class List_ extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(array $vars, array $attributes = array()) {
|
public function __construct(array $vars, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->vars = $vars;
|
||||||
'vars' => $vars,
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('vars');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,13 +5,15 @@ namespace PhpParser\Node\Expr;
|
|||||||
use PhpParser\Node\Arg;
|
use PhpParser\Node\Arg;
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $var Variable holding object
|
|
||||||
* @property string|Expr $name Method name
|
|
||||||
* @property Arg[] $args Arguments
|
|
||||||
*/
|
|
||||||
class MethodCall extends Expr
|
class MethodCall extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Variable holding object */
|
||||||
|
public $var;
|
||||||
|
/** @var string|Expr Method name */
|
||||||
|
public $name;
|
||||||
|
/** @var Arg[] Arguments */
|
||||||
|
public $args;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a function call node.
|
* Constructs a function call node.
|
||||||
*
|
*
|
||||||
@ -21,13 +23,13 @@ class MethodCall extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $var, $name, array $args = array(), array $attributes = array()) {
|
public function __construct(Expr $var, $name, array $args = array(), array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->var = $var;
|
||||||
'var' => $var,
|
$this->name = $name;
|
||||||
'name' => $name,
|
$this->args = $args;
|
||||||
'args' => $args
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('var', 'name', 'args');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,26 +5,27 @@ namespace PhpParser\Node\Expr;
|
|||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Node\Name|Expr $class Class name
|
|
||||||
* @property Node\Arg[] $args Arguments
|
|
||||||
*/
|
|
||||||
class New_ extends Expr
|
class New_ extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Node\Name|Expr|Node\Stmt\Class_ Class name */
|
||||||
|
public $class;
|
||||||
|
/** @var Node\Arg[] Arguments */
|
||||||
|
public $args;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a function call node.
|
* Constructs a function call node.
|
||||||
*
|
*
|
||||||
* @param Node\Name|Expr $class Class name
|
* @param Node\Name|Expr|Node\Stmt\Class_ $class Class name (or class node for anonymous classes)
|
||||||
* @param Node\Arg[] $args Arguments
|
* @param Node\Arg[] $args Arguments
|
||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct($class, array $args = array(), array $attributes = array()) {
|
public function __construct($class, array $args = array(), array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->class = $class;
|
||||||
'class' => $class,
|
$this->args = $args;
|
||||||
'args' => $args
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('class', 'args');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $var Variable
|
|
||||||
*/
|
|
||||||
class PostDec extends Expr
|
class PostDec extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Variable */
|
||||||
|
public $var;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a post decrement node.
|
* Constructs a post decrement node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class PostDec extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $var, array $attributes = array()) {
|
public function __construct(Expr $var, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->var = $var;
|
||||||
'var' => $var
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('var');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $var Variable
|
|
||||||
*/
|
|
||||||
class PostInc extends Expr
|
class PostInc extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Variable */
|
||||||
|
public $var;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a post increment node.
|
* Constructs a post increment node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class PostInc extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $var, array $attributes = array()) {
|
public function __construct(Expr $var, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->var = $var;
|
||||||
'var' => $var
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('var');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $var Variable
|
|
||||||
*/
|
|
||||||
class PreDec extends Expr
|
class PreDec extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Variable */
|
||||||
|
public $var;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a pre decrement node.
|
* Constructs a pre decrement node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class PreDec extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $var, array $attributes = array()) {
|
public function __construct(Expr $var, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->var = $var;
|
||||||
'var' => $var
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('var');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $var Variable
|
|
||||||
*/
|
|
||||||
class PreInc extends Expr
|
class PreInc extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Variable */
|
||||||
|
public $var;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a pre increment node.
|
* Constructs a pre increment node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class PreInc extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $var, array $attributes = array()) {
|
public function __construct(Expr $var, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->var = $var;
|
||||||
'var' => $var
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('var');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
*/
|
|
||||||
class Print_ extends Expr
|
class Print_ extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an print() node.
|
* Constructs an print() node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class Print_ extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $expr, array $attributes = array()) {
|
public function __construct(Expr $expr, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,12 +4,13 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $var Variable holding object
|
|
||||||
* @property string|Expr $name Property Name
|
|
||||||
*/
|
|
||||||
class PropertyFetch extends Expr
|
class PropertyFetch extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Variable holding object */
|
||||||
|
public $var;
|
||||||
|
/** @var string|Expr Property name */
|
||||||
|
public $name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a function call node.
|
* Constructs a function call node.
|
||||||
*
|
*
|
||||||
@ -18,12 +19,12 @@ class PropertyFetch extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $var, $name, array $attributes = array()) {
|
public function __construct(Expr $var, $name, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->var = $var;
|
||||||
'var' => $var,
|
$this->name = $name;
|
||||||
'name' => $name
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('var', 'name');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,23 +4,23 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property array $parts Encapsed string array
|
|
||||||
*/
|
|
||||||
class ShellExec extends Expr
|
class ShellExec extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var array Encapsed string array */
|
||||||
|
public $parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a shell exec (backtick) node.
|
* Constructs a shell exec (backtick) node.
|
||||||
*
|
*
|
||||||
* @param array $parts Encapsed string array
|
* @param array $parts Encapsed string array
|
||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct($parts, array $attributes = array()) {
|
public function __construct(array $parts, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->parts = $parts;
|
||||||
'parts' => $parts
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('parts');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,13 +5,15 @@ namespace PhpParser\Node\Expr;
|
|||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Node\Name|Expr $class Class name
|
|
||||||
* @property string|Expr $name Method name
|
|
||||||
* @property Node\Arg[] $args Arguments
|
|
||||||
*/
|
|
||||||
class StaticCall extends Expr
|
class StaticCall extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Node\Name|Expr Class name */
|
||||||
|
public $class;
|
||||||
|
/** @var string|Expr Method name */
|
||||||
|
public $name;
|
||||||
|
/** @var Node\Arg[] Arguments */
|
||||||
|
public $args;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a static method call node.
|
* Constructs a static method call node.
|
||||||
*
|
*
|
||||||
@ -21,13 +23,13 @@ class StaticCall extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct($class, $name, array $args = array(), array $attributes = array()) {
|
public function __construct($class, $name, array $args = array(), array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->class = $class;
|
||||||
'class' => $class,
|
$this->name = $name;
|
||||||
'name' => $name,
|
$this->args = $args;
|
||||||
'args' => $args
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('class', 'name', 'args');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,12 +5,13 @@ namespace PhpParser\Node\Expr;
|
|||||||
use PhpParser\Node\Name;
|
use PhpParser\Node\Name;
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Name|Expr $class Class name
|
|
||||||
* @property string|Expr $name Property name
|
|
||||||
*/
|
|
||||||
class StaticPropertyFetch extends Expr
|
class StaticPropertyFetch extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Name|Expr Class name */
|
||||||
|
public $class;
|
||||||
|
/** @var string|Expr Property name */
|
||||||
|
public $name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a static property fetch node.
|
* Constructs a static property fetch node.
|
||||||
*
|
*
|
||||||
@ -19,12 +20,12 @@ class StaticPropertyFetch extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct($class, $name, array $attributes = array()) {
|
public function __construct($class, $name, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->class = $class;
|
||||||
'class' => $class,
|
$this->name = $name;
|
||||||
'name' => $name
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('class', 'name');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,13 +4,15 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $cond Condition
|
|
||||||
* @property null|Expr $if Expression for true
|
|
||||||
* @property Expr $else Expression for false
|
|
||||||
*/
|
|
||||||
class Ternary extends Expr
|
class Ternary extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Condition */
|
||||||
|
public $cond;
|
||||||
|
/** @var null|Expr Expression for true */
|
||||||
|
public $if;
|
||||||
|
/** @var Expr Expression for false */
|
||||||
|
public $else;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a ternary operator node.
|
* Constructs a ternary operator node.
|
||||||
*
|
*
|
||||||
@ -20,13 +22,13 @@ class Ternary extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $cond, $if, Expr $else, array $attributes = array()) {
|
public function __construct(Expr $cond, $if, Expr $else, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->cond = $cond;
|
||||||
'cond' => $cond,
|
$this->if = $if;
|
||||||
'if' => $if,
|
$this->else = $else;
|
||||||
'else' => $else
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('cond', 'if', 'else');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
*/
|
|
||||||
class UnaryMinus extends Expr
|
class UnaryMinus extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a unary minus node.
|
* Constructs a unary minus node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class UnaryMinus extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $expr, array $attributes = array()) {
|
public function __construct(Expr $expr, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property Expr $expr Expression
|
|
||||||
*/
|
|
||||||
class UnaryPlus extends Expr
|
class UnaryPlus extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var Expr Expression */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a unary plus node.
|
* Constructs a unary plus node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class UnaryPlus extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $expr, array $attributes = array()) {
|
public function __construct(Expr $expr, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->expr = $expr;
|
||||||
'expr' => $expr
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('expr');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property string|Expr $name Name
|
|
||||||
*/
|
|
||||||
class Variable extends Expr
|
class Variable extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var string|Expr Name */
|
||||||
|
public $name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a variable node.
|
* Constructs a variable node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class Variable extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct($name, array $attributes = array()) {
|
public function __construct($name, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->name = $name;
|
||||||
'name' => $name
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('name');
|
||||||
}
|
}
|
||||||
}
|
}
|
26
lib/PhpParser/Node/Expr/YieldFrom.php
Normal file
26
lib/PhpParser/Node/Expr/YieldFrom.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpParser\Node\Expr;
|
||||||
|
|
||||||
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
|
class YieldFrom extends Expr
|
||||||
|
{
|
||||||
|
/** @var Expr Expression to yield from */
|
||||||
|
public $expr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an "yield from" node.
|
||||||
|
*
|
||||||
|
* @param Expr $expr Expression
|
||||||
|
* @param array $attributes Additional attributes
|
||||||
|
*/
|
||||||
|
public function __construct(Expr $expr, array $attributes = array()) {
|
||||||
|
parent::__construct($attributes);
|
||||||
|
$this->expr = $expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSubNodeNames() {
|
||||||
|
return array('expr');
|
||||||
|
}
|
||||||
|
}
|
@ -4,12 +4,13 @@ namespace PhpParser\Node\Expr;
|
|||||||
|
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property null|Expr $value Value expression
|
|
||||||
* @property null|Expr $key Key expression
|
|
||||||
*/
|
|
||||||
class Yield_ extends Expr
|
class Yield_ extends Expr
|
||||||
{
|
{
|
||||||
|
/** @var null|Expr Key expression */
|
||||||
|
public $key;
|
||||||
|
/** @var null|Expr Value expression */
|
||||||
|
public $value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a yield expression node.
|
* Constructs a yield expression node.
|
||||||
*
|
*
|
||||||
@ -18,12 +19,12 @@ class Yield_ extends Expr
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Expr $value = null, Expr $key = null, array $attributes = array()) {
|
public function __construct(Expr $value = null, Expr $key = null, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->key = $key;
|
||||||
'key' => $key,
|
$this->value = $value;
|
||||||
'value' => $value,
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('key', 'value');
|
||||||
}
|
}
|
||||||
}
|
}
|
36
lib/PhpParser/Node/FunctionLike.php
Normal file
36
lib/PhpParser/Node/FunctionLike.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpParser\Node;
|
||||||
|
|
||||||
|
use PhpParser\Node;
|
||||||
|
|
||||||
|
interface FunctionLike extends Node
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Whether to return by reference
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function returnsByRef();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of parameters
|
||||||
|
*
|
||||||
|
* @return Node\Param[]
|
||||||
|
*/
|
||||||
|
public function getParams();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the declared return type or null
|
||||||
|
*
|
||||||
|
* @return null|string|Node\Name
|
||||||
|
*/
|
||||||
|
public function getReturnType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function body
|
||||||
|
*
|
||||||
|
* @return Node\Stmt[]
|
||||||
|
*/
|
||||||
|
public function getStmts();
|
||||||
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node;
|
|||||||
|
|
||||||
use PhpParser\NodeAbstract;
|
use PhpParser\NodeAbstract;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property array $parts Parts of the name
|
|
||||||
*/
|
|
||||||
class Name extends NodeAbstract
|
class Name extends NodeAbstract
|
||||||
{
|
{
|
||||||
|
/** @var string[] Parts of the name */
|
||||||
|
public $parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a name node.
|
* Constructs a name node.
|
||||||
*
|
*
|
||||||
@ -20,12 +20,12 @@ class Name extends NodeAbstract
|
|||||||
$parts = explode('\\', $parts);
|
$parts = explode('\\', $parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->parts = $parts;
|
||||||
'parts' => $parts,
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('parts');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,37 +106,45 @@ class Name extends NodeAbstract
|
|||||||
/**
|
/**
|
||||||
* Sets the whole name.
|
* Sets the whole name.
|
||||||
*
|
*
|
||||||
|
* @deprecated Create a new Name instead, or manually modify the $parts property
|
||||||
|
*
|
||||||
* @param string|array|self $name The name to set the whole name to
|
* @param string|array|self $name The name to set the whole name to
|
||||||
*/
|
*/
|
||||||
public function set($name) {
|
public function set($name) {
|
||||||
$this->parts = $this->prepareName($name);
|
$this->parts = self::prepareName($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepends a name to this name.
|
* Prepends a name to this name.
|
||||||
*
|
*
|
||||||
|
* @deprecated Use Name::concat($name1, $name2) instead
|
||||||
|
*
|
||||||
* @param string|array|self $name Name to prepend
|
* @param string|array|self $name Name to prepend
|
||||||
*/
|
*/
|
||||||
public function prepend($name) {
|
public function prepend($name) {
|
||||||
$this->parts = array_merge($this->prepareName($name), $this->parts);
|
$this->parts = array_merge(self::prepareName($name), $this->parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends a name to this name.
|
* Appends a name to this name.
|
||||||
*
|
*
|
||||||
|
* @deprecated Use Name::concat($name1, $name2) instead
|
||||||
|
*
|
||||||
* @param string|array|self $name Name to append
|
* @param string|array|self $name Name to append
|
||||||
*/
|
*/
|
||||||
public function append($name) {
|
public function append($name) {
|
||||||
$this->parts = array_merge($this->parts, $this->prepareName($name));
|
$this->parts = array_merge($this->parts, self::prepareName($name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the first part of the name.
|
* Sets the first part of the name.
|
||||||
*
|
*
|
||||||
|
* @deprecated Use concat($first, $name->slice(1)) instead
|
||||||
|
*
|
||||||
* @param string|array|self $name The name to set the first part to
|
* @param string|array|self $name The name to set the first part to
|
||||||
*/
|
*/
|
||||||
public function setFirst($name) {
|
public function setFirst($name) {
|
||||||
array_splice($this->parts, 0, 1, $this->prepareName($name));
|
array_splice($this->parts, 0, 1, self::prepareName($name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,7 +153,47 @@ class Name extends NodeAbstract
|
|||||||
* @param string|array|self $name The name to set the last part to
|
* @param string|array|self $name The name to set the last part to
|
||||||
*/
|
*/
|
||||||
public function setLast($name) {
|
public function setLast($name) {
|
||||||
array_splice($this->parts, -1, 1, $this->prepareName($name));
|
array_splice($this->parts, -1, 1, self::prepareName($name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a slice of a name (similar to array_slice).
|
||||||
|
*
|
||||||
|
* This method returns a new instance of the same type as the original and with the same
|
||||||
|
* attributes.
|
||||||
|
*
|
||||||
|
* If the slice is empty, a Name with an empty parts array is returned. While this is
|
||||||
|
* meaningless in itself, it works correctly in conjunction with concat().
|
||||||
|
*
|
||||||
|
* @param int $offset Offset to start the slice at
|
||||||
|
*
|
||||||
|
* @return static Sliced name
|
||||||
|
*/
|
||||||
|
public function slice($offset) {
|
||||||
|
// TODO negative offset and length
|
||||||
|
if ($offset < 0 || $offset > count($this->parts)) {
|
||||||
|
throw new \OutOfBoundsException(sprintf('Offset %d is out of bounds', $offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new static(array_slice($this->parts, $offset), $this->attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatenate two names, yielding a new Name instance.
|
||||||
|
*
|
||||||
|
* The type of the generated instance depends on which class this method is called on, for
|
||||||
|
* example Name\FullyQualified::concat() will yield a Name\FullyQualified instance.
|
||||||
|
*
|
||||||
|
* @param string|array|self $name1 The first name
|
||||||
|
* @param string|array|self $name2 The second name
|
||||||
|
* @param array $attributes Attributes to assign to concatenated name
|
||||||
|
*
|
||||||
|
* @return static Concatenated name
|
||||||
|
*/
|
||||||
|
public static function concat($name1, $name2, array $attributes = []) {
|
||||||
|
return new static(
|
||||||
|
array_merge(self::prepareName($name1), self::prepareName($name2)), $attributes
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,7 +204,7 @@ class Name extends NodeAbstract
|
|||||||
*
|
*
|
||||||
* @return array Prepared name
|
* @return array Prepared name
|
||||||
*/
|
*/
|
||||||
protected function prepareName($name) {
|
private static function prepareName($name) {
|
||||||
if (is_string($name)) {
|
if (is_string($name)) {
|
||||||
return explode('\\', $name);
|
return explode('\\', $name);
|
||||||
} elseif (is_array($name)) {
|
} elseif (is_array($name)) {
|
||||||
|
@ -5,15 +5,19 @@ namespace PhpParser\Node;
|
|||||||
use PhpParser\Error;
|
use PhpParser\Error;
|
||||||
use PhpParser\NodeAbstract;
|
use PhpParser\NodeAbstract;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property null|string|Name $type Typehint
|
|
||||||
* @property bool $byRef Whether is passed by reference
|
|
||||||
* @property bool $variadic Whether this is a variadic argument
|
|
||||||
* @property string $name Name
|
|
||||||
* @property null|Expr $default Default value
|
|
||||||
*/
|
|
||||||
class Param extends NodeAbstract
|
class Param extends NodeAbstract
|
||||||
{
|
{
|
||||||
|
/** @var null|string|Name Typehint */
|
||||||
|
public $type;
|
||||||
|
/** @var bool Whether parameter is passed by reference */
|
||||||
|
public $byRef;
|
||||||
|
/** @var bool Whether this is a variadic argument */
|
||||||
|
public $variadic;
|
||||||
|
/** @var string Name */
|
||||||
|
public $name;
|
||||||
|
/** @var null|Expr Default value */
|
||||||
|
public $default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a parameter node.
|
* Constructs a parameter node.
|
||||||
*
|
*
|
||||||
@ -24,20 +28,20 @@ class Param extends NodeAbstract
|
|||||||
* @param bool $variadic Whether this is a variadic argument
|
* @param bool $variadic Whether this is a variadic argument
|
||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct($name, $default = null, $type = null, $byRef = false, $variadic = false, array $attributes = array()) {
|
public function __construct($name, Expr $default = null, $type = null, $byRef = false, $variadic = false, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->type = $type;
|
||||||
'type' => $type,
|
$this->byRef = $byRef;
|
||||||
'byRef' => $byRef,
|
$this->variadic = $variadic;
|
||||||
'variadic' => $variadic,
|
$this->name = $name;
|
||||||
'name' => $name,
|
$this->default = $default;
|
||||||
'default' => $default,
|
|
||||||
),
|
|
||||||
$attributes
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($variadic && null !== $default) {
|
if ($variadic && null !== $default) {
|
||||||
throw new Error('Variadic parameter cannot have a default value');
|
throw new Error('Variadic parameter cannot have a default value', $default->getAttributes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSubNodeNames() {
|
||||||
|
return array('type', 'byRef', 'variadic', 'name', 'default');
|
||||||
|
}
|
||||||
}
|
}
|
@ -4,24 +4,24 @@ namespace PhpParser\Node\Scalar;
|
|||||||
|
|
||||||
use PhpParser\Node\Scalar;
|
use PhpParser\Node\Scalar;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property float $value Number value
|
|
||||||
*/
|
|
||||||
class DNumber extends Scalar
|
class DNumber extends Scalar
|
||||||
{
|
{
|
||||||
|
/** @var float Number value */
|
||||||
|
public $value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a float number scalar node.
|
* Constructs a float number scalar node.
|
||||||
*
|
*
|
||||||
* @param float $value Value of the number
|
* @param float $value Value of the number
|
||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct($value = 0.0, array $attributes = array()) {
|
public function __construct($value, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->value = $value;
|
||||||
'value' => $value
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('value');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,23 +4,23 @@ namespace PhpParser\Node\Scalar;
|
|||||||
|
|
||||||
use PhpParser\Node\Scalar;
|
use PhpParser\Node\Scalar;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property array $parts Encaps list
|
|
||||||
*/
|
|
||||||
class Encapsed extends Scalar
|
class Encapsed extends Scalar
|
||||||
{
|
{
|
||||||
|
/** @var array Encaps list */
|
||||||
|
public $parts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an encapsed string node.
|
* Constructs an encapsed string node.
|
||||||
*
|
*
|
||||||
* @param array $parts Encaps list
|
* @param array $parts Encaps list
|
||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(array $parts = array(), array $attributes = array()) {
|
public function __construct(array $parts, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->parts = $parts;
|
||||||
'parts' => $parts
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('parts');
|
||||||
}
|
}
|
||||||
}
|
}
|
26
lib/PhpParser/Node/Scalar/EncapsedStringPart.php
Normal file
26
lib/PhpParser/Node/Scalar/EncapsedStringPart.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpParser\Node\Scalar;
|
||||||
|
|
||||||
|
use PhpParser\Node\Scalar;
|
||||||
|
|
||||||
|
class EncapsedStringPart extends Scalar
|
||||||
|
{
|
||||||
|
/** @var string String value */
|
||||||
|
public $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a node representing a string part of an encapsed string.
|
||||||
|
*
|
||||||
|
* @param string $value String value
|
||||||
|
* @param array $attributes Additional attributes
|
||||||
|
*/
|
||||||
|
public function __construct($value, array $attributes = array()) {
|
||||||
|
parent::__construct($attributes);
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSubNodeNames() {
|
||||||
|
return array('value');
|
||||||
|
}
|
||||||
|
}
|
@ -4,24 +4,24 @@ namespace PhpParser\Node\Scalar;
|
|||||||
|
|
||||||
use PhpParser\Node\Scalar;
|
use PhpParser\Node\Scalar;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property int $value Number value
|
|
||||||
*/
|
|
||||||
class LNumber extends Scalar
|
class LNumber extends Scalar
|
||||||
{
|
{
|
||||||
|
/** @var int Number value */
|
||||||
|
public $value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an integer number scalar node.
|
* Constructs an integer number scalar node.
|
||||||
*
|
*
|
||||||
* @param int $value Value of the number
|
* @param int $value Value of the number
|
||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct($value = 0, array $attributes = array()) {
|
public function __construct($value, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->value = $value;
|
||||||
'value' => $value
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('value');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,7 +12,11 @@ abstract class MagicConst extends Scalar
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(array $attributes = array()) {
|
public function __construct(array $attributes = array()) {
|
||||||
parent::__construct(array(), $attributes);
|
parent::__construct($attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSubNodeNames() {
|
||||||
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,119 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace PhpParser\Node\Scalar;
|
|
||||||
|
|
||||||
use PhpParser\Node\Scalar;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @property string $value String value
|
|
||||||
*/
|
|
||||||
class String extends Scalar
|
|
||||||
{
|
|
||||||
protected static $replacements = array(
|
|
||||||
'\\' => '\\',
|
|
||||||
'$' => '$',
|
|
||||||
'n' => "\n",
|
|
||||||
'r' => "\r",
|
|
||||||
't' => "\t",
|
|
||||||
'f' => "\f",
|
|
||||||
'v' => "\v",
|
|
||||||
'e' => "\x1B",
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a string scalar node.
|
|
||||||
*
|
|
||||||
* @param string $value Value of the string
|
|
||||||
* @param array $attributes Additional attributes
|
|
||||||
*/
|
|
||||||
public function __construct($value = '', array $attributes = array()) {
|
|
||||||
parent::__construct(
|
|
||||||
array(
|
|
||||||
'value' => $value
|
|
||||||
),
|
|
||||||
$attributes
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* Parses a string token.
|
|
||||||
*
|
|
||||||
* @param string $str String token content
|
|
||||||
*
|
|
||||||
* @return string The parsed string
|
|
||||||
*/
|
|
||||||
public static function parse($str) {
|
|
||||||
$bLength = 0;
|
|
||||||
if ('b' === $str[0]) {
|
|
||||||
$bLength = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('\'' === $str[$bLength]) {
|
|
||||||
return str_replace(
|
|
||||||
array('\\\\', '\\\''),
|
|
||||||
array( '\\', '\''),
|
|
||||||
substr($str, $bLength + 1, -1)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return self::parseEscapeSequences(substr($str, $bLength + 1, -1), '"');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* Parses escape sequences in strings (all string types apart from single quoted).
|
|
||||||
*
|
|
||||||
* @param string $str String without quotes
|
|
||||||
* @param null|string $quote Quote type
|
|
||||||
*
|
|
||||||
* @return string String with escape sequences parsed
|
|
||||||
*/
|
|
||||||
public static function parseEscapeSequences($str, $quote) {
|
|
||||||
if (null !== $quote) {
|
|
||||||
$str = str_replace('\\' . $quote, $quote, $str);
|
|
||||||
}
|
|
||||||
|
|
||||||
return preg_replace_callback(
|
|
||||||
'~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3})~',
|
|
||||||
array(__CLASS__, 'parseCallback'),
|
|
||||||
$str
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function parseCallback($matches) {
|
|
||||||
$str = $matches[1];
|
|
||||||
|
|
||||||
if (isset(self::$replacements[$str])) {
|
|
||||||
return self::$replacements[$str];
|
|
||||||
} elseif ('x' === $str[0] || 'X' === $str[0]) {
|
|
||||||
return chr(hexdec($str));
|
|
||||||
} else {
|
|
||||||
return chr(octdec($str));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*
|
|
||||||
* Parses a constant doc string.
|
|
||||||
*
|
|
||||||
* @param string $startToken Doc string start token content (<<<SMTHG)
|
|
||||||
* @param string $str String token content
|
|
||||||
*
|
|
||||||
* @return string Parsed string
|
|
||||||
*/
|
|
||||||
public static function parseDocString($startToken, $str) {
|
|
||||||
// strip last newline (thanks tokenizer for sticking it into the string!)
|
|
||||||
$str = preg_replace('~(\r\n|\n|\r)$~', '', $str);
|
|
||||||
|
|
||||||
// nowdoc string
|
|
||||||
if (false !== strpos($startToken, '\'')) {
|
|
||||||
return $str;
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::parseEscapeSequences($str, null);
|
|
||||||
}
|
|
||||||
}
|
|
147
lib/PhpParser/Node/Scalar/String_.php
Normal file
147
lib/PhpParser/Node/Scalar/String_.php
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpParser\Node\Scalar;
|
||||||
|
|
||||||
|
use PhpParser\Error;
|
||||||
|
use PhpParser\Node\Scalar;
|
||||||
|
|
||||||
|
class String_ extends Scalar
|
||||||
|
{
|
||||||
|
/** @var string String value */
|
||||||
|
public $value;
|
||||||
|
|
||||||
|
protected static $replacements = array(
|
||||||
|
'\\' => '\\',
|
||||||
|
'$' => '$',
|
||||||
|
'n' => "\n",
|
||||||
|
'r' => "\r",
|
||||||
|
't' => "\t",
|
||||||
|
'f' => "\f",
|
||||||
|
'v' => "\v",
|
||||||
|
'e' => "\x1B",
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a string scalar node.
|
||||||
|
*
|
||||||
|
* @param string $value Value of the string
|
||||||
|
* @param array $attributes Additional attributes
|
||||||
|
*/
|
||||||
|
public function __construct($value, array $attributes = array()) {
|
||||||
|
parent::__construct($attributes);
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSubNodeNames() {
|
||||||
|
return array('value');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* Parses a string token.
|
||||||
|
*
|
||||||
|
* @param string $str String token content
|
||||||
|
* @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
|
||||||
|
*
|
||||||
|
* @return string The parsed string
|
||||||
|
*/
|
||||||
|
public static function parse($str, $parseUnicodeEscape = true) {
|
||||||
|
$bLength = 0;
|
||||||
|
if ('b' === $str[0]) {
|
||||||
|
$bLength = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('\'' === $str[$bLength]) {
|
||||||
|
return str_replace(
|
||||||
|
array('\\\\', '\\\''),
|
||||||
|
array( '\\', '\''),
|
||||||
|
substr($str, $bLength + 1, -1)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return self::parseEscapeSequences(
|
||||||
|
substr($str, $bLength + 1, -1), '"', $parseUnicodeEscape
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* Parses escape sequences in strings (all string types apart from single quoted).
|
||||||
|
*
|
||||||
|
* @param string $str String without quotes
|
||||||
|
* @param null|string $quote Quote type
|
||||||
|
* @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
|
||||||
|
*
|
||||||
|
* @return string String with escape sequences parsed
|
||||||
|
*/
|
||||||
|
public static function parseEscapeSequences($str, $quote, $parseUnicodeEscape = true) {
|
||||||
|
if (null !== $quote) {
|
||||||
|
$str = str_replace('\\' . $quote, $quote, $str);
|
||||||
|
}
|
||||||
|
|
||||||
|
$extra = '';
|
||||||
|
if ($parseUnicodeEscape) {
|
||||||
|
$extra = '|u\{([0-9a-fA-F]+)\}';
|
||||||
|
}
|
||||||
|
|
||||||
|
return preg_replace_callback(
|
||||||
|
'~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}' . $extra . ')~',
|
||||||
|
function($matches) {
|
||||||
|
$str = $matches[1];
|
||||||
|
|
||||||
|
if (isset(self::$replacements[$str])) {
|
||||||
|
return self::$replacements[$str];
|
||||||
|
} elseif ('x' === $str[0] || 'X' === $str[0]) {
|
||||||
|
return chr(hexdec($str));
|
||||||
|
} elseif ('u' === $str[0]) {
|
||||||
|
return self::codePointToUtf8(hexdec($matches[2]));
|
||||||
|
} else {
|
||||||
|
return chr(octdec($str));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
$str
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function codePointToUtf8($num) {
|
||||||
|
if ($num <= 0x7F) {
|
||||||
|
return chr($num);
|
||||||
|
}
|
||||||
|
if ($num <= 0x7FF) {
|
||||||
|
return chr(($num>>6) + 0xC0) . chr(($num&0x3F) + 0x80);
|
||||||
|
}
|
||||||
|
if ($num <= 0xFFFF) {
|
||||||
|
return chr(($num>>12) + 0xE0) . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80);
|
||||||
|
}
|
||||||
|
if ($num <= 0x1FFFFF) {
|
||||||
|
return chr(($num>>18) + 0xF0) . chr((($num>>12)&0x3F) + 0x80)
|
||||||
|
. chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80);
|
||||||
|
}
|
||||||
|
throw new Error('Invalid UTF-8 codepoint escape sequence: Codepoint too large');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* Parses a constant doc string.
|
||||||
|
*
|
||||||
|
* @param string $startToken Doc string start token content (<<<SMTHG)
|
||||||
|
* @param string $str String token content
|
||||||
|
* @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
|
||||||
|
*
|
||||||
|
* @return string Parsed string
|
||||||
|
*/
|
||||||
|
public static function parseDocString($startToken, $str, $parseUnicodeEscape = true) {
|
||||||
|
// strip last newline (thanks tokenizer for sticking it into the string!)
|
||||||
|
$str = preg_replace('~(\r\n|\n|\r)\z~', '', $str);
|
||||||
|
|
||||||
|
// nowdoc string
|
||||||
|
if (false !== strpos($startToken, '\'')) {
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::parseEscapeSequences($str, null, $parseUnicodeEscape);
|
||||||
|
}
|
||||||
|
}
|
@ -4,11 +4,11 @@ namespace PhpParser\Node\Stmt;
|
|||||||
|
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property null|Node\Expr $num Number of loops to break
|
|
||||||
*/
|
|
||||||
class Break_ extends Node\Stmt
|
class Break_ extends Node\Stmt
|
||||||
{
|
{
|
||||||
|
/** @var null|Node\Expr Number of loops to break */
|
||||||
|
public $num;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a break node.
|
* Constructs a break node.
|
||||||
*
|
*
|
||||||
@ -16,11 +16,11 @@ class Break_ extends Node\Stmt
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct(Node\Expr $num = null, array $attributes = array()) {
|
public function __construct(Node\Expr $num = null, array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->num = $num;
|
||||||
'num' => $num,
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('num');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,12 +4,13 @@ namespace PhpParser\Node\Stmt;
|
|||||||
|
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property null|Node\Expr $cond Condition (null for default)
|
|
||||||
* @property Node[] $stmts Statements
|
|
||||||
*/
|
|
||||||
class Case_ extends Node\Stmt
|
class Case_ extends Node\Stmt
|
||||||
{
|
{
|
||||||
|
/** @var null|Node\Expr $cond Condition (null for default) */
|
||||||
|
public $cond;
|
||||||
|
/** @var Node[] Statements */
|
||||||
|
public $stmts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a case node.
|
* Constructs a case node.
|
||||||
*
|
*
|
||||||
@ -18,12 +19,12 @@ class Case_ extends Node\Stmt
|
|||||||
* @param array $attributes Additional attributes
|
* @param array $attributes Additional attributes
|
||||||
*/
|
*/
|
||||||
public function __construct($cond, array $stmts = array(), array $attributes = array()) {
|
public function __construct($cond, array $stmts = array(), array $attributes = array()) {
|
||||||
parent::__construct(
|
parent::__construct($attributes);
|
||||||
array(
|
$this->cond = $cond;
|
||||||
'cond' => $cond,
|
$this->stmts = $stmts;
|
||||||
'stmts' => $stmts,
|
}
|
||||||
),
|
|
||||||
$attributes
|
public function getSubNodeNames() {
|
||||||
);
|
return array('cond', 'stmts');
|
||||||
}
|
}
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user