Compare commits

...

164 Commits

Author SHA1 Message Date
2b96ab8edc Release PHP-Parser 1.0.0 2014-09-12 14:48:23 +02:00
7503356e03 Fix typos 2014-09-12 14:44:32 +02:00
22ef0de7ef Add migration guide for 0.9 -> 1.0 2014-09-12 14:40:17 +02:00
5d7fec2027 Mention that composer autoload.php will work as well 2014-09-12 13:51:17 +02:00
6423864160 Add Autoloader tests 2014-09-12 13:45:34 +02:00
fd064dac6c Very that node type is valid in XML unserializer 2014-09-12 00:39:59 +02:00
d9bd550414 Fix XML unserializer 2014-09-12 00:37:21 +02:00
94eca2ce44 Remove deprecated Template and TemplateLoader 2014-09-12 00:25:30 +02:00
e65fd664d1 Small docs touchups and typo fixes 2014-09-12 00:21:27 +02:00
7a3789f1a9 Remove "experimental" message 2014-08-31 17:05:11 +02:00
b31f36bf89 Release PHP-Parser 1.0.0 Beta 2 2014-08-31 16:54:25 +02:00
3d583ab19c Update changelog 2014-08-31 16:39:53 +02:00
616be1d0fc Use emulative lexer for < 5.6RC1
Earlier releases come with incorrect tokenizer data for T_POW and
T_POW_EQUAL.
2014-08-31 16:33:41 +02:00
7c81229261 Disable xdebug var_dump in php-parse script 2014-08-31 16:21:21 +02:00
452e1c0180 Add constant dereferencing, a list-minute 5.6 change 2014-08-31 16:14:36 +02:00
31bc022d0d Merge pull request #124 from sasezaki/patch-1
Add PHP 5.6 to .travis.yml
2014-08-30 12:12:32 +02:00
ce1078bc00 add PHP 5.6 to .travis.yml 2014-08-29 00:44:47 +09:00
6d0589d14f Ensure that special class names are unqualified
Replicates the PHP error message
2014-08-11 22:04:52 +02:00
ef121e690c Preserve case of "static" class name 2014-08-11 21:44:50 +02:00
c0340053d1 Fix case sensitivity for special class names 2014-08-11 21:41:54 +02:00
39f323b5ad Fix classname of Class_ in docblock of BuilderFactory 2014-08-11 20:53:18 +02:00
22c76a3da4 Update changelog 2014-07-23 21:35:24 +02:00
a332352dbc Merge branch '0.9' 2014-07-23 21:24:21 +02:00
ef70767475 Release version 0.9.5 2014-07-23 20:24:17 +02:00
1cecf9efc5 Revert change to NodeTraverserInterface
Only add this method in 1.0, to avoid any BC breaks.
2014-07-23 20:21:42 +02:00
1f143393e5 Rewrite namespace handling code
Add a check for disallowed statements between braced namespaces
while at it.
2014-04-21 15:16:00 +02:00
6d1f77132c Move Stmt\Namespace_::postprocess() to parser 2014-04-21 12:30:55 +02:00
2e195d7cb2 Make sure that pretty printer preserves whitespace after <?php 2014-04-21 11:15:33 +02:00
947a897238 Make names in the parser more descriptive
And improve the code a tad bit in general.

I left YY2TBLSTATES and YYNLSTATES around, because I don't fully
understand their role in the action double indexing.
2014-04-20 23:05:51 +02:00
1edbc89749 Use normal properties instead of static ones 2014-04-20 00:34:31 +02:00
0faa844a75 Separate parser code from generated data 2014-04-20 00:19:35 +02:00
3db3ad7d1e Add experimental php-parse script
Script supporting dumping, pretty printing, serializing and resolving
names. Intended to help exploring and debugging the node tree.
2014-04-19 23:14:28 +02:00
4743e9b0b8 Update constant scalar expression support 2014-04-19 22:53:13 +02:00
8499696021 Add note about prettyPrintFile() to docs 2014-04-19 22:30:20 +02:00
e4e56511b9 Merge branch '0.9' 2014-04-19 22:26:35 +02:00
5960ecfc10 Disable xdebug.scream while lexing 2014-04-19 22:26:05 +02:00
c341ab2ecf Make autoloader for new names PSR-0 compliant 2014-04-02 09:44:45 +02:00
c62ffedfca Require file only if file exists
Allows usage of class_exists() on undefined classes.
2014-03-27 15:40:08 +01:00
a6d46c17b1 Release PHP-Parser 1.0.0 Beta 1 2014-03-27 14:12:13 +01:00
fa96086a49 Update changelog 2014-03-27 13:43:42 +01:00
4c06b0919a Merge branch '0.9'
Conflicts:
	lib/PhpParser/Template.php
	lib/PhpParser/TemplateLoader.php
2014-03-27 12:53:24 +01:00
8429157ab5 Deprecate templating functionality
Other projects cover this a lot better.
2014-03-27 12:51:13 +01:00
2605b8319e Added support for autoload $prepend 2014-03-27 12:39:30 +01:00
91f6880734 Improve pretty printing of empty statement lists
The pStmts() method now also includes the leading \n, however only
if the statement list is non-empty.
2014-03-27 12:31:21 +01:00
b3332184cf Minor cleanups to emulative lexer
Be consistent about version numbers. We'll only emulate until
beta1 of a release, as that's the feature freeze release.
2014-03-27 00:01:39 +01:00
1cb6e1407c Fix ** emulation wrt comments 2014-03-26 23:41:06 +01:00
a5e0bbcb62 Support use function/const in name resolver 2014-03-26 23:28:32 +01:00
3b7829b011 Add support for function and constant import (PHP 5.6) 2014-03-26 22:33:45 +01:00
bea89a0bf2 Add support for constant scalar expressions (PHP 5.6) 2014-03-26 21:48:12 +01:00
cda6f575f0 Add support for pow operator (PHP 5.6) 2014-03-26 19:18:16 +01:00
b5bcfa1168 Add support for argument unpacking (PHP 5.6) 2014-03-26 18:42:46 +01:00
96f1151ab2 Add support for variadic parameters (PHP 5.6) 2014-03-26 18:23:30 +01:00
f5be0d30f7 Guarantee that subnodes are always in the right order 2014-03-22 14:49:56 +01:00
c8c233f900 Correctly pretty print negative floats 2014-03-22 14:24:35 +01:00
8c59f41d02 Remove inline Name[] creations
This ensures that the attributes on the Name nodes are correct.
2014-03-22 14:24:33 +01:00
74efea91d1 Merge pull request #96 from Techworker/patch-1
Adjustment to documentation
2014-02-21 18:19:28 +01:00
70077039b4 Add Scalar\MagicConst->getName()
Return magic constant name, e.g. __CLASS__.

Resolves #95.
2014-02-21 18:16:18 +01:00
558087399f Adjustment to documentation 2014-02-19 23:06:39 +01:00
1c8481bff6 Merge branch '0.9'
Conflicts:
	lib/PhpParser/Lexer.php
	lib/PhpParser/Node/Stmt/Class.php
	lib/PhpParser/Node/Stmt/ClassMethod.php
	lib/PhpParser/Node/Stmt/Interface.php
	lib/PhpParser/Node/Stmt/Namespace.php
	lib/PhpParser/Node/Stmt/UseUse.php
	lib/PhpParser/Parser.php
2014-02-12 20:23:12 +01:00
118f28344d Synchronized error messages with native php error messages 2014-02-12 20:19:48 +01:00
523e024ba0 Fix a number of other typos 2014-02-12 17:47:34 +01:00
99e44eb8e1 Merge pull request #94 from llaville/typo-1
Fix path in phpunit.xml.dist
2014-02-12 17:43:44 +01:00
4223e643dc fix typo (see also issue 93 already fixed) 2014-02-12 17:39:57 +01:00
26422257f5 Merge pull request #93 from hason/patch-1
Fix path in rebuildParser.php
2014-02-12 17:36:16 +01:00
d6eac28955 Fixed typo 2014-02-12 14:12:55 +01:00
5cab2a7844 Specify autoloader in composer.json 2014-02-06 21:39:57 +01:00
843aad4382 Fix readme 2014-02-06 20:54:49 +01:00
5e725df892 Update docs to use new names 2014-02-06 20:52:01 +01:00
f82862ec9c Port library to use namespaces, with BC for old names 2014-02-06 20:29:35 +01:00
10e1c1895c Remove 5.2 compatibilty code in some places 2014-02-05 22:37:07 +01:00
0ac054a74f Bump version to 1.0-dev, without PHP 5.2 support 2014-01-26 19:05:00 +01:00
6f36a88993 Ensure no registered error handler will see the 'reset' error 2014-01-24 20:27:42 +01:00
bf9956b634 Merge pull request #86 from GrahamCampbell/travis-tweaks
Run travis tests on hhvm as well
2014-01-20 08:24:18 -08:00
3a5f7d6cae Updated travis.yml 2014-01-20 11:20:54 +00:00
0353c921bd Merge pull request #81 from brikou/Elseif_to_ElseIf
Rename "Elseif" to "ElseIf"
2013-11-27 11:33:56 -08:00
72310dd5a3 s/Elseif/ElseIf/ 2013-11-27 15:05:37 +01:00
7f4ab26732 Fix name resolver (class names are case insensitive) 2013-11-15 20:27:56 +01:00
700847e295 Add NodeTraverser::removeVisitor() 2013-09-28 13:21:30 +02:00
52aa17fa68 Require ext/tokenizer in composer.json 2013-09-27 21:08:51 +02:00
1e5e280ae8 Release PHP-Parser 0.9.4 2013-08-25 19:11:40 +02:00
3d467ca18e Add PHP 5.5 to .travis.yml 2013-08-04 16:15:12 +02:00
c8695a8f56 Remove obsolete item from grammar/README.md 2013-08-04 16:14:44 +02:00
01123ae6af Fix notices when generating expected tokens list (continued)
Forgot to add regenerated parser
2013-07-27 18:50:08 +02:00
09c106d11f Fix notices when generating expected tokens list 2013-07-27 18:48:49 +02:00
77c08a75c9 Fix pretty printing of include expressions 2013-07-27 16:23:27 +02:00
f9c3aa2a22 Improve PrettyPrinter construction perf by not using uniqid
The uniqid function is *very* slow on unix systems. The code has no
particular unique-ness requirements, so the much faster mt_rand()
function is used instead.

Closes PR #65.
2013-07-13 01:03:57 +02:00
5ccf6196d6 Update changelog 2013-05-23 15:17:59 +02:00
12faad529e Add interface builder 2013-05-23 15:14:58 +02:00
c0da1b88b2 Merge pull request #59 from Trismegiste/refactor-adding-an-interface-for-LSP
Adding an interface to the Node Traverser for LSP concern
2013-05-22 14:45:21 -07:00
bc9ab604f6 Merge pull request #58 from fantasticjamieburns/master
Fix typo in doccomment for lcfirst replacement
2013-05-17 08:14:14 -07:00
900a3f3b7c Implementing the interface for PHPParser_NodeTraverser 2013-05-16 15:44:12 +02:00
92df3e5add Adding the interface 2013-05-16 15:43:24 +02:00
ba91348142 Typo fix 2013-05-15 16:48:42 +02:00
8e686ce7a7 PHP-Parser supports PHP 5.5 2013-04-15 20:56:45 +02:00
08f0cde6f9 Add prettyPrintFile() method 2013-04-15 20:53:23 +02:00
5fca55702b Merge pull request #52 from igorw/patch-1
Add branch-alias
2013-03-05 06:42:24 -08:00
dc95f3b425 Add branch-alias
This allows "0.9.*" or "~0.9" to install the dev version, if the
consumer allows for dev versions to be installed.
2013-03-05 12:50:52 +01:00
75ec7a3e78 Looks like I forgot to git add some files... 2013-02-14 21:49:08 +01:00
a249c002dd Add support for ClassName::class (PHP 5.5) 2013-02-14 21:46:58 +01:00
81d20bf10e Pretty print namespaces in semicolon-style if possible 2013-01-15 18:21:42 +01:00
db18906dfc Rename PrettyPrinter_Zend to PrettyPrinter_Default 2013-01-15 17:43:36 +01:00
fbaa1e5fc3 Add information on expected tokens to syntax errors
This now mimics the error messages provided by PHP itself (pre 5.4).
2013-01-15 17:30:14 +01:00
222c9612ab Use RegexIterator in docs (by @lstrojny)
Also fix formatting in changelog and be more specific in a doc comment.
2012-12-21 13:28:35 +01:00
eeb5e899a5 Merge pull request #46 from siwinski/pr-composer-x-bit
Remove composer.json execute bit
2012-12-21 04:20:39 -08:00
01c5b84db5 Removed composer.json execute bit 2012-12-20 22:18:59 -05:00
98ebfc8d54 Release PHP-Parser 0.9.3 2012-11-22 19:54:05 +01:00
9f0e12bfca Update changelog 2012-11-22 19:51:21 +01:00
cdbad02fb2 Fix endAttributes assignment
The end attributes previously were always assigned from the last read token,
which does not necessarily correspond to the last token in the reduced rule.
In particular this occurs if the parser read a new token and based on that
lookahead decided to reduce a rule. The behavior was only correct if the
newly read token was first shifted and then the rule was reduced.

This is fixed by buffering the endAttributes of the new token in a temporary
variable and only assigning them once the token is shifted.
2012-11-20 16:12:19 +01:00
b0c8787406 Merge pull request #43 from nicmart/patch-1
Update BuilderAbstract::normalizeValue() doc comment
2012-11-06 11:12:30 -08:00
2ae2410dbd Merge pull request #40 from fabpot/patch-2
Fixed some typos in the doc
2012-11-06 11:10:08 -08:00
bdb58ada7c Update lib/PHPParser/BuilderAbstract.php
Updated BuilderAbstract::normalizeValue phpdoc description.
2012-11-06 18:28:15 +01:00
efa872692e Fixed some typos in the doc 2012-11-05 17:44:56 +01:00
fc56da59ce Rename pSafe to pNoIndent
Matches the function more closely
2012-10-31 17:50:54 +01:00
df17d62b40 Fix switch formatting
The switch cases were not indented and fall-through cases had an
unnecessary additional newline.

Patch by @pscheit (PR #39).
2012-10-31 17:46:48 +01:00
ac6f221c50 Better prededence and associativity handling in pretty printer
Previously the pretty printer added unnecessary and odd-looking parentheses
when several operators with the same precedence were chained:

    'a' . 'b' . 'c' . 'd' . 'e'
    // was printed as
    'a' . ('b' . ('c' . ('d' . 'e')))

Another issue reported as part of #39 was that assignments inside closures
were wrapped in parentheses:

    function() {
        $a = $b;
    }
    // was printed as
    function() {
        ($a = $b);
    }

This was caused by the automatic precedence handling, which just regarded
the closure as an ordinal nested expression.

With the new system the $predenceMap of PrettyPrinterAbstract contains both
precedence and associativity and there is a new method pPrec() which prints
a node taking precedence and associativity into account.

For simpler usage there are additional function pInfixOp(), pPrefixOp() and
pPostfixOp().

Prints not going through pPrec() do not have any precedence handling (fixing
the closure issue).
2012-10-31 17:34:06 +01:00
759c04db9b Turn rebuildParser.php into a CLI script
The paths are now more generic so it can be run from any directory, not
just grammar/.
2012-10-19 19:11:47 +02:00
9e43acee2c Scalar_String::create() -> Scalar_String::parse()
Directly creating the node isn't necessary anymore, the token only needs
to be parsed. This makes it consistent with the other scalar parsing
methods and removes the need to pass $arguments around.
2012-10-19 15:17:08 +02:00
9d8e13b4a9 Fix Switch subnode order
Not that it makes much of a difference, but could have caused issues with
"out of order" visiting of nodes.
2012-10-19 14:54:56 +02:00
af5d288fb3 Add support for expressions in empty (PHP 5.5)
Apart from the grammar modifications this also renames the Empty subnode
from var to expr. This breaks BC.
2012-09-07 23:42:01 +02:00
f6c1ab6657 Adjust list and yield parsing, update prettyprinter
* nested list()s will now create nested List nodes (instead of just
   nested arrays)
 * yield $k => $v was parsed with key and value swapped. This is now fixed
 * the pretty printer now works with the newly added language constructs
2012-09-07 23:41:59 +02:00
4259b44a84 Add support for constant dereferencing (PHP 5.5)
Examples: "foo"[2], [1, 2, 3][2]
2012-09-07 23:41:58 +02:00
417a8bb07e Add support for yield expressions (PHP 5.5)
This adds a new Yield expression type, with subnodes key and value.
2012-09-07 23:41:57 +02:00
ae3774f0f2 Add support for finally clauses (PHP 5.5)
This adds a new finallyStmts subnode to the TryCatch node. If there is
no finally clause it will be null.
2012-09-07 23:41:56 +02:00
f8f1e17e41 Add support for list() in foreach (PHP 5.5)
Example: foreach ($coords as list($x, $y)) { ... }

This change slightly breaks backwards compatability, as it changes the
node structure for the previously existing `list(...) = $foo` assignments.
Those no longer have a dedicated `AssignList` node; instead they are
parsed as a normal `Assign` node with a `List` as `var`. Similarly the
use in `foreach` will generate a `List` for `valueVar`.
2012-09-07 23:41:55 +02:00
8d218110db Fix some doc comments 2012-09-07 23:41:54 +02:00
a590937fdf Merge pull request #33 from hakre/patch-1
Change to SPDX License Identifier (BSD-3-Clause) for composer
2012-08-07 09:40:19 -07:00
84b23a3eb5 Change to SPDX License Identifier (BSD-3-Clause) for composer
The composer validate command is now supporting SPDX license identifers.
2012-08-07 18:51:11 +03:00
5a947e9843 Fix parsing of $foo =& new Bar;
By-reference assignments of new expressions are now parsed as AssignRef
(instead of just Assign).

Closes issue #31.
2012-07-23 11:36:47 +02:00
a81cccff7f Release PHP-Parser 0.9.2 2012-07-07 22:23:25 +02:00
e90c8f17db Add installation instructions for different methods 2012-07-07 21:34:06 +02:00
25a7b2cbb9 Add note about xdebug.max_nesting_level 2012-07-07 16:43:23 +02:00
eb5991227d Add Class->getMethods() function 2012-07-07 16:24:07 +02:00
4137d7a7a8 Add modifier accessors for ClassMethod etc 2012-07-07 16:08:37 +02:00
4972124468 Fix test failures due to precision differences
Travis 5.2 seems to have changed the float output precision, so a test was
failing. Now the numbers in the expected output are also provided by PHP,
so they should be the same.
2012-06-08 18:19:37 +02:00
44ed30957f Fix two tests which would fail on x64 2012-06-08 18:09:42 +02:00
35ec185558 Make $line argument for Comment optional
Also add setLine() method.
2012-06-08 17:55:35 +02:00
0911b2e1ce Add line number information to comments
Line numbers are stored in the $line property of the PHPParser_Comment
and PHPParser_Comment_Doc classes and can be retrieved with getLine().
2012-06-06 14:33:38 +01:00
3f66b7ecac Update changelog 2012-05-12 14:15:24 +02:00
e16513a0eb Fix parsing of new expressions in parenthesis
The new dereferencing syntaxes (new Foo)->bar and (new Foo)['bar'] were
causing a shift/reduce conflict with the '(' expr ')' rule. When
(new Foo) was encountered (without dereference operators following) the
parser thus threw a parse error.

The fix simply adds a special '(' new_expr ')' rule to expr. This does not
remove the shift/reduce conflict itself, but makes it irrelevant.

This fixes issue #20.
2012-05-12 14:11:10 +02:00
25bbd69919 Improve some formatting 2012-05-12 00:09:53 +02:00
10fc22f518 Replace \N with .
Older PCRE versions (coming with PHP 5.2) don't support \N yet.
2012-05-11 20:38:05 +02:00
93392c82e0 Fix getAttribute signature in Node interface
This fixes a build failure on PHP 5.2.
2012-05-11 18:48:23 +02:00
dab2fd4b7a Fix comment reformatting on Linux
Remove the use of \R (with BSR_ANYCRLF) at two places, as it was causing
problems there.
2012-05-11 18:45:55 +02:00
cc4b8761e4 Update CHANGELOG 2012-05-11 17:58:59 +02:00
4f9dd7b1e2 Add more extensive Lexer component docs 2012-05-11 17:50:50 +02:00
107c7a262c Update docs 2012-05-11 16:44:13 +02:00
81e53ce0ff Insert comments when pretty printing
This changset also adds unit tests for Comments and adds a way to test the
pretty printer.
2012-05-11 16:18:14 +02:00
a824a2aba7 Fix $node->getDocComment()
getDocComment() now returns the last comment (given that it is a doc
comment). setDocComment() no longer exists, as it doesn't make sense
with the comment objects anymore. getAttribute() now returns by reference,
so it also works in reference contexts.
2012-05-06 18:24:26 +02:00
9d96dd1796 Adjust XML unserializer for new comments attribute 2012-05-06 18:12:02 +02:00
603582fe50 Add test coverage for two things 2012-05-06 17:58:31 +02:00
e587e3f4c6 Collect normal comments too, not only doc comments
Comments and doc comments are now saved in the 'comments' attribute, as an
array. The are instances of PHPParser_Comment[_Doc].
2012-05-06 17:49:04 +02:00
dd711f2a04 Generalize the attribute generation for nodes
Now two arrays are fetched from the lexer: $startAttributes and
$endAttributes. When constructing the attributes for a node, the
$startAttributes from the first token of the node and the $endAttributes
of the last token of the node are merged.

Now the end line is saved in the endLine attribute.
2012-05-05 17:34:27 +02:00
5438cc0d69 Add progress indicator for test_old.
I hate waiting for something without seeing at least *some* output.
2012-05-05 12:22:23 +02:00
101a6ddcfc Fix NameResolver to properly copy attributes 2012-05-04 10:18:50 +02:00
2f5ebf7c4d Store line and doc comment as attributes 2012-05-04 10:16:59 +02:00
c3cf3f29bd Adjust test_old to use new Lexer injection method 2012-05-04 10:16:52 +02:00
f66a672dd0 Start refactoring parser skeleton
The yacc parser skeleton with all those odd $yy short names is quite
non-obvious. This commits starts to refactor it a bit, to use more
obvious names and logic.
2012-05-04 10:16:49 +02:00
3701e02d32 Use inject-once approach for lexer
Now the lexer is injected only once when creating the parser. Instead of

    $parser = new PHPParser_Parser;
    $parser->parse(new PHPParser_Lexer($code));
    $parser->parse(new PHPParser_Lexer($code2));

you write:

    $parser = new PHPParser_Parser(new PHPParser_Lexer);
    $parser->parse($code);
    $parser->parse($code2);
2012-05-04 10:16:46 +02:00
271156f941 Fix typo 2012-05-04 10:16:44 +02:00
f33cd97a8d Merge pull request #22 from schmittjoh/resolveCatchType
fixes a bug where catch type was not resolved
2012-05-04 00:45:47 -07:00
3c2e68a354 Merge pull request #21 from ss23/patch-1
Update doc/1_Usage_of_basic_components.markdown
2012-05-04 00:44:47 -07:00
c2c7fdd13d fixes a bug were line number were lost 2012-05-03 23:58:47 -05:00
0dae07af6b fixes a bug where catch type was not resolved 2012-05-03 23:52:39 -05:00
eb05d2b82d Update doc/1_Usage_of_basic_components.markdown 2012-05-04 15:33:48 +12:00
478 changed files with 14113 additions and 10241 deletions

View File

@ -1,6 +1,13 @@
language: php
php:
- 5.2
- 5.3
- 5.4
- 5.3
- 5.4
- 5.5
- 5.6
- hhvm
matrix:
allow_failures:
- php: hhvm
fast_finish: true

View File

@ -1,34 +1,97 @@
Version 0.9.2-dev
Version 1.0.1-dev
-----------------
Nothing yet.
Version 0.9.1 (24.04.2012)
Version 1.0.0 (12.09.2014)
--------------------------
* Add ability to add attributes to nodes:
* [BC] Removed deprecated `Template` and `TemplateLoader` classes.
It is now possible to add attributes to a node using `$node->setAttribute('name', 'value')` and to retrieve them using
`$node->getAttribute('name' [, 'default'])`. Additionally the existance of an attribute can be checked with
`$node->hasAttribute('name')` and all attributes can be returned using `$node->getAttributes()`.
* Fixed XML unserializer to properly work with new namespaced node names.
* Add code generation features: Builders and templates.
Version 1.0.0-beta2 (31.08.2014)
--------------------------------
For more infos, see the [code generation documentation][1].
* [PHP 5.6] Updated support for constant scalar expressions to comply with latest changes. This means that arrays
and array dimension fetches are now supported as well.
* [BC] Don't traverse nodes merged by another visitor:
* [PHP 5.6] Direct array dereferencing of constants is supported now, i.e. both `FOO[0]` and `Foo::BAR[0]` are valid
now.
If a NodeVisitor returns an array of nodes to merge, these will no longer be traversed by all other visitors. This
behavior only caused problems.
* Fixed handling of special class names (`self`, `parent` and `static`) in the name resolver to be case insensitive.
Additionally the name resolver now enforces that special class names are only used as unqualified names, e.g. `\self`
is considered invalid.
* Fix line numbers for some list structures
* Fix XML unserialization of empty nodes
* Fix parsing of integers that overflow into floats
* Fix emulation of NOWDOC and binary floats
* The case of references to the `static` class name is now preserved. Previously `static` was always lowercased,
regardless of the case used in the source code.
Version 0.9.0 (05.01.2012)
--------------------------
* The autoloader now only requires a file if it exists. This allows usages like
`class_exists('PhpParser\NotExistingClass')`.
First version.
* Added experimental `bin/php-parse.php` script, which is intended to help exploring and debugging the node tree.
[1]: https://github.com/nikic/PHP-Parser/blob/master/doc/3_Code_generation.markdown
* Separated the parser implemention (in `lib/PhpParser/ParserAbstract.php`) and the generated data (in
`lib/PhpParser/Parser.php`). Furthermore the parser now uses meaningful variable names and contains comments
explaining their usage.
Version 1.0.0-beta1 (27.03.2014)
--------------------------------
* [BC] PHP-Parser now requires PHP 5.3 or newer to run. It is however still possible to *parse* PHP 5.2 source code,
while running on a newer version.
* [BC] The library has been moved to use namespaces with the `PhpParser` vendor prefix. However, the old names using
underscores are still available as aliases, as such most code should continue running on the new version without
further changes.
However, code performing dispatch operations on `Node::getType()` may be affected by some of the name changes. For
example a `+` node will now return type `Expr_BinaryOp_Plus` instead of `Expr_Plus`. In particular this may affect
custom pretty printers.
Due to conflicts with reserved keywords, some class names now end with an underscore, e.g. `PHPParser_Node_Stmt_Class`
is now `PhpParser\Node\Stmt\Class_`. (But as usual, the old name is still available)
* [PHP 5.6] Added support for the power operator `**` (node `Expr\BinaryOp\Pow`) and the compound power assignment
operator `**=` (node `Expr\AssignOp\Pow`).
* [PHP 5.6] Added support for variadic functions: `Param` nodes now have `variadic` as a boolean subnode.
* [PHP 5.6] Added support for argument unpacking: `Arg` nodes now have `unpack` as a boolean subnode.
* [PHP 5.6] Added support for aliasing of functions and constants. `Stmt\Use_` nodes now have an integral `type`
subnode, which is one of `Stmt\Use_::TYPE_NORMAL` (`use`), `Stmt\Use_::TYPE_FUNCTION` (`use function`) or
`Stmt\Use_::TYPE_CONSTANT` (`use const`).
The `NameResolver` now also supports resolution of such aliases.
* [PHP 5.6] Added support for constant scalar expressions. This means that certain expressions are now allowed as the
initializer for constants, properties, parameters, static variables, etc.
* [BC] Improved pretty printing of empty statements lists, which are now printed as `{\n}` instead of `{\n \n}`.
This changes the behavior of the protected `PrettyPrinterAbstract::pStmts()` method, so custom pretty printing code
making use it of may need to be adjusted.
* Changed the order of some subnodes to be consistent with their order in the sour code. For example `Stmt\If->cond`
will now appear before `Stmt\If->stmts` etc.
* Added `Scalar\MagicConstant->getName()`, which returns the name of the magic constant (e.g. `__CLASS__`).
**The following changes are also included in 0.9.5**:
* [BC] Deprecated `PHPParser_Template` and `PHPParser_TemplateLoader`. This functionality does not belong in the main project
and - as far as I know - nobody is using it.
* Add `NodeTraverser::removeVisitor()` method, which removes a visitor from the node traverser. This also modifies the
corresponding `NodeTraverserInterface`.
* Fix alias resolution in `NameResolver`: Class names are now correctly handled as case-insensitive.
* The undefined variable error, which is used to the lexer to reset the error state, will no longer interfere with
custom error handlers.
---
**This changelog only includes changes from the 1.0 series. For older changes see the [0.9 series changelog][1].**
[1]: https://github.com/nikic/PHP-Parser/blob/0.9/CHANGELOG.md

View File

@ -1,21 +1,18 @@
PHP Parser
==========
This is a PHP 5.4 (and older) parser written in PHP. It's purpose is to simplify static code analysis and
This is a PHP 5.2 to PHP 5.6 parser written in PHP. It's purpose is to simplify static code analysis and
manipulation.
Documentation can be found in the [`doc/`][1] directory.
[**Documentation for version 1.0.x**][doc_master] (stable; for running on PHP >= 5.3).
***Note: This project is experimental, so the API is subject to change.***
[Documentation for version 0.9.x][doc_0_9] (unsupported; for running on PHP 5.2).
In a Nutshell
-------------
Basically, the parser does nothing more than turn some PHP code into an abstract syntax tree. ("nothing
more" is kind of sarcastic here as PHP has a ... uhm, let's just say "not nice" ... grammar, which makes
parsing PHP very hard.)
For example, if you stick this code in the parser:
The parser turns PHP source code into an abstract syntax tree. For example, if you pass the following code into the
parser:
```php
<?php
@ -73,6 +70,7 @@ programming errors or security issues).
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).
So, that's it, in a nutshell. You can find everything else in the [docs][1].
So, that's it, in a nutshell. You can find everything else in the [docs][doc_master].
[1]: https://github.com/nikic/PHP-Parser/tree/master/doc
[doc_0_9]: https://github.com/nikic/PHP-Parser/tree/0.9/doc
[doc_master]: https://github.com/nikic/PHP-Parser/tree/master/doc

121
UPGRADE-1.0.md Normal file
View File

@ -0,0 +1,121 @@
Upgrading from PHP-Parser 0.9 to 1.0
====================================
### PHP version requirements
PHP-Parser now requires PHP 5.3 or newer to run. It is however still possible to *parse* PHP 5.2 source code, while
running on a newer version.
### Move to namespaced names
The library has been moved to use namespaces with the `PhpParser` vendor prefix. However, the old names using
underscores are still available as aliases, as such most code should continue running on the new version without
further changes.
Old (still works, but discouraged):
```php
$parser = new \PHPParser_Parser(new \PHPParser_Lexer_Emulative);
$prettyPrinter = new \PHPParser_PrettyPrinter_Default;
```
New:
```php
$parser = new \PhpParser\Parser(new PhpParser\Lexer\Emulative);
$prettyPrinter = new \PhpParser\PrettyPrinter\Standard;
```
Note that the `PHPParser` prefix was changed to `PhpParser`. While PHP class names are technically case-insensitive,
the autoloader will not be able to load `PHPParser\Parser` or other case variants.
Due to conflicts with reserved keywords, some class names now end with an underscore, e.g. `PHPParser_Node_Stmt_Class`
is now `PhpParser\Node\Stmt\Class_`. (But as usual, the old name is still available.)
### Changes to `Node::getType()`
The `Node::getType()` method continues to return names using underscores instead of namespace separators and also does
not contain the trailing underscore that may be present in the class name. As such its output will not change in many
cases.
However, some node classes have been moved to a different namespace or renamed, which will result in a different
`Node::getType()` output:
```
Expr_AssignBitwiseAnd => Expr_AssignOp_BitwiseAnd
Expr_AssignBitwiseOr => Expr_AssignOp_BitwiseOr
Expr_AssignBitwiseXor => Expr_AssignOp_BitwiseXor
Expr_AssignConcat => Expr_AssignOp_Concat
Expr_AssignDiv => Expr_AssignOp_Div
Expr_AssignMinus => Expr_AssignOp_Minus
Expr_AssignMod => Expr_AssignOp_Mod
Expr_AssignMul => Expr_AssignOp_Mul
Expr_AssignPlus => Expr_AssignOp_Plus
Expr_AssignShiftLeft => Expr_AssignOp_ShiftLeft
Expr_AssignShiftRight => Expr_AssignOp_ShiftRight
Expr_BitwiseAnd => Expr_BinaryOp_BitwiseAnd
Expr_BitwiseOr => Expr_BinaryOp_BitwiseOr
Expr_BitwiseXor => Expr_BinaryOp_BitwiseXor
Expr_BooleanAnd => Expr_BinaryOp_BooleanAnd
Expr_BooleanOr => Expr_BinaryOp_BooleanOr
Expr_Concat => Expr_BinaryOp_Concat
Expr_Div => Expr_BinaryOp_Div
Expr_Equal => Expr_BinaryOp_Equal
Expr_Greater => Expr_BinaryOp_Greater
Expr_GreaterOrEqual => Expr_BinaryOp_GreaterOrEqual
Expr_Identical => Expr_BinaryOp_Identical
Expr_LogicalAnd => Expr_BinaryOp_LogicalAnd
Expr_LogicalOr => Expr_BinaryOp_LogicalOr
Expr_LogicalXor => Expr_BinaryOp_LogicalXor
Expr_Minus => Expr_BinaryOp_Minus
Expr_Mod => Expr_BinaryOp_Mod
Expr_Mul => Expr_BinaryOp_Mul
Expr_NotEqual => Expr_BinaryOp_NotEqual
Expr_NotIdentical => Expr_BinaryOp_NotIdentical
Expr_Plus => Expr_BinaryOp_Plus
Expr_ShiftLeft => Expr_BinaryOp_ShiftLeft
Expr_ShiftRight => Expr_BinaryOp_ShiftRight
Expr_Smaller => Expr_BinaryOp_Smaller
Expr_SmallerOrEqual => Expr_BinaryOp_SmallerOrEqual
Scalar_ClassConst => Scalar_MagicConst_Class
Scalar_DirConst => Scalar_MagicConst_Dir
Scalar_FileConst => Scalar_MagicConst_File
Scalar_FuncConst => Scalar_MagicConst_Function
Scalar_LineConst => Scalar_MagicConst_Line
Scalar_MethodConst => Scalar_MagicConst_Method
Scalar_NSConst => Scalar_MagicConst_Namespace
Scalar_TraitConst => Scalar_MagicConst_Trait
```
These changes may affect custom pretty printers and code comparing the return value of `Node::getType()` to specific
strings.
### Miscellaneous
* The classes `Template` and `TemplateLoader` have been removed. You should use some other [code generation][code_gen]
project built on top of PHP-Parser instead.
* The `PrettyPrinterAbstract::pStmts()` method now emits a leading newline if the statement list is not empty.
Custom pretty printers should remove the explicit newline before `pStmts()` calls.
Old:
```php
public function pStmt_Trait(PHPParser_Node_Stmt_Trait $node) {
return 'trait ' . $node->name
. "\n" . '{' . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
}
```
New:
```php
public function pStmt_Trait(Stmt\Trait_ $node) {
return 'trait ' . $node->name
. "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}';
}
```
[code_gen]: https://github.com/nikic/PHP-Parser/wiki/Projects-using-the-PHP-Parser#code-generation

132
bin/php-parse.php Normal file
View File

@ -0,0 +1,132 @@
<?php
require __DIR__ . '/../lib/bootstrap.php';
ini_set('xdebug.max_nesting_level', 2000);
/* The fancy var_dump function provided by XDebug will cut off the output way too
* early to be of use. */
ini_set('xdebug.overload_var_dump', 0);
list($operations, $files) = parseArgs($argv);
/* Dump nodes by default */
if (empty($operations)) {
$operations[] = 'dump';
}
if (empty($files)) {
showHelp("Must specify at least one file.");
}
$parser = new PhpParser\Parser(new PhpParser\Lexer\Emulative);
$dumper = new PhpParser\NodeDumper;
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
$serializer = new PhpParser\Serializer\XML;
$traverser = new PhpParser\NodeTraverser();
$traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver);
foreach ($files as $file) {
if (!file_exists($file)) {
die("File $file does not exist.\n");
}
echo "====> File $file:\n";
$code = file_get_contents($file);
try {
$stmts = $parser->parse($code);
} catch (PhpParser\Error $e) {
die("==> Parse Error: {$e->getMessage()}\n");
}
foreach ($operations as $operation) {
if ('dump' === $operation) {
echo "==> Node dump:\n";
echo $dumper->dump($stmts), "\n";
} elseif ('pretty-print' === $operation) {
echo "==> Pretty print:\n";
echo $prettyPrinter->prettyPrintFile($stmts), "\n";
} elseif ('serialize-xml' === $operation) {
echo "==> Serialized XML:\n";
echo $serializer->serialize($stmts), "\n";
} elseif ('var-dump' === $operation) {
echo "==> var_dump():\n";
var_dump($stmts);
} elseif ('resolve-names' === $operation) {
echo "==> Resolved names.\n";
$stmts = $traverser->traverse($stmts);
}
}
}
function showHelp($error) {
die($error . "\n\n" .
<<<OUTPUT
Usage:
php php-parse.php [operations] file1.php [file2.php ...]
Operations is a list of the following options (--dump by default):
--dump -d Dump nodes using NodeDumper
--pretty-print -p Pretty print file using PrettyPrinter\Standard
--serialize-xml Serialize nodes using Serializer\XML
--var-dump var_dump() nodes (for exact structure)
--resolve-names -N Resolve names using NodeVisitor\NameResolver
Example:
php php-parse.php -d -p -N -d file.php
Dumps nodes, pretty prints them, then resolves names and dumps them again.
OUTPUT
);
}
function parseArgs($args) {
$operations = array();
$files = array();
array_shift($args);
$parseOptions = true;
foreach ($args as $arg) {
if (!$parseOptions) {
$files[] = $arg;
continue;
}
switch ($arg) {
case '--dump':
case '-d':
$operations[] = 'dump';
break;
case '--pretty-print':
case '-p':
$operations[] = 'pretty-print';
break;
case '--serialize-xml':
$operations[] = 'serialize-xml';
break;
case '--var-dump':
$operations[] = 'var-dump';
break;
case '--resolve-names':
case '-N';
$operations[] = 'resolve-names';
break;
case '--':
$parseOptions = false;
break;
default:
if ($arg[0] === '-') {
showHelp("Invalid operation $arg.");
} else {
$files[] = $arg;
}
}
}
return array($operations, $files);
}

12
composer.json Executable file → Normal file
View File

@ -3,16 +3,22 @@
"description": "A PHP parser written in PHP",
"keywords": ["php", "parser"],
"type": "library",
"license": "BSD",
"license": "BSD-3-Clause",
"authors": [
{
"name": "Nikita Popov"
}
],
"require": {
"php": ">=5.2"
"php": ">=5.3",
"ext-tokenizer": "*"
},
"autoload": {
"psr-0": { "PHPParser": "lib/" }
"files": ["lib/bootstrap.php"]
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
}
}

View File

@ -1,18 +1,18 @@
Introduction
============
This project is a PHP 5.4 (and older) parser **written in PHP itself**.
This project is a PHP 5.2 to PHP 5.6 parser **written in PHP itself**.
What is this for?
-----------------
A parser is useful for [static analysis][0] and manipulation of code and basically any other
A parser is useful for [static analysis][0], manipulation of code and basically any other
application dealing with code programmatically. A parser constructs an [Abstract Syntax Tree][1]
(AST) of the code and thus allows dealing with it in an abstract and robust way.
There are other ways of dealing with source code. One that PHP supports natively is using the
There are other ways of processing source code. One that PHP supports natively is using the
token stream generated by [`token_get_all`][2]. The token stream is much more low level than
the AST and thus has different applications: It allows to also analyize the exact formating of
the AST and thus has different applications: It allows to also analyze the exact formatting of
a file. On the other hand the token stream is much harder to deal with for more complex analysis.
For example an AST abstracts away the fact that in PHP variables can be written as `$foo`, but also
as `$$bar`, `${'foobar'}` or even `${!${''}=barfoo()}`. You don't have to worry about recognizing
@ -21,18 +21,18 @@ 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
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
programmatic PHP code analysis are incidentially PHP developers, not C developers.
programmatic PHP code analysis are incidentally PHP developers, not C developers.
What can it parse?
------------------
The parser uses a PHP 5.4 compliant grammar, which is backwards compatible with at least PHP 5.3 and PHP
5.2 (and maybe older).
The parser uses a PHP 5.6 compliant grammar, which is backwards compatible with all PHP version from PHP 5.2
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
version it runs on), additionally a wrapper for emulating new tokens from 5.3 and 5.4 is provided. This
allows to parse PHP 5.4 source code running on PHP 5.2, for example. This emulation is very hacky and not
yet perfect, but it should work well on any sane code.
version it runs on), additionally a wrapper for emulating new tokens from 5.3, 5.4, 5.5 and 5.6 is provided.
his allows to parse PHP 5.6 source code running on PHP 5.3, for example. This emulation is very hacky and not
perfect, but it should work well on any sane code.
What output does it produce?
----------------------------
@ -56,11 +56,11 @@ array(
)
```
This matches the semantics the program had: An echo statement, which takes two strings as expressions,
This matches the structure of the code: An echo statement, which takes two strings as expressions,
with the values `Hi` and `World!`.
You can also see that the AST does not contain any whitespace or comment information (only doc comments
are saved). So using it for formatting analysis is not possible.
You can also see that the AST does not contain any whitespace information (but most comments are saved).
So using it for formatting analysis is not possible.
What else can it do?
--------------------

View File

@ -0,0 +1,39 @@
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.0"
}
}
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

View File

@ -6,42 +6,60 @@ This document explains how to use the parser, the pretty printer and the node tr
Bootstrapping
-------------
The library needs to register a class autoloader; you can do this either by including the
`bootstrap.php` file:
The library needs to register a class autoloader. You can either use the ''vendor/autoload.php'' file generated by
Composer or by including the bundled `lib/bootstrap.php` file:
```php
<?php
require 'path/to/PHP-Parser/lib/bootstrap.php';
// Or, if you're using Composer:
require 'path/to/vendor/autoload.php';
```
Additionally you may want to set the `xdebug.max_nesting_level` ini option to a higher value:
```php
<?php
ini_set('xdebug.max_nesting_level', 2000);
```
This ensures that there will be no errors when traversing highly nested node trees.
Parsing
-------
Parsing is done by calling the `parse` method of a `PHPParser_Parser` object. The method
expects a `PHPParser_Lexer` instance which itself again expects a PHP source code (including
`<?php` opening tags). If a syntax error is encountered `PHPParser_Error` is thrown, so
this exception should be `catch`ed.
In order to parse some source code you first have to create a `PhpParser\Parser` object, which
needs to be passed a `PhpParser\Lexer` instance:
```php
<?php
$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
you're running on. For example it will allow you to parse PHP 5.6 code while running on PHP 5.3.
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:
```php
<?php
$code = '<?php // some code';
$parser = new PHPParser_Parser;
$parser = new PhpParser\Parser(new PhpParser\Lexer\Emulative);
try {
$stmts = $parser->parse(new PHPParser_Lexer($code));
} catch (PHPParser_Error $e) {
$stmts = $parser->parse($code);
// $stmts is an array of statement nodes
} catch (PhpParser\Error $e) {
echo 'Parse Error: ', $e->getMessage();
}
```
The `parse` method will return an array of statement nodes (`$stmts`).
### Emulative lexer
Instead of `PHPParser_Lexer` one can also use `PHPParser_Lexer_Emulative`. This class will emulate tokens
of newer PHP versions and as such allow parsing PHP 5.4 on PHP 5.2, for example. So if you want to parse
PHP code of newer versions than the one you are running, you should use the emulative lexer.
A parser instance can be reused to parse multiple files.
Node tree
---------
@ -72,81 +90,91 @@ array(
```
Thus `$stmts` will contain an array with only one node, with this node being an instance of
`PHPParser_Node_Stmt_Echo`.
`PhpParser\Node\Stmt\Echo_`.
As PHP is a large language there are approximately 140 different nodes. In order to make work
with them easier they are grouped into three categories:
* `PHPParser_Node_Stmt`s are statement nodes, i.e. language constructs that do not return
* `PhpParser\Node\Stmt`s are statement nodes, i.e. language constructs that do not return
a value and can not occur in an expression. For example a class definition is a statement.
It doesn't return a value and you can't write something like `func(class A {});`.
* `PHPParser_Node_Expr`s are expression nodes, i.e. language constructs that return a value
* `PhpParser\Node\Expr`s are expression nodes, i.e. language constructs that return a value
and thus can occur in other expressions. Examples of expressions are `$var`
(`PHPParser_Node_Expr_Variable`) and `func()` (`PHPParser_Node_Expr_FuncCall`).
* `PHPParser_Node_Scalar`s are nodes representing scalar values, like `'string'`
(`PHPParser_Node_Scalar_String`), `0` (`PHPParser_Node_Scalar_LNumber`) or magic constants
like `__FILE__` (`PHPParser_Node_Scalar_FileConst`). All `PHPParser_Node_Scalar`s extend
`PHPParser_Node_Expr`, as scalars are expressions, too.
* There are some nodes not in either of these groups, for example names (`PHPParser_Node_Name`)
and call arguments (`PHPParser_Node_Arg`).
(`PhpParser\Node\Expr\Variable`) and `func()` (`PhpParser\Node\Expr\FuncCall`).
* `PhpParser\Node\Scalar`s are nodes representing scalar values, like `'string'`
(`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
`PhpParser\Node\Expr`, as scalars are expressions, too.
* There are some nodes not in either of these groups, for example names (`PhpParser\Node\Name`)
and call arguments (`PhpParser\Node\Arg`).
Some node class names have a trailing `_`. This is used whenever the class name would otherwise clash
with a PHP keyword.
Every node has a (possibly zero) number of subnodes. You can access subnodes by writing
`$node->subNodeName`. The `Stmt_Echo` node has only one subnode `exprs`. So in order to access it
in the above example you would write `$stmts[0]->exprs`. If you wanted to access name of the function
`$node->subNodeName`. The `Stmt\Echo_` node has only one subnode `exprs`. So in order to access it
in the above example you would write `$stmts[0]->exprs`. If you wanted to access the name of the function
call, you would write `$stmts[0]->exprs[1]->name`.
All nodes also define a `getType()` method that returns the node type (the type is the class name
without the `PHPParser_Node_` prefix). Additionally there are `getLine()`, which returns the line
the node startet in, and `getDocComment()`, which returns the doc comment above the node (if there
is any), and the respective setters `setLine()` and `setDocComment()`.
All nodes also define a `getType()` method that returns the node type. The type is the class name
without the `PhpParser\Node\` prefix and `\` replaced with `_`. It also does not contain a trailing
`_` for reserved-keyword class names.
It is possible to associate custom metadata with a node using the `setAttribute()` method. This data
can then be retrieved using `hasAttribute()`, `getAttribute()` and `getAttributes()`.
By default the lexer adds the `startLine`, `endLine` and `comments` attributes. `comments` is an array
of `PhpParser\Comment[\Doc]` instances.
The start line can also be accessed using `getLine()`/`setLine()` (instead of `getAttribute('startLine')`).
The last doc comment from the `comments` attribute can be obtained using `getDocComment()`.
Pretty printer
--------------
The pretty printer component compiles the AST back to PHP code. As the parser does not retain formatting
information the formatting is done using a specified scheme. Currently there is only one scheme available,
namely `PHPParser_PrettyPrinter_Zend` (the name "Zend" might be misleading. It does not strictly adhere
to the Zend Coding Standard.)
namely `PhpParser\PrettyPrinter\Standard`.
```php
<?php
$code = "<?php echo 'Hi ', hi\\getTarget();";
$parser = new PHPParser_Parser;
$prettyPrinter = new PHPParser_PrettyPrinter_Zend;
$parser = new PhpParser\Parser(new PhpParser\Lexer);
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
try {
// parse
$stmts = $parser->parse(new PHPParser_Lexer($code));
$stmts = $parser->parse($code);
// change
$stmts[0] // the echo statement
->exprs // sub expressions
[0] // the first of them (the string node)
->value // it's value, i.e. 'Hi '
= 'Hallo '; // change to 'Hallo '
= 'Hello '; // change to 'Hello '
// pretty print
$code = '<?php ' . $prettyPrinter->prettyPrint($stmts);
$code = $prettyPrinter->prettyPrint($stmts);
echo $code;
} catch (PHPParser_Error $e) {
} catch (PhpParser\Error $e) {
echo 'Parse Error: ', $e->getMessage();
}
```
The above code will output:
<?php echo 'Hallo ', hi\getTarget();
<?php echo 'Hello ', hi\getTarget();
As you can see the source code was first parsed using `PHPParser_Parser->parse`, then changed and then
again converted to code using `PHPParser_PrettyPrinter_Zend->prettyPrint`.
As you can see the source code was first parsed using `PhpParser\Parser->parse()`, then changed and then
again converted to code using `PhpParser\PrettyPrinter\Standard->prettyPrint()`.
The `prettyPrint` method pretty prints a statements array. It is also possible to pretty print only a
single expression using `prettyPrintExpr`.
The `prettyPrint()` method pretty prints a statements array. It is also possible to pretty print only a
single expression using `prettyPrintExpr()`.
The `prettyPrintFile()` method can be used to print an entire file. This will include the opening `<?php` tag
and handle inline HTML as the first/last statement more gracefully.
Node traversation
-----------------
@ -157,43 +185,46 @@ Usually you want to change / analyze code in a generic way, where you don't know
going to look like.
For this purpose the parser provides a component for traversing and visiting the node tree. The basic
structure of a program using this `PHPParser_NodeTraverser` looks like this:
structure of a program using this `PhpParser\NodeTraverser` looks like this:
```php
<?php
$code = "<?php // some code";
$parser = new PHPParser_Parser;
$traverser = new PHPParser_NodeTraverser;
$prettyPrinter = new PHPParser_PrettyPrinter_Zend;
$parser = new PhpParser\Parser(new PhpParser\Lexer\Emulative);
$traverser = new PhpParser\NodeTraverser;
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
// add your visitor
$traverser->addVisitor(new MyNodeVisitor);
try {
$code = file_get_contents($fileName);
// parse
$stmts = $parser->parse(new PHPParser_Lexer($code));
$stmts = $parser->parse($code);
// traverse
$stmts = $traverser->traverse($stmts);
// pretty print
$code = '<?php ' . $prettyPrinter->prettyPrint($stmts);
$code = $prettyPrinter->prettyPrintFile($stmts);
echo $code;
} catch (PHPParser_Error $e) {
} catch (PhpParser\Error $e) {
echo 'Parse Error: ', $e->getMessage();
}
```
A same node visitor for this code might look like this:
The corresponding node visitor might look like this:
```php
<?php
class MyNodeVisitor extends PHPParser_NodeVisitorAbstract
use PhpParser\Node;
class MyNodeVisitor extends PhpParser\NodeVisitorAbstract
{
public function leaveNode(PHPParser_Node $node) {
if ($node instanceof PHPParser_Node_Scalar_String) {
public function leaveNode(Node $node) {
if ($node instanceof Node\Scalar\String) {
$node->value = 'foo';
}
}
@ -202,12 +233,12 @@ class MyNodeVisitor extends PHPParser_NodeVisitorAbstract
The above node visitor would change all string literals in the program to `'foo'`.
All visitors must implement the `PHPParser_NodeVisitor` interface, which defined the following four
All visitors must implement the `PhpParser\NodeVisitor` interface, which defines the following four
methods:
public function beforeTraverse(array $nodes);
public function enterNode(PHPParser_Node $node);
public function leaveNode(PHPParser_Node $node);
public function enterNode(PhpParser\Node $node);
public function leaveNode(PhpParser\Node $node);
public function afterTraverse(array $nodes);
The `beforeTraverse` method is called once before the traversal begins and is passed the nodes the
@ -221,11 +252,12 @@ The `enterNode` and `leaveNode` methods are called on every node, the former whe
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
case the current node is not changed. The `leaveNode` method can furthermore return two special
values: If `false` is returned the current node will be removed from the parent array. If an `array`
is returned the current node 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)`.
case the current node is not changed. The `leaveNode` method can additionally return two special
values:
If `false` is returned the current node will be removed from the parent array. If an array is returned
it 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`
class, which will define empty default implementations for all the above methods.
@ -233,7 +265,7 @@ class, which will define empty default implementations for all the above methods
The NameResolver node visitor
-----------------------------
One visitor is already bundled with the package: `PHPParser_NodeVisitor_NameResolver`. This visitor
One visitor is already bundled with the package: `PhpParser\NodeVisitor\NameResolver`. This visitor
helps you work with namespaced code by trying to resolve most names to fully qualified ones.
For example, consider the following code:
@ -264,89 +296,85 @@ We start off with the following base code:
```php
<?php
const IN_DIR = '/some/path';
const OUT_DIR = '/some/other/path';
$inDir = '/some/path';
$outDir = '/some/other/path';
$parser = new PHPParser_Parser;
$traverser = new PHPParser_NodeTraverser;
$prettyPrinter = new PHPParser_PrettyPrinter_Zend;
$parser = new PhpParser\Parser(new PhpParser\Lexer\Emulative);
$traverser = new PhpParser\NodeTraverser;
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
$traverser->addVisitor(new PHPParser_NodeVisitor_NameResolver); // we will need resolved names
$traverser->addVisitor(new NodeVisitor_NamespaceConverter); // our own node visitor
$traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver); // we will need resolved names
$traverser->addVisitor(new NodeVisitor\NamespaceConverter); // our own node visitor
// iterate over all files in the directory
foreach (new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(IN_DIR),
RecursiveIteratorIterator::LEAVES_ONLY)
as $file) {
// only convert .php files
if (!preg_match('~\.php$~', $file)) {
continue;
}
// iterate over all .php files in the directory
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($inDir));
$files = new RegexIterator($files, '/\.php$/');
foreach ($files as $file) {
try {
// read the file that should be converted
$code = file_get_contents($file);
// parse
// use the emulative lexer here, as we are running PHP 5.2 but want to
// parse PHP 5.3
$stmts = $parser->parse(new PHPParser_Lexer_Emulative($code));
$stmts = $parser->parse($code);
// traverse
$stmts = $traverser->traverse($stmts);
// pretty print
$code = '<?php ' . $prettyPrinter->prettyPrint($stmts);
$code = $prettyPrinter->prettyPrintFile($stmts);
// write the converted file to the target directory
file_put_contents(
substr_replace($file->getPathname(), OUT_DIR, 0, strlen(IN_DIR)),
substr_replace($file->getPathname(), $outDir, 0, strlen($inDir)),
$code
);
} catch (PHPParser_Error $e) {
} catch (PhpParser\Error $e) {
echo 'Parse Error: ', $e->getMessage();
}
}
```
Now lets start with the main code, the `NodeVisitor_NamespaceConverter`. One thing it needs to do
Now lets start with the main code, the `NodeVisitor\NamespaceConverter`. One thing it needs to do
is convert `A\\B` style names to `A_B` style ones.
```php
<?php
class NodeVisitor_NamespaceConverter extends PHPParser_NodeVisitorAbstract
use PhpParser\Node;
class NodeVisitor_NamespaceConverter extends PhpParser\NodeVisitorAbstract
{
public function leaveNode(PHPParser_Node $node) {
if ($node instanceof PHPParser_Node_Name) {
return new PHPParser_Node_Name($node->toString('_'));
public function leaveNode(Node $node) {
if ($node instanceof Node\Name) {
return new Node\Name($node->toString('_'));
}
}
}
```
The above code profits from the fact that the `NameResolver` already resolved all names as far as
possible, so we don't need to do that. All the need to create a string with the name parts separated
possible, so we don't need to do that. We only need to create a string with the name parts separated
by underscores instead of backslashes. This is what `$node->toString('_')` does. (If you want to
create a name with backslashes either write `$node->toString()` or `(string) $node`.) Then we create
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
only the shortname (i.e. the last part of the name), but they need to contain the complete class
name:
only the shortname (i.e. the last part of the name), but they need to contain the complete name inclduing
the namespace prefix:
```php
<?php
class NodeVisitor_NamespaceConverter extends PHPParser_NodeVisitorAbstract
use PhpParser\Node;
use PhpParser\Node\Stmt;
class NodeVisitor_NamespaceConverter extends PhpParser\NodeVisitorAbstract
{
public function leaveNode(PHPParser_Node $node) {
if ($node instanceof PHPParser_Node_Name) {
return new PHPParser_Node_Name($node->toString('_'));
} elseif ($node instanceof PHPParser_Node_Stmt_Class
|| $node instanceof PHPParser_Node_Stmt_Interface
|| $node instanceof PHPParser_Node_Stmt_Function) {
public function leaveNode(Node $node) {
if ($node instanceof Node\Name) {
return new Node\Name($node->toString('_'));
} elseif ($node instanceof Stmt\Class_
|| $node instanceof Stmt\Interface_
|| $node instanceof Stmt\Function_) {
$node->name = $node->namespacedName->toString('_');
} elseif ($node instanceof PHPParser_Node_Stmt_Const) {
} elseif ($node instanceof Stmt\Const_) {
foreach ($node->consts as $const) {
$const->name = $const->namespacedName->toString('_');
}
@ -361,23 +389,25 @@ The last thing we need to do is remove the `namespace` and `use` statements:
```php
<?php
class NodeVisitor_NamespaceConverter extends PHPParser_NodeVisitorAbstract
use PhpParser\Node;
use PhpParser\Node\Stmt;
class NodeVisitor_NamespaceConverter extends PhpParser\NodeVisitorAbstract
{
public function leaveNode(PHPParser_Node $node) {
if ($node instanceof PHPParser_Node_Name) {
return new PHPParser_Node_Name($node->toString('_'));
} elseif ($node instanceof PHPParser_Node_Stmt_Class
|| $node instanceof PHPParser_Node_Stmt_Interface
|| $node instanceof PHPParser_Node_Stmt_Function) {
public function leaveNode(Node $node) {
if ($node instanceof Node\Name) {
return new Node\Name($node->toString('_'));
} elseif ($node instanceof Stmt\Class_
|| $node instanceof Stmt\Interface_
|| $node instanceof Stmt\Function_) {
$node->name = $node->namespacedName->toString('_');
} elseif ($node instanceof PHPParser_Node_Stmt_Const) {
} elseif ($node instanceof Stmt\Const_) {
foreach ($node->consts as $const) {
$const->name = $const->namespacedName->toString('_');
}
} elseif ($node instanceof PHPParser_Node_Stmt_Namespace) {
} elseif ($node instanceof Stmt\Namespace_) {
// returning an array merges is into the parent array
return $node->stmts;
} elseif ($node instanceof PHPParser_Node_Stmt_Use) {
} elseif ($node instanceof Stmt\Use_) {
// returning false removed the node altogether
return false;
}

View File

@ -1,265 +0,0 @@
Code generation
===============
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
common structures as well as simple templating support. Both features are described in the following:
Builders
--------
The project provides builders for classes, methods, functions, parameters and properties, which
allow creating node trees with a fluid interface, instead of instantiating all nodes manually.
Here is an example:
```php
<?php
$factory = new PHPParser_BuilderFactory;
$node = $factory->class('SomeClass')
->extend('SomeOtherClass')
->implement('A\Few', 'Interfaces')
->makeAbstract() // ->makeFinal()
->addStmt($factory->method('someMethod')
->makeAbstract() // ->makeFinal()
->addParam($factory->param('someParam')->setTypeHint('SomeClass'))
)
->addStmt($factory->method('anotherMethod')
->makeProtected() // ->makePublic() [default], ->makePrivate()
->addParam($factory->param('someParam')->setDefault('test'))
// it is possible to add manually created nodes
->addStmt(new PHPParser_Node_Expr_Print(new PHPParser_Node_Expr_Variable('someParam')))
)
// properties will be correctly reordered above the methods
->addStmt($factory->property('someProperty')->makeProtected())
->addStmt($factory->property('anotherProperty')->makePrivate()->setDefault(array(1, 2, 3)))
->getNode()
;
$stmts = array($node);
echo $prettyPrinter->prettyPrint($stmts);
```
This will produce the following output with the default pretty printer:
```php
<?php
abstract class SomeClass extends SomeOtherClass implements A\Few, Interfaces
{
protected $someProperty;
private $anotherProperty = array(1, 2, 3);
abstract function someMethod(SomeClass $someParam);
protected function anotherMethod($someParam = 'test')
{
print $someParam;
}
}
```
Templates
---------
Additionally it is possible to generate code from reusable templates.
As an example consider the following template, which defines a general getter/setter sceleton in terms of a property
`__name__` and its `__type__`:
```php
<?php
class GetterSetterTemplate
{
/**
* @var __type__ The __name__
*/
protected $__name__;
/**
* Gets the __name__.
*
* @return __type__ The __name__
*/
public function get__Name__() {
return $this->__name__;
}
/**
* Sets the __name__.
*
* @param __type__ $__name__ The new __name__
*/
public function set__Name__($__name__) {
$this->__name__ = $__name__;
}
}
```
Using this template we can easily create a class with multiple properties and their respective getters and setters:
```php
<?php
// $templateString contains the above template
$template = new PHPParser_Template($parser, $templateString);
// We only have to specify the __name__ placeholder, as the
// capitalized __Name__ placeholder is automatically created
$properties = [
['name' => 'title', 'type' => 'string'],
['name' => 'body', 'type' => 'string'],
['name' => 'author', 'type' => 'User'],
['name' => 'timestamp', 'type' => 'DateTime'],
];
$class = $factory->class('BlogPost')->implement('Post');
foreach ($properties as $propertyPlaceholders) {
$stmts = $template->getStmts($propertyPlaceholders);
$class->addStmts(
// $stmts contains all statements from the template. So [0] fetches the class statement
// and ->stmts retrieves the methods.
$stmts[0]->stmts
);
}
echo $prettyPrinter->prettyPrint(array($class->getNode()));
```
The result would look roughly like this:
```php
<?php
class BlogPost implements Post
{
/**
* @var string The title
*/
protected $title;
/**
* @var string The body
*/
protected $body;
/**
* @var User The author
*/
protected $author;
/**
* @var DateTime The timestamp
*/
protected $timestamp;
/**
* Gets the title.
*
* @return string The title
*/
public function getTitle()
{
return $this->title;
}
/**
* Sets the title.
*
* @param string $title The new title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* Gets the body.
*
* @return string The body
*/
public function getBody()
{
return $this->body;
}
/**
* Sets the body.
*
* @param string $body The new body
*/
public function setBody($body)
{
$this->body = $body;
}
/**
* Gets the author.
*
* @return User The author
*/
public function getAuthor()
{
return $this->author;
}
/**
* Sets the author.
*
* @param User $author The new author
*/
public function setAuthor($author)
{
$this->author = $author;
}
/**
* Gets the timestamp.
*
* @return DateTime The timestamp
*/
public function getTimestamp()
{
return $this->timestamp;
}
/**
* Sets the timestamp.
*
* @param DateTime $timestamp The new timestamp
*/
public function setTimestamp($timestamp)
{
$this->timestamp = $timestamp;
}
}
```
When using multiple templates it is easier to manage them on the filesystem. They can be loaded using the
`TemplateLoader`:
```php
<?php
// We'll store our templates in ./templates and give them a .php suffix
$loader = new PHPParser_TemplateLoader($parser, './templates', '.php');
// loads ./templates/GetterSetter.php
$getterSetterTemplate = $loader->load('GetterSetter');
// loads ./templates/Collection.php
$collectionTemplate = $loader->load('Collection');
// The use of a suffix is optional. The following code for example is equivalent:
$loader = new PHPParser_TemplateLoader($parser, './templates');
// loads ./templates/GetterSetter.php
$getterSetterTemplate = $loader->load('GetterSetter.php');
// loads ./templates/Collection.php
$collectionTemplate = $loader->load('Collection.php');
```

View File

@ -1,7 +1,7 @@
Other node tree representations
===============================
It is possible to convert the AST in several textual representations, which serve different uses.
It is possible to convert the AST into several textual representations, which serve different uses.
Simple serialization
--------------------
@ -13,33 +13,34 @@ but PHP, but it is compact and generates fast. The main application thus is in c
Human readable dumping
----------------------
Furthermore it is possible to dump nodes into a human readable form using the `dump` method of
`PHPParser_NodeDumper`. This can be used for debugging.
Furthermore it is possible to dump nodes into a human readable format using the `dump` method of
`PhpParser\NodeDumper`. This can be used for debugging.
```php
<?php
$code = <<<'CODE'
<?php
function printLine($msg) {
echo $msg, "\n";
}
printLine('Hallo World!!!');
function printLine($msg) {
echo $msg, "\n";
}
printLine('Hello World!!!');
CODE;
$parser = new PHPParser_Parser;
$nodeDumper = new PHPParser_NodeDumper;
$parser = new PhpParser\Parser(new PhpParser\Lexer);
$nodeDumper = new PhpParser\NodeDumper;
try {
$stmts = $parser->parse(new PHPParser_Lexer($code));
$stmts = $parser->parse($code);
echo '<pre>' . htmlspecialchars($nodeDumper->dump($stmts)) . '</pre>';
} catch (PHPParser_Error $e) {
echo $nodeDumper->dump($stmts), "\n";
} catch (PhpParser\Error $e) {
echo 'Parse Error: ', $e->getMessage();
}
```
The above output will have an output looking roughly like this:
The above script will have an output looking roughly like this:
```
array(
@ -77,7 +78,7 @@ array(
args: array(
0: Arg(
value: Scalar_String(
value: Hallo World!!!
value: Hello World!!!
)
byRef: false
)
@ -89,29 +90,30 @@ array(
Serialization to XML
--------------------
It is also possible to serialize the node tree to XML using `PHPParser_Serializer_XML->serialize()`
and to unserialize it using `PHPParser_Unserializer_XML->unserialize()`. This is useful for
It is also possible to serialize the node tree to XML using `PhpParser\Serializer\XML->serialize()`
and to unserialize it using `PhpParser\Unserializer\XML->unserialize()`. This is useful for
interfacing with other languages and applications or for doing transformation using XSLT.
```php
<?php
$code = <<<'CODE'
<?php
function printLine($msg) {
echo $msg, "\n";
}
printLine('Hallo World!!!');
function printLine($msg) {
echo $msg, "\n";
}
printLine('Hello World!!!');
CODE;
$parser = new PHPParser_Parser;
$serializer = new PHPParser_Serializer_XML;
$parser = new PhpParser\Parser(new PhpParser\Lexer);
$serializer = new PhpParser\Serializer\XML;
try {
$stmts = $parser->parse(new PHPParser_Lexer($code));
$stmts = $parser->parse($code);
echo '<pre>' . htmlspecialchars($serializer->serialize($stmts)) . '</pre>';
} catch (PHPParser_Error $e) {
echo $serializer->serialize($stmts);
} catch (PhpParser\Error $e) {
echo 'Parse Error: ', $e->getMessage();
}
```
@ -185,7 +187,7 @@ Produces:
<subNode:value>
<node:Scalar_String line="6">
<subNode:value>
<scalar:string>Hallo World!!!</scalar:string>
<scalar:string>Hello World!!!</scalar:string>
</subNode:value>
</node:Scalar_String>
</subNode:value>

View File

@ -0,0 +1,56 @@
Code generation
===============
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
classes, interfaces, methods, functions, parameters and properties. The builders allow creating node trees using a
fluid interface, instead of instantiating all nodes manually.
Here is an example:
```php
<?php
$factory = new PhpParser\BuilderFactory;
$node = $factory->class('SomeClass')
->extend('SomeOtherClass')
->implement('A\Few', 'Interfaces')
->makeAbstract() // ->makeFinal()
->addStmt($factory->method('someMethod')
->makeAbstract() // ->makeFinal()
->addParam($factory->param('someParam')->setTypeHint('SomeClass'))
)
->addStmt($factory->method('anotherMethod')
->makeProtected() // ->makePublic() [default], ->makePrivate()
->addParam($factory->param('someParam')->setDefault('test'))
// it is possible to add manually created nodes
->addStmt(new PhpParser\Node\Expr\Print_(new PhpParser\Node\Expr\Variable('someParam')))
)
// properties will be correctly reordered above the methods
->addStmt($factory->property('someProperty')->makeProtected())
->addStmt($factory->property('anotherProperty')->makePrivate()->setDefault(array(1, 2, 3)))
->getNode()
;
$stmts = array($node);
echo $prettyPrinter->prettyPrint($stmts);
```
This will produce the following output with the default pretty printer:
```php
<?php
abstract class SomeClass extends SomeOtherClass implements A\Few, Interfaces
{
protected $someProperty;
private $anotherProperty = array(1, 2, 3);
abstract function someMethod(SomeClass $someParam);
protected function anotherMethod($someParam = 'test')
{
print $someParam;
}
}
```

View File

@ -0,0 +1,114 @@
Lexer component documentation
=============================
The lexer is responsible for providing tokens to the parser. The project comes with two lexers: `PhpParser\Lexer` and
`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.
A lexer has to define the following public interface:
startLexing($code);
getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null);
handleHaltCompiler();
startLexing
-----------
The `startLexing` method is invoked when the `parse()` method of the parser is called. It's argument will be whatever
was passed to the `parse()` method.
Even though `startLexing` is meant to accept a source code string, you could for example overwrite it to accept a file:
```php
<?php
class FileLexer extends PhpParser\Lexer {
public function startLexing($fileName) {
if (!file_exists($fileName)) {
throw new InvalidArgumentException(sprintf('File "%s" does not exist', $fileName));
}
parent::startLexing(file_get_contents($fileName));
}
}
$parser = new PhpParser\Parser(new FileLexer);
var_dump($parser->parse('someFile.php'));
var_dump($parser->parse('someOtherFile.php'));
```
getNextToken
------------
`getNextToken` returns the ID of the next token and sets some additional information in the three variables which it
accepts by-ref. If no more tokens are available it must return `0`, which is the ID of the `EOF` token.
The first by-ref variable `$value` should contain the textual content of the token. It is what will be available as `$1`
etc in the parser.
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
class LessAttributesLexer extends PhpParser\Lexer {
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;
}
}
```
You can obviously also add additional attributes. E.g. in conjunction with the above `FileLexer` you might want to add
a `fileName` attribute to all nodes:
```php
<?php
class FileLexer extends PhpParser\Lexer {
protected $fileName;
public function startLexing($fileName) {
if (!file_exists($fileName)) {
throw new InvalidArgumentException(sprintf('File "%s" does not exist', $fileName));
}
$this->fileName = $fileName;
parent::startLexing(file_get_contents($fileName));
}
public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) {
$tokenId = parent::getNextToken($value, $startAttributes, $endAttributes);
// we could use either $startAttributes or $endAttributes here, because the fileName is always the same
// (regardless of whether it is the start or end token). We choose $endAttributes, because it is slightly
// more efficient (as the parser has to keep a stack for the $startAttributes).
$endAttributes['fileName'] = $this->fileName;
return $tokenId;
}
}
```
handleHaltCompiler
------------------
The method is invoked whenever a `T_HALT_COMPILER` token is encountered. It has to return the remaining string after the
construct (not including `();`).

View File

@ -1,7 +1,6 @@
What do all those files mean?
=============================
* `zend_language_parser.y`: Original PHP grammer this parser is based on
* `zend_language_parser.phpy`: PHP grammer written in a pseudo language
* `analyze.php`: Analyzes the `.phpy`-grammer and outputs some info about it
* `rebuildParser.php`: Preprocesses the `.phpy`-grammar and builds the parser using `kmyacc`
@ -14,8 +13,8 @@ The `.phpy` file is a normal grammer in `kmyacc` (`yacc`) style, with some trans
applied to it:
* Nodes are created using the syntax `Name[..., ...]`. This is transformed into
`new PHPParser_Node_Name(..., ..., $line, $docComment)`
* `Name::abc` is transformed to `PHPParser_Node_Name::abc`
`new Node\Name(..., ..., $attributes)`
* `Name::abc` is transformed to `Node\Name::abc`
* 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, ...)`
@ -24,7 +23,7 @@ Building the parser
===================
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` file.
After you compiled/installed it, run the `rebuildParser.php` script.
By default only the Parser.php is built. If you want to build the Parser/Debug.php and the y.output
file you need to call the file with the debug option: `rebuildParser.php?debug`.
By default only the `Parser.php` is built. If you want to additionally build `Parser/Debug.php` and `y.output` run the
script with `--debug`. If you want to retain the preprocessed grammar pass `--keep-tmp-grammar`.

View File

@ -1,294 +1,99 @@
<?php
$meta #
#semval($) $this->yyval
#semval($,%t) $this->yyval
#semval(%n) $this->yyastk[$this->yysp-(%l-%n)]
#semval(%n,%t) $this->yyastk[$this->yysp-(%l-%n)]
#semval($) $this->semValue
#semval($,%t) $this->semValue
#semval(%n) $this->semStack[$this->stackPos-(%l-%n)]
#semval(%n,%t) $this->semStack[$this->stackPos-(%l-%n)]
#include;
namespace PhpParser;
/* This is an automatically GENERATED file, which should not be manually edited.
* Instead edit one of the following:
* * the grammar file grammar/zend_language_parser.phpy
* * the parser skeleton grammar/kymacc.php.parser
* * the skeleton file grammar/kymacc.php.parser
* * the preprocessing script grammar/rebuildParser.php
*
* The skeleton for this parser was written by Moriyoshi Koizumi and is based on
* the work by Masato Bito and is in the PUBLIC DOMAIN.
*/
#if -t
class #(-p)_Debug extends #(-p)
#endif
#ifnot -t
class #(-p)
#endif
class Parser extends ParserAbstract
{
#ifnot -t
const YYBADCH = #(YYBADCH);
const YYMAXLEX = #(YYMAXLEX);
const YYTERMS = #(YYTERMS);
const YYNONTERMS = #(YYNONTERMS);
const YYLAST = #(YYLAST);
const YY2TBLSTATE = #(YY2TBLSTATE);
const YYGLAST = #(YYGLAST);
const YYSTATES = #(YYSTATES);
const YYNLSTATES = #(YYNLSTATES);
const YYINTERRTOK = #(YYINTERRTOK);
const YYUNEXPECTED = #(YYUNEXPECTED);
const YYDEFAULT = #(YYDEFAULT);
protected $tokenToSymbolMapSize = #(YYMAXLEX);
protected $actionTableSize = #(YYLAST);
protected $gotoTableSize = #(YYGLAST);
protected $invalidToken = #(YYBADCH);
protected $defaultAction = #(YYDEFAULT);
protected $unexpectedTokenRule = #(YYUNEXPECTED);
protected $YY2TBLSTATE = #(YY2TBLSTATE);
protected $YYNLSTATES = #(YYNLSTATES);
// {{{ Tokens
#tokenval
const %s = %n;
#endtokenval
// }}}
protected static $yyterminals = array(
protected $symbolToName = array(
#listvar terminals
, "???"
);
protected static $yytranslate = array(
protected $tokenToSymbol = array(
#listvar yytranslate
);
protected static $yyaction = array(
protected $action = array(
#listvar yyaction
);
protected static $yycheck = array(
protected $actionCheck = array(
#listvar yycheck
);
protected static $yybase = array(
protected $actionBase = array(
#listvar yybase
);
protected static $yydefault = array(
protected $actionDefault = array(
#listvar yydefault
);
protected static $yygoto = array(
protected $goto = array(
#listvar yygoto
);
protected static $yygcheck = array(
protected $gotoCheck = array(
#listvar yygcheck
);
protected static $yygbase = array(
protected $gotoBase = array(
#listvar yygbase
);
protected static $yygdefault = array(
protected $gotoDefault = array(
#listvar yygdefault
);
protected static $yylhs = array(
protected $ruleToNonTerminal = array(
#listvar yylhs
);
protected static $yylen = array(
protected $ruleToLength = array(
#listvar yylen
);
protected $yyval;
protected $yyastk;
protected $yysp;
protected $lexer;
#endif
#if -t
protected static $yyproduction = array(
protected $productions = array(
#production-strings;
);
protected function yyprintln($msg) {
echo $msg, "\n";
}
protected function YYTRACE_NEWSTATE($state, $sym) {
$this->yyprintln(
'% State ' . $state
. ', Lookahead ' . ($sym < 0 ? '--none--' : self::$yyterminals[$sym])
);
}
protected function YYTRACE_READ($sym) {
$this->yyprintln('% Reading ' . self::$yyterminals[$sym]);
}
protected function YYTRACE_SHIFT($sym) {
$this->yyprintln('% Shift ' . self::$yyterminals[$sym]);
}
protected function YYTRACE_ACCEPT() {
$this->yyprintln('% Accepted.');
}
protected function YYTRACE_REDUCE($n) {
$this->yyprintln('% Reduce by (' . $n . ') ' . self::$yyproduction[$n]);
}
protected function YYTRACE_POP($state) {
$this->yyprintln('% Recovering, uncovers state ' . $state);
}
protected function YYTRACE_DISCARD($sym) {
$this->yyprintln('% Discard ' . self::$yyterminals[$sym]);
}
#endif
/**
#ifnot -t
* Parses PHP code into a node tree.
#endif
#if -t
* Parses PHP code into a node tree and prints out debugging information.
#endif
*
* @param PHPParser_Lexer $lexer A lexer
*
* @return array Array of statements
*/
public function parse(PHPParser_Lexer $lexer) {
$this->lexer = $lexer;
$this->yysp = 0; // Stack pos
$yysstk = array($yystate = 0); // State stack
$this->yyastk = array(); // AST stack (?)
$yylstk = array($yyline = 1); // Line stack
$yydstk = array($yyDC = null); // Doc comment stack
$yychar = -1;
for (;;) {
#if -t
$this->YYTRACE_NEWSTATE($yystate, $yychar);
#endif
if (self::$yybase[$yystate] == 0) {
$yyn = self::$yydefault[$yystate];
} else {
if ($yychar < 0) {
if (($yychar = $lexer->lex($yylval, $yyline, $yyDC)) < 0)
$yychar = 0;
$yychar = $yychar < self::YYMAXLEX ?
self::$yytranslate[$yychar] : self::YYBADCH;
$yylstk[$this->yysp] = $yyline;
$yydstk[$this->yysp] = $yyDC;
#if -t
$this->YYTRACE_READ($yychar);
#endif
}
if ((($yyn = self::$yybase[$yystate] + $yychar) >= 0
&& $yyn < self::YYLAST && self::$yycheck[$yyn] == $yychar
|| ($yystate < self::YY2TBLSTATE
&& ($yyn = self::$yybase[$yystate + self::YYNLSTATES]
+ $yychar) >= 0
&& $yyn < self::YYLAST
&& self::$yycheck[$yyn] == $yychar))
&& ($yyn = self::$yyaction[$yyn]) != self::YYDEFAULT) {
/*
* >= YYNLSTATE: shift and reduce
* > 0: shift
* = 0: accept
* < 0: reduce
* = -YYUNEXPECTED: error
*/
if ($yyn > 0) {
/* shift */
#if -t
$this->YYTRACE_SHIFT($yychar);
#endif
++$this->yysp;
$yysstk[$this->yysp] = $yystate = $yyn;
$this->yyastk[$this->yysp] = $yylval;
$yylstk[$this->yysp] = $yyline;
$yydstk[$this->yysp] = $yyDC;
$yychar = -1;
if ($yyn < self::YYNLSTATES)
continue;
/* $yyn >= YYNLSTATES means shift-and-reduce */
$yyn -= self::YYNLSTATES;
} else {
$yyn = -$yyn;
}
} else {
$yyn = self::$yydefault[$yystate];
}
}
for (;;) {
/* reduce/error */
if ($yyn == 0) {
/* accept */
#if -t
$this->YYTRACE_ACCEPT();
#endif
return $this->yyval;
} elseif ($yyn != self::YYUNEXPECTED) {
/* reduce */
#if -t
$this->YYTRACE_REDUCE($yyn);
#endif
try {
$this->{'yyn' . $yyn}(
$yylstk[$this->yysp - self::$yylen[$yyn]],
$yydstk[$this->yysp - self::$yylen[$yyn]]
);
} catch (PHPParser_Error $e) {
if (-1 === $e->getRawLine()) {
$e->setRawLine($yyline);
}
throw $e;
}
/* Goto - shift nonterminal */
$this->yysp -= self::$yylen[$yyn];
$yyn = self::$yylhs[$yyn];
if (($yyp = self::$yygbase[$yyn] + $yysstk[$this->yysp]) >= 0
&& $yyp < self::YYGLAST
&& self::$yygcheck[$yyp] == $yyn) {
$yystate = self::$yygoto[$yyp];
} else {
$yystate = self::$yygdefault[$yyn];
}
++$this->yysp;
$yysstk[$this->yysp] = $yystate;
$this->yyastk[$this->yysp] = $this->yyval;
$yylstk[$this->yysp] = $yyline;
$yydstk[$this->yysp] = $yyDC;
} else {
/* error */
throw new PHPParser_Error(
'Unexpected token ' . self::$yyterminals[$yychar],
$yyline
);
}
if ($yystate < self::YYNLSTATES)
break;
/* >= YYNLSTATES means shift-and-reduce */
$yyn = $yystate - self::YYNLSTATES;
}
}
}
#ifnot -t
#reduce
protected function yyn%n($line, $docComment) {
protected function reduceRule%n($attributes) {
%b
}
#noact
protected function yyn%n() {
$this->yyval = $this->yyastk[$this->yysp];
protected function reduceRule%n() {
$this->semValue = $this->semStack[$this->stackPos];
}
#endreduce
#endif
}
#tailcode;

View File

@ -1,8 +1,20 @@
<?php
const GRAMMAR_FILE = './zend_language_parser.phpy';
const TMP_FILE = './tmp_parser.phpy';
const RESULT_FILE = './tmp_parser.php';
$grammarFile = __DIR__ . '/zend_language_parser.phpy';
$skeletonFile = __DIR__ . '/kmyacc.php.parser';
$tmpGrammarFile = __DIR__ . '/tmp_parser.phpy';
$tmpResultFile = __DIR__ . '/tmp_parser.php';
$parserResultFile = __DIR__ . '/../lib/PhpParser/Parser.php';
// check for kmyacc.exe binary in this directory, otherwise fall back to global name
$kmyacc = __DIR__ . '/kmyacc.exe';
if (!file_exists($kmyacc)) {
$kmyacc = 'kmyacc';
}
$options = array_flip($argv);
$optionDebug = isset($options['--debug']);
$optionKeepTmpGrammar = isset($options['--keep-tmp-grammar']);
///////////////////////////////
/// Utility regex constants ///
@ -23,54 +35,40 @@ const ARGS = '\((?<args>[^()]*+(?:\((?&args)\)[^()]*+)*+)\)';
/// Main script ///
///////////////////
echo '<pre>';
echo 'Building temporary preproprocessed grammar file.', "\n";
$grammarCode = file_get_contents(GRAMMAR_FILE);
$grammarCode = file_get_contents($grammarFile);
$grammarCode = resolveConstants($grammarCode);
$grammarCode = resolveNodes($grammarCode);
$grammarCode = resolveMacros($grammarCode);
$grammarCode = resolveArrays($grammarCode);
file_put_contents(TMP_FILE, $grammarCode);
file_put_contents($tmpGrammarFile, $grammarCode);
echo 'Building parser. Output: "',
trim(shell_exec('kmyacc -l -m kmyacc.php.parser -p PHPParser_Parser ' . TMP_FILE . ' 2>&1')),
'"', "\n";
$additionalArgs = $optionDebug ? '-t -v' : '';
rename(RESULT_FILE, '../lib/PHPParser/Parser.php');
echo "Building parser.\n";
$output = trim(shell_exec("$kmyacc $additionalArgs -l -m $skeletonFile $tmpGrammarFile 2>&1"));
echo "Output: \"$output\"\n";
if (isset($_GET['debug'])) {
echo 'Building debug parser. Output: "',
trim(shell_exec('kmyacc -t -v -l -m kmyacc.php.parser -p PHPParser_Parser ' . TMP_FILE . ' 2>&1')),
'"', "\n";
moveFileWithDirCheck($tmpResultFile, $parserResultFile);
if (!is_dir('../lib/PHPParser/Parser')) {
mkdir('../lib/PHPParser/Parser');
}
rename(RESULT_FILE, '../lib/PHPParser/Parser/Debug.php');
if (!$optionKeepTmpGrammar) {
unlink($tmpGrammarFile);
}
unlink(TMP_FILE);
echo 'The following temporary preproprocessed grammar file was used:', "\n", $grammarCode;
echo '</pre>';
///////////////////////////////
/// Preprocessing functions ///
///////////////////////////////
function resolveConstants($code) {
return preg_replace('~[A-Z][a-zA-Z_]++::~', 'PHPParser_Node_$0', $code);
return preg_replace('~[A-Z][a-zA-Z_\\\\]++::~', 'Node\\\\$0', $code);
}
function resolveNodes($code) {
return preg_replace_callback(
'~(?<name>[A-Z][a-zA-Z_]++)\s*' . PARAMS . '~',
'~(?<name>[A-Z][a-zA-Z_\\\\]++)\s*' . PARAMS . '~',
function($matches) {
// recurse
$matches['params'] = resolveNodes($matches['params']);
@ -85,7 +83,7 @@ function resolveNodes($code) {
$paramCode .= $param . ', ';
}
return 'new PHPParser_Node_' . $matches['name'] . '(' . $paramCode . '$line, $docComment)';
return 'new Node\\' . $matches['name'] . '(' . $paramCode . '$attributes)';
},
$code
);
@ -107,7 +105,7 @@ function resolveMacros($code) {
if ('error' == $name) {
assertArgs(1, $args, $name);
return 'throw new PHPParser_Error(' . $args[0] . ')';
return 'throw new Error(' . $args[0] . ')';
}
if ('init' == $name) {
@ -141,13 +139,13 @@ function resolveMacros($code) {
if ('parseEncapsed' == $name) {
assertArgs(2, $args, $name);
return 'foreach (' . $args[0] . ' as &$s) { if (is_string($s)) { $s = PHPParser_Node_Scalar_String::parseEscapeSequences($s, ' . $args[1] . '); } }';
return 'foreach (' . $args[0] . ' as &$s) { if (is_string($s)) { $s = Node\Scalar\String::parseEscapeSequences($s, ' . $args[1] . '); } }';
}
if ('parseEncapsedDoc' == $name) {
assertArgs(1, $args, $name);
return 'foreach (' . $args[0] . ' as &$s) { if (is_string($s)) { $s = PHPParser_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 (is_string($s)) { $s = Node\Scalar\String::parseEscapeSequences($s, null); } } $s = preg_replace(\'~(\r\n|\n|\r)$~\', \'\', $s); if (\'\' === $s) array_pop(' . $args[0] . ');';
}
throw new Exception(sprintf('Unknown macro "%s"', $name));
@ -193,6 +191,14 @@ function resolveArrays($code) {
);
}
function moveFileWithDirCheck($fromPath, $toPath) {
$dir = dirname($toPath);
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
rename($fromPath, $toPath);
}
//////////////////////////////
/// Regex helper functions ///
//////////////////////////////
@ -209,4 +215,4 @@ function magicSplit($regex, $string) {
}
return array_filter($pieces);
}
}

View File

@ -7,7 +7,8 @@
%left T_LOGICAL_XOR
%left T_LOGICAL_AND
%right T_PRINT
%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
%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
@ -22,6 +23,7 @@
%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
@ -63,6 +65,7 @@
%token T_RETURN
%token T_TRY
%token T_CATCH
%token T_FINALLY
%token T_THROW
%token T_USE
%token T_INSTEADOF
@ -104,11 +107,12 @@
%token T_NS_C
%token T_DIR
%token T_NS_SEPARATOR
%token T_ELLIPSIS
%%
start:
top_statement_list { $$ = Stmt_Namespace::postprocess($1); }
top_statement_list { $$ = $this->handleNamespaces($1); }
;
top_statement_list:
@ -116,9 +120,13 @@ top_statement_list:
| /* empty */ { init(); }
;
namespace_name:
namespace_name_parts:
T_STRING { init($1); }
| namespace_name T_NS_SEPARATOR T_STRING { push($1, $3); }
| namespace_name_parts T_NS_SEPARATOR T_STRING { push($1, $3); }
;
namespace_name:
namespace_name_parts { $$ = Name[$1]; }
;
top_statement:
@ -126,12 +134,14 @@ top_statement:
| function_declaration_statement { $$ = $1; }
| class_declaration_statement { $$ = $1; }
| T_HALT_COMPILER
{ $$ = Stmt_HaltCompiler[$this->lexer->handleHaltCompiler()]; }
| T_NAMESPACE namespace_name ';' { $$ = Stmt_Namespace[Name[$2], null]; }
| T_NAMESPACE namespace_name '{' top_statement_list '}' { $$ = Stmt_Namespace[Name[$2], $4]; }
| T_NAMESPACE '{' top_statement_list '}' { $$ = Stmt_Namespace[null, $3]; }
| T_USE use_declarations ';' { $$ = Stmt_Use[$2]; }
| T_CONST constant_declaration_list ';' { $$ = Stmt_Const[$2]; }
{ $$ = 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 T_FUNCTION use_declarations ';' { $$ = Stmt\Use_[$3, Stmt\Use_::TYPE_FUNCTION]; }
| T_USE T_CONST use_declarations ';' { $$ = Stmt\Use_[$3, Stmt\Use_::TYPE_CONSTANT]; }
| T_CONST constant_declaration_list ';' { $$ = Stmt\Const_[$2]; }
;
use_declarations:
@ -140,10 +150,10 @@ use_declarations:
;
use_declaration:
namespace_name { $$ = Stmt_UseUse[Name[$1], null]; }
| namespace_name T_AS T_STRING { $$ = Stmt_UseUse[Name[$1], $3]; }
| T_NS_SEPARATOR namespace_name { $$ = Stmt_UseUse[Name[$2], null]; }
| T_NS_SEPARATOR namespace_name T_AS T_STRING { $$ = Stmt_UseUse[Name[$2], $4]; }
namespace_name { $$ = Stmt\UseUse[$1, null]; }
| namespace_name T_AS T_STRING { $$ = Stmt\UseUse[$1, $3]; }
| T_NS_SEPARATOR namespace_name { $$ = Stmt\UseUse[$2, null]; }
| T_NS_SEPARATOR namespace_name T_AS T_STRING { $$ = Stmt\UseUse[$2, $4]; }
;
constant_declaration_list:
@ -152,7 +162,7 @@ constant_declaration_list:
;
constant_declaration:
T_STRING '=' static_scalar { $$ = Const[$1, $3]; }
T_STRING '=' static_scalar { $$ = Const_[$1, $3]; }
;
inner_statement_list:
@ -164,53 +174,59 @@ inner_statement:
statement { $$ = $1; }
| function_declaration_statement { $$ = $1; }
| class_declaration_statement { $$ = $1; }
| T_HALT_COMPILER { error('__halt_compiler() can only be used from the outermost scope'); }
| T_HALT_COMPILER { error('__HALT_COMPILER() can only be used from the outermost scope'); }
;
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_IF parentheses_expr statement elseif_list else_single
{ $$ = Stmt\If_[$2, [stmts: toArray($3), elseifs: $4, else: $5]]; }
| T_IF parentheses_expr ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';'
{ $$ = Stmt\If_[$2, [stmts: $4, elseifs: $5, else: $6]]; }
| T_WHILE parentheses_expr while_statement { $$ = Stmt\While_[$2, $3]; }
| T_DO statement T_WHILE parentheses_expr ';' { $$ = Stmt\Do_ [$4, 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 ';' { $$ = Stmt_Break[null]; }
| T_BREAK expr ';' { $$ = Stmt_Break[$2]; }
| T_CONTINUE ';' { $$ = Stmt_Continue[null]; }
| T_CONTINUE expr ';' { $$ = Stmt_Continue[$2]; }
| T_RETURN ';' { $$ = Stmt_Return[null]; }
| T_RETURN 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]; }
{ $$ = Stmt\For_[[init: $3, cond: $5, loop: $7, stmts: $9]]; }
| T_SWITCH parentheses_expr switch_case_list { $$ = Stmt\Switch_[$2, $3]; }
| T_BREAK ';' { $$ = Stmt\Break_[null]; }
| T_BREAK expr ';' { $$ = Stmt\Break_[$2]; }
| T_CONTINUE ';' { $$ = Stmt\Continue_[null]; }
| T_CONTINUE expr ';' { $$ = Stmt\Continue_[$2]; }
| T_RETURN ';' { $$ = Stmt\Return_[null]; }
| T_RETURN expr ';' { $$ = Stmt\Return_[$2]; }
| yield_expr ';' { $$ = $1; }
| 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 variable ')' foreach_statement
{ $$ = Stmt_Foreach[$3, $5, [keyVar: null, byRef: false, stmts: $7]]; }
| T_FOREACH '(' expr T_AS '&' variable ')' foreach_statement
{ $$ = Stmt_Foreach[$3, $6, [keyVar: null, byRef: true, stmts: $8]]; }
| T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW optional_ref variable ')' foreach_statement
{ $$ = Stmt_Foreach[$3, $8, [keyVar: $5, byRef: $7, stmts: $10]]; }
| T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt_Declare[$3, $5]; }
| 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]; }
| ';' { $$ = array(); /* means: no statement */ }
| T_TRY '{' inner_statement_list '}' catches { $$ = Stmt_TryCatch[$3, $5]; }
| T_THROW expr ';' { $$ = Stmt_Throw[$2]; }
| T_GOTO T_STRING ';' { $$ = Stmt_Goto[$2]; }
| T_STRING ':' { $$ = Stmt_Label[$1]; }
| 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]; }
;
catches:
catch { init($1); }
/* empty */ { init(); }
| catches catch { push($1, $2); }
;
catch:
T_CATCH '(' name T_VARIABLE ')' '{' inner_statement_list '}'
{ $$ = Stmt_Catch[$3, parseVar($4), $7]; }
{ $$ = Stmt\Catch_[$3, parseVar($4), $7]; }
;
optional_finally:
/* empty */ { $$ = null; }
| T_FINALLY '{' inner_statement_list '}' { $$ = $3; }
;
variables_list:
@ -223,24 +239,29 @@ optional_ref:
| '&' { $$ = true; }
;
optional_ellipsis:
/* empty */ { $$ = false; }
| T_ELLIPSIS { $$ = true; }
;
function_declaration_statement:
T_FUNCTION optional_ref T_STRING '(' parameter_list ')' '{' inner_statement_list '}'
{ $$ = Stmt_Function[$3, [byRef: $2, params: $5, stmts: $8]]; }
{ $$ = Stmt\Function_[$3, [byRef: $2, params: $5, stmts: $8]]; }
;
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]]; }
{ $$ = 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]]; }
{ $$ = Stmt\Interface_[$2, [extends: $3, stmts: $5]]; }
| T_TRAIT T_STRING '{' class_statement_list '}'
{ $$ = Stmt_Trait[$2, $4]; }
{ $$ = 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; }
| T_ABSTRACT T_CLASS { $$ = Stmt\Class_::MODIFIER_ABSTRACT; }
| T_FINAL T_CLASS { $$ = Stmt\Class_::MODIFIER_FINAL; }
;
extends_from:
@ -284,7 +305,7 @@ declare_list:
;
declare_list_element:
T_STRING '=' static_scalar { $$ = Stmt_DeclareDeclare[$1, $3]; }
T_STRING '=' static_scalar { $$ = Stmt\DeclareDeclare[$1, $3]; }
;
switch_case_list:
@ -300,8 +321,8 @@ case_list:
;
case:
T_CASE expr case_separator inner_statement_list { $$ = Stmt_Case[$2, $4]; }
| T_DEFAULT case_separator inner_statement_list { $$ = Stmt_Case[null, $3]; }
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:
@ -320,7 +341,7 @@ elseif_list:
;
elseif:
T_ELSEIF '(' expr ')' statement { $$ = Stmt_ElseIf[$3, toArray($5)]; }
T_ELSEIF parentheses_expr statement { $$ = Stmt\ElseIf_[$2, toArray($3)]; }
;
new_elseif_list:
@ -329,17 +350,23 @@ new_elseif_list:
;
new_elseif:
T_ELSEIF '(' expr ')' ':' inner_statement_list { $$ = Stmt_ElseIf[$3, $6]; }
T_ELSEIF parentheses_expr ':' inner_statement_list { $$ = Stmt\ElseIf_[$2, $4]; }
;
else_single:
/* empty */ { $$ = null; }
| T_ELSE statement { $$ = Stmt_Else[toArray($2)]; }
| T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; }
;
new_else_single:
/* empty */ { $$ = null; }
| T_ELSE ':' inner_statement_list { $$ = Stmt_Else[$3]; }
| 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:
@ -353,10 +380,10 @@ non_empty_parameter_list:
;
parameter:
optional_class_type optional_ref T_VARIABLE
{ $$ = Param[parseVar($3), null, $1, $2]; }
| optional_class_type optional_ref T_VARIABLE '=' static_scalar
{ $$ = Param[parseVar($3), $5, $1, $2]; }
optional_class_type optional_ref optional_ellipsis T_VARIABLE
{ $$ = Param[parseVar($4), null, $1, $2, $3]; }
| optional_class_type optional_ref optional_ellipsis T_VARIABLE '=' static_scalar
{ $$ = Param[parseVar($4), $6, $1, $2, $3]; }
;
optional_class_type:
@ -367,8 +394,9 @@ optional_class_type:
;
argument_list:
non_empty_argument_list { $$ = $1; }
| /* empty */ { $$ = array(); }
'(' ')' { $$ = array(); }
| '(' non_empty_argument_list ')' { $$ = $2; }
| '(' yield_expr ')' { $$ = array(Arg[$2, false, false]); }
;
non_empty_argument_list:
@ -377,8 +405,9 @@ non_empty_argument_list:
;
argument:
expr { $$ = Arg[$1, false]; }
| '&' variable { $$ = Arg[$2, true]; }
expr { $$ = Arg[$1, false, false]; }
| '&' variable { $$ = Arg[$2, true, false]; }
| T_ELLIPSIS expr { $$ = Arg[$2, false, true]; }
;
global_var_list:
@ -387,9 +416,9 @@ global_var_list:
;
global_var:
T_VARIABLE { $$ = Expr_Variable[parseVar($1)]; }
| '$' variable { $$ = Expr_Variable[$2]; }
| '$' '{' expr '}' { $$ = Expr_Variable[$3]; }
T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; }
| '$' variable { $$ = Expr\Variable[$2]; }
| '$' '{' expr '}' { $$ = Expr\Variable[$3]; }
;
static_var_list:
@ -398,8 +427,8 @@ static_var_list:
;
static_var:
T_VARIABLE { $$ = Stmt_StaticVar[parseVar($1), null]; }
| T_VARIABLE '=' static_scalar { $$ = Stmt_StaticVar[parseVar($1), $3]; }
T_VARIABLE { $$ = Stmt\StaticVar[parseVar($1), null]; }
| T_VARIABLE '=' static_scalar { $$ = Stmt\StaticVar[parseVar($1), $3]; }
;
class_statement_list:
@ -408,11 +437,11 @@ class_statement_list:
;
class_statement:
variable_modifiers property_declaration_list ';' { $$ = Stmt_Property[$1, $2]; }
| T_CONST constant_declaration_list ';' { $$ = Stmt_ClassConst[$2]; }
variable_modifiers property_declaration_list ';' { $$ = Stmt\Property[$1, $2]; }
| T_CONST constant_declaration_list ';' { $$ = Stmt\ClassConst[$2]; }
| method_modifiers T_FUNCTION optional_ref T_STRING '(' parameter_list ')' method_body
{ $$ = Stmt_ClassMethod[$4, [type: $1, byRef: $3, params: $6, stmts: $8]]; }
| T_USE name_list trait_adaptations { $$ = Stmt_TraitUse[$2, $3]; }
{ $$ = Stmt\ClassMethod[$4, [type: $1, byRef: $3, params: $6, stmts: $8]]; }
| T_USE name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; }
;
trait_adaptations:
@ -427,13 +456,13 @@ trait_adaptation_list:
trait_adaptation:
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 ';'
{ $$ = 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 ';'
{ $$ = 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 ';'
{ $$ = Stmt_TraitUseAdaptation_Alias[$1[0], $1[1], null, $3]; }
{ $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; }
;
trait_method_reference_fully_qualified:
@ -451,26 +480,26 @@ method_body:
variable_modifiers:
non_empty_member_modifiers { $$ = $1; }
| T_VAR { $$ = Stmt_Class::MODIFIER_PUBLIC; }
| T_VAR { $$ = Stmt\Class_::MODIFIER_PUBLIC; }
;
method_modifiers:
/* empty */ { $$ = Stmt_Class::MODIFIER_PUBLIC; }
/* empty */ { $$ = Stmt\Class_::MODIFIER_PUBLIC; }
| 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; }
| 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; }
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:
@ -479,8 +508,8 @@ property_declaration_list:
;
property_declaration:
T_VARIABLE { $$ = Stmt_PropertyProperty[parseVar($1), null]; }
| T_VARIABLE '=' static_scalar { $$ = Stmt_PropertyProperty[parseVar($1), $3]; }
T_VARIABLE { $$ = Stmt\PropertyProperty[parseVar($1), null]; }
| T_VARIABLE '=' static_scalar { $$ = Stmt\PropertyProperty[parseVar($1), $3]; }
;
expr_list:
@ -495,88 +524,117 @@ for_expr:
expr:
variable { $$ = $1; }
| T_LIST '(' assignment_list ')' '=' expr { $$ = Expr_AssignList[$3, $6]; }
| variable '=' expr { $$ = Expr_Assign[$1, $3]; }
| variable '=' '&' variable { $$ = Expr_AssignRef[$1, $4]; }
| variable '=' '&' new_expr { $$ = Expr_Assign[$1, $4]; } /* reference dropped intentially */
| 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_AssignPlus [$1, $3]; }
| variable T_MINUS_EQUAL expr { $$ = Expr_AssignMinus [$1, $3]; }
| variable T_MUL_EQUAL expr { $$ = Expr_AssignMul [$1, $3]; }
| variable T_DIV_EQUAL expr { $$ = Expr_AssignDiv [$1, $3]; }
| variable T_CONCAT_EQUAL expr { $$ = Expr_AssignConcat [$1, $3]; }
| variable T_MOD_EQUAL expr { $$ = Expr_AssignMod [$1, $3]; }
| variable T_AND_EQUAL expr { $$ = Expr_AssignBitwiseAnd[$1, $3]; }
| variable T_OR_EQUAL expr { $$ = Expr_AssignBitwiseOr [$1, $3]; }
| variable T_XOR_EQUAL expr { $$ = Expr_AssignBitwiseXor[$1, $3]; }
| variable T_SL_EQUAL expr { $$ = Expr_AssignShiftLeft [$1, $3]; }
| variable T_SR_EQUAL expr { $$ = Expr_AssignShiftRight[$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_BooleanOr [$1, $3]; }
| expr T_BOOLEAN_AND expr { $$ = Expr_BooleanAnd[$1, $3]; }
| expr T_LOGICAL_OR expr { $$ = Expr_LogicalOr [$1, $3]; }
| expr T_LOGICAL_AND expr { $$ = Expr_LogicalAnd[$1, $3]; }
| expr T_LOGICAL_XOR expr { $$ = Expr_LogicalXor[$1, $3]; }
| expr '|' expr { $$ = Expr_BitwiseOr [$1, $3]; }
| expr '&' expr { $$ = Expr_BitwiseAnd[$1, $3]; }
| expr '^' expr { $$ = Expr_BitwiseXor[$1, $3]; }
| expr '.' expr { $$ = Expr_Concat [$1, $3]; }
| expr '+' expr { $$ = Expr_Plus [$1, $3]; }
| expr '-' expr { $$ = Expr_Minus [$1, $3]; }
| expr '*' expr { $$ = Expr_Mul [$1, $3]; }
| expr '/' expr { $$ = Expr_Div [$1, $3]; }
| expr '%' expr { $$ = Expr_Mod [$1, $3]; }
| expr T_SL expr { $$ = Expr_ShiftLeft [$1, $3]; }
| expr T_SR expr { $$ = Expr_ShiftRight[$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_Identical [$1, $3]; }
| expr T_IS_NOT_IDENTICAL expr { $$ = Expr_NotIdentical [$1, $3]; }
| expr T_IS_EQUAL expr { $$ = Expr_Equal [$1, $3]; }
| expr T_IS_NOT_EQUAL expr { $$ = Expr_NotEqual [$1, $3]; }
| expr '<' expr { $$ = Expr_Smaller [$1, $3]; }
| expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr_SmallerOrEqual[$1, $3]; }
| expr '>' expr { $$ = Expr_Greater [$1, $3]; }
| expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr_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]; }
| T_ISSET '(' variables_list ')' { $$ = Expr_Isset[$3]; }
| T_EMPTY '(' variable ')' { $$ = 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]; }
| 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 '<' 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]; }
| parentheses_expr { $$ = $1; }
/* we need a separate '(' new_expr ')' rule to avoid problems caused by a s/r conflict */
| '(' new_expr ')' { $$ = $2; }
| expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; }
| expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; }
| 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 parentheses_expr { $$ = Expr\Eval_[$2]; }
| 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; }
| T_ARRAY '(' array_pair_list ')' { $$ = Expr_Array[$3]; }
| '[' array_pair_list ']' { $$ = Expr_Array[$2]; }
| '`' backticks_expr '`' { $$ = Expr_ShellExec[$2]; }
| T_PRINT expr { $$ = Expr_Print[$2]; }
| array_expr { $$ = $1; }
| scalar_dereference { $$ = $1; }
| '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; }
| T_PRINT expr { $$ = Expr\Print_[$2]; }
| T_YIELD { $$ = Expr\Yield_[null, null]; }
| T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars '{' inner_statement_list '}'
{ $$ = Expr_Closure[[static: false, byRef: $2, params: $4, uses: $6, stmts: $8]]; }
{ $$ = Expr\Closure[[static: false, byRef: $2, params: $4, uses: $6, stmts: $8]]; }
| T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars '{' inner_statement_list '}'
{ $$ = Expr_Closure[[static: true, byRef: $3, params: $5, uses: $7, stmts: $9]]; }
{ $$ = Expr\Closure[[static: true, byRef: $3, params: $5, uses: $7, stmts: $9]]; }
;
parentheses_expr:
'(' expr ')' { $$ = $2; }
| '(' yield_expr ')' { $$ = $2; }
;
yield_expr:
T_YIELD expr { $$ = Expr\Yield_[$2, null]; }
| T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; }
;
array_expr:
T_ARRAY '(' array_pair_list ')' { $$ = Expr\Array_[$3]; }
| '[' array_pair_list ']' { $$ = Expr\Array_[$2]; }
;
scalar_dereference:
array_expr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
| T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']'
{ $$ = Expr\ArrayDimFetch[Scalar\String[Scalar\String::parse($1)], $3]; }
| constant '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
| scalar_dereference '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
/* alternative array syntax missing intentionally */
;
new_expr:
T_NEW class_name_reference ctor_arguments { $$ = Expr_New[$2, $3]; }
T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; }
;
lexical_vars:
@ -590,45 +648,45 @@ lexical_var_list:
;
lexical_var:
optional_ref T_VARIABLE { $$ = Expr_ClosureUse[parseVar($2), $1]; }
optional_ref T_VARIABLE { $$ = Expr\ClosureUse[parseVar($2), $1]; }
;
function_call:
name '(' argument_list ')' { $$ = Expr_FuncCall[$1, $3]; }
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' argument_list ')'
{ $$ = Expr_StaticCall[$1, $3, $5]; }
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' '(' argument_list ')'
{ $$ = Expr_StaticCall[$1, $4, $7]; }
| static_property '(' argument_list ')' {
if ($1 instanceof PHPParser_Node_Expr_StaticPropertyFetch) {
$$ = Expr_StaticCall[$1->class, Expr_Variable[$1->name], $3];
} elseif ($1 instanceof PHPParser_Node_Expr_ArrayDimFetch) {
name argument_list { $$ = Expr\FuncCall[$1, $2]; }
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM T_STRING argument_list
{ $$ = Expr\StaticCall[$1, $3, $4]; }
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' argument_list
{ $$ = Expr\StaticCall[$1, $4, $6]; }
| static_property argument_list {
if ($1 instanceof Node\Expr\StaticPropertyFetch) {
$$ = Expr\StaticCall[$1->class, Expr\Variable[$1->name], $2];
} elseif ($1 instanceof Node\Expr\ArrayDimFetch) {
$tmp = $1;
while ($tmp->var instanceof PHPParser_Node_Expr_ArrayDimFetch) {
while ($tmp->var instanceof Node\Expr\ArrayDimFetch) {
$tmp = $tmp->var;
}
$$ = Expr_StaticCall[$tmp->var->class, $1, $3];
$tmp->var = Expr_Variable[$tmp->var->name];
$$ = Expr\StaticCall[$tmp->var->class, $1, $2];
$tmp->var = Expr\Variable[$tmp->var->name];
} else {
throw new Exception;
throw new \Exception;
}
}
| variable_without_objects '(' argument_list ')'
{ $$ = Expr_FuncCall[$1, $3]; }
| function_call '[' dim_offset ']' { $$ = Expr_ArrayDimFetch[$1, $3]; }
| variable_without_objects argument_list
{ $$ = Expr\FuncCall[$1, $2]; }
| function_call '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
/* alternative array syntax missing intentionally */
;
class_name:
T_STATIC { $$ = Name['static']; }
T_STATIC { $$ = Name[$1]; }
| name { $$ = $1; }
;
name:
namespace_name { $$ = Name[$1]; }
| T_NS_SEPARATOR namespace_name { $$ = Name_FullyQualified[$2]; }
| T_NAMESPACE T_NS_SEPARATOR namespace_name { $$ = Name_Relative[$3]; }
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:
@ -648,65 +706,111 @@ class_name_or_var:
object_access_for_dcnr:
| base_variable T_OBJECT_OPERATOR object_property
{ $$ = Expr_PropertyFetch[$1, $3]; }
{ $$ = Expr\PropertyFetch[$1, $3]; }
| object_access_for_dcnr T_OBJECT_OPERATOR object_property
{ $$ = Expr_PropertyFetch[$1, $3]; }
| object_access_for_dcnr '[' dim_offset ']' { $$ = Expr_ArrayDimFetch[$1, $3]; }
| object_access_for_dcnr '{' expr '}' { $$ = Expr_ArrayDimFetch[$1, $3]; }
{ $$ = Expr\PropertyFetch[$1, $3]; }
| object_access_for_dcnr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
| object_access_for_dcnr '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; }
;
exit_expr:
/* empty */ { $$ = null; }
| '(' ')' { $$ = null; }
| '(' expr ')' { $$ = $2; }
| parentheses_expr { $$ = $1; }
;
backticks_expr:
/* empty */ { $$ = array(); }
| T_ENCAPSED_AND_WHITESPACE { $$ = array(Scalar_String::parseEscapeSequences($1, '`')); }
| T_ENCAPSED_AND_WHITESPACE { $$ = array(Scalar\String::parseEscapeSequences($1, '`')); }
| encaps_list { parseEncapsed($1, '`'); $$ = $1; }
;
ctor_arguments:
/* empty */ { $$ = array(); }
| '(' argument_list ')' { $$ = $2; }
| argument_list { $$ = $1; }
;
common_scalar:
T_LNUMBER { $$ = Scalar_LNumber[Scalar_LNumber::parse($1)]; }
| T_DNUMBER { $$ = Scalar_DNumber[Scalar_DNumber::parse($1)]; }
| T_CONSTANT_ENCAPSED_STRING { $$ = Scalar_String::create($1, $line, $docComment); }
| T_LINE { $$ = Scalar_LineConst[]; }
| T_FILE { $$ = Scalar_FileConst[]; }
| T_DIR { $$ = Scalar_DirConst[]; }
| T_CLASS_C { $$ = Scalar_ClassConst[]; }
| T_TRAIT_C { $$ = Scalar_TraitConst[]; }
| T_METHOD_C { $$ = Scalar_MethodConst[]; }
| T_FUNC_C { $$ = Scalar_FuncConst[]; }
| T_NS_C { $$ = Scalar_NSConst[]; }
T_LNUMBER { $$ = Scalar\LNumber[Scalar\LNumber::parse($1)]; }
| T_DNUMBER { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; }
| T_CONSTANT_ENCAPSED_STRING { $$ = Scalar\String[Scalar\String::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_[]; }
| T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC
{ $$ = Scalar_String[Scalar_String::parseDocString($1, $2)]; }
{ $$ = Scalar\String[Scalar\String::parseDocString($1, $2)]; }
| T_START_HEREDOC T_END_HEREDOC
{ $$ = Scalar_String['']; }
| name { $$ = Expr_ConstFetch[$1]; }
{ $$ = Scalar\String['']; }
;
static_scalar: /* compile-time evaluated scalars */
static_scalar:
common_scalar { $$ = $1; }
| class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { $$ = Expr_ClassConstFetch[$1, $3]; }
| '+' static_scalar { $$ = Expr_UnaryPlus[$2]; }
| '-' static_scalar { $$ = Expr_UnaryMinus[$2]; }
| T_ARRAY '(' static_array_pair_list ')' { $$ = Expr_Array[$3]; }
| '[' static_array_pair_list ']' { $$ = Expr_Array[$2]; }
| class_name T_PAAMAYIM_NEKUDOTAYIM class_const_name { $$ = Expr\ClassConstFetch[$1, $3]; }
| name { $$ = Expr\ConstFetch[$1]; }
| T_ARRAY '(' static_array_pair_list ')' { $$ = Expr\Array_[$3]; }
| '[' static_array_pair_list ']' { $$ = Expr\Array_[$2]; }
| static_operation { $$ = $1; }
;
static_operation:
static_scalar T_BOOLEAN_OR static_scalar { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; }
| static_scalar T_BOOLEAN_AND static_scalar { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; }
| static_scalar T_LOGICAL_OR static_scalar { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; }
| static_scalar T_LOGICAL_AND static_scalar { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; }
| static_scalar T_LOGICAL_XOR static_scalar { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; }
| static_scalar '|' static_scalar { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; }
| static_scalar '&' static_scalar { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
| static_scalar '^' static_scalar { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; }
| static_scalar '.' static_scalar { $$ = Expr\BinaryOp\Concat [$1, $3]; }
| static_scalar '+' static_scalar { $$ = Expr\BinaryOp\Plus [$1, $3]; }
| static_scalar '-' static_scalar { $$ = Expr\BinaryOp\Minus [$1, $3]; }
| static_scalar '*' static_scalar { $$ = Expr\BinaryOp\Mul [$1, $3]; }
| static_scalar '/' static_scalar { $$ = Expr\BinaryOp\Div [$1, $3]; }
| static_scalar '%' static_scalar { $$ = Expr\BinaryOp\Mod [$1, $3]; }
| static_scalar T_SL static_scalar { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; }
| static_scalar T_SR static_scalar { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; }
| static_scalar T_POW static_scalar { $$ = Expr\BinaryOp\Pow [$1, $3]; }
| '+' static_scalar %prec T_INC { $$ = Expr\UnaryPlus [$2]; }
| '-' static_scalar %prec T_INC { $$ = Expr\UnaryMinus[$2]; }
| '!' static_scalar { $$ = Expr\BooleanNot[$2]; }
| '~' static_scalar { $$ = Expr\BitwiseNot[$2]; }
| static_scalar T_IS_IDENTICAL static_scalar { $$ = Expr\BinaryOp\Identical [$1, $3]; }
| static_scalar T_IS_NOT_IDENTICAL static_scalar { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; }
| static_scalar T_IS_EQUAL static_scalar { $$ = Expr\BinaryOp\Equal [$1, $3]; }
| static_scalar T_IS_NOT_EQUAL static_scalar { $$ = Expr\BinaryOp\NotEqual [$1, $3]; }
| static_scalar '<' static_scalar { $$ = Expr\BinaryOp\Smaller [$1, $3]; }
| static_scalar T_IS_SMALLER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; }
| static_scalar '>' static_scalar { $$ = Expr\BinaryOp\Greater [$1, $3]; }
| static_scalar T_IS_GREATER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; }
| static_scalar '?' static_scalar ':' static_scalar { $$ = Expr\Ternary[$1, $3, $5]; }
| static_scalar '?' ':' static_scalar { $$ = Expr\Ternary[$1, null, $4]; }
| static_scalar '[' static_scalar ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
| '(' static_scalar ')' { $$ = $2; }
;
constant:
name { $$ = Expr\ConstFetch[$1]; }
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM class_const_name
{ $$ = Expr\ClassConstFetch[$1, $3]; }
;
scalar:
common_scalar { $$ = $1; }
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM T_STRING { $$ = Expr_ClassConstFetch[$1, $3]; }
| constant { $$ = $1; }
| '"' encaps_list '"'
{ parseEncapsed($2, '"'); $$ = Scalar_Encapsed[$2]; }
{ parseEncapsed($2, '"'); $$ = Scalar\Encapsed[$2]; }
| T_START_HEREDOC encaps_list T_END_HEREDOC
{ parseEncapsedDoc($2); $$ = Scalar_Encapsed[$2]; }
{ parseEncapsedDoc($2); $$ = Scalar\Encapsed[$2]; }
;
class_const_name:
T_STRING { $$ = $1; }
| T_CLASS { $$ = 'class'; }
;
static_array_pair_list:
@ -725,8 +829,8 @@ non_empty_static_array_pair_list:
;
static_array_pair:
static_scalar T_DOUBLE_ARROW static_scalar { $$ = Expr_ArrayItem[$3, $1, false]; }
| static_scalar { $$ = Expr_ArrayItem[$1, null, false]; }
static_scalar T_DOUBLE_ARROW static_scalar { $$ = Expr\ArrayItem[$3, $1, false]; }
| static_scalar { $$ = Expr\ArrayItem[$1, null, false]; }
;
variable:
@ -737,19 +841,19 @@ variable:
;
new_expr_array_deref:
'(' new_expr ')' '[' dim_offset ']' { $$ = Expr_ArrayDimFetch[$2, $5]; }
| new_expr_array_deref '[' dim_offset ']' { $$ = Expr_ArrayDimFetch[$1, $3]; }
'(' new_expr ')' '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$2, $5]; }
| new_expr_array_deref '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
/* alternative array syntax missing intentionally */
;
object_access:
variable_or_new_expr T_OBJECT_OPERATOR object_property
{ $$ = Expr_PropertyFetch[$1, $3]; }
| variable_or_new_expr T_OBJECT_OPERATOR object_property '(' argument_list ')'
{ $$ = Expr_MethodCall[$1, $3, $5]; }
| object_access '(' argument_list ')' { $$ = Expr_FuncCall[$1, $3]; }
| object_access '[' dim_offset ']' { $$ = Expr_ArrayDimFetch[$1, $3]; }
| object_access '{' expr '}' { $$ = Expr_ArrayDimFetch[$1, $3]; }
{ $$ = Expr\PropertyFetch[$1, $3]; }
| variable_or_new_expr T_OBJECT_OPERATOR object_property argument_list
{ $$ = Expr\MethodCall[$1, $3, $4]; }
| object_access argument_list { $$ = Expr\FuncCall[$1, $2]; }
| object_access '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
| object_access '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; }
;
variable_or_new_expr:
@ -759,7 +863,7 @@ variable_or_new_expr:
variable_without_objects:
reference_variable { $$ = $1; }
| '$' variable_without_objects { $$ = Expr_Variable[$2]; }
| '$' variable_without_objects { $$ = Expr\Variable[$2]; }
;
base_variable:
@ -769,24 +873,24 @@ base_variable:
static_property:
class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' reference_variable
{ $$ = Expr_StaticPropertyFetch[$1, $4]; }
{ $$ = Expr\StaticPropertyFetch[$1, $4]; }
| static_property_with_arrays { $$ = $1; }
;
static_property_with_arrays:
class_name_or_var T_PAAMAYIM_NEKUDOTAYIM T_VARIABLE
{ $$ = Expr_StaticPropertyFetch[$1, parseVar($3)]; }
{ $$ = Expr\StaticPropertyFetch[$1, parseVar($3)]; }
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' '{' expr '}'
{ $$ = Expr_StaticPropertyFetch[$1, $5]; }
| static_property_with_arrays '[' dim_offset ']' { $$ = Expr_ArrayDimFetch[$1, $3]; }
| static_property_with_arrays '{' expr '}' { $$ = Expr_ArrayDimFetch[$1, $3]; }
{ $$ = Expr\StaticPropertyFetch[$1, $5]; }
| static_property_with_arrays '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
| static_property_with_arrays '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; }
;
reference_variable:
reference_variable '[' dim_offset ']' { $$ = Expr_ArrayDimFetch[$1, $3]; }
| reference_variable '{' expr '}' { $$ = Expr_ArrayDimFetch[$1, $3]; }
| T_VARIABLE { $$ = Expr_Variable[parseVar($1)]; }
| '$' '{' expr '}' { $$ = Expr_Variable[$3]; }
reference_variable '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
| reference_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; }
| T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; }
| '$' '{' expr '}' { $$ = Expr\Variable[$3]; }
;
dim_offset:
@ -800,14 +904,18 @@ object_property:
| variable_without_objects { $$ = $1; }
;
assignment_list:
assignment_list ',' assignment_list_element { push($1, $3); }
| assignment_list_element { init($1); }
list_expr:
T_LIST '(' list_expr_elements ')' { $$ = Expr\List_[$3]; }
;
assignment_list_element:
list_expr_elements:
list_expr_elements ',' list_expr_element { push($1, $3); }
| list_expr_element { init($1); }
;
list_expr_element:
variable { $$ = $1; }
| T_LIST '(' assignment_list ')' { $$ = $3; }
| list_expr { $$ = $1; }
| /* empty */ { $$ = null; }
;
@ -822,10 +930,10 @@ non_empty_array_pair_list:
;
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]; }
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:
@ -836,20 +944,20 @@ encaps_list:
;
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_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]; }
{ $$ = 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)]; }
T_STRING { $$ = Scalar\String[$1]; }
| T_NUM_STRING { $$ = Scalar\String[$1]; }
| T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; }
;
%%

View File

@ -1,33 +0,0 @@
<?php
/**
* @codeCoverageIgnore
*/
class PHPParser_Autoloader
{
/**
* Registers PHPParser_Autoloader as an SPL autoloader.
*/
static public function register()
{
ini_set('unserialize_callback_func', 'spl_autoload_call');
spl_autoload_register(array(__CLASS__, 'autoload'));
}
/**
* Handles autoloading of classes.
*
* @param string $class A class name.
*/
static public function autoload($class)
{
if (0 !== strpos($class, 'PHPParser')) {
return;
}
$file = dirname(dirname(__FILE__)) . '/' . strtr($class, '_', '/') . '.php';
if (is_file($file)) {
require $file;
}
}
}

View File

@ -1,77 +0,0 @@
<?php
/**
* "class" and "function" are reserved keywords, so the methods are defined as _class()
* and _function() in the class and are made available as class() and function() through
* __call() magic.
*
* @method PHPParser_Builder_Class class(string $name) Creates a class builder.
* @method PHPParser_Builder_Function function(string $name) Creates a function builder
*/
class PHPParser_BuilderFactory
{
/**
* Creates a class builder.
*
* @param string $name Name of the class
*
* @return PHPParser_Builder_Class The created class builder
*/
protected function _class($name) {
return new PHPParser_Builder_Class($name);
}
/**
* Creates a method builder.
*
* @param string $name Name of the method
*
* @return PHPParser_Builder_Method The created method builder
*/
public function method($name) {
return new PHPParser_Builder_Method($name);
}
/**
* Creates a parameter builder.
*
* @param string $name Name of the parameter
*
* @return PHPParser_Builder_Param The created parameter builder
*/
public function param($name) {
return new PHPParser_Builder_Param($name);
}
/**
* Creates a property builder.
*
* @param string $name Name of the property
*
* @return PHPParser_Builder_Property The created property builder
*/
public function property($name) {
return new PHPParser_Builder_Property($name);
}
/**
* Creates a function builder.
*
* @param string $name Name of the function
*
* @return PHPParser_Builder_Property The created function builder
*/
protected function _function($name) {
return new PHPParser_Builder_Function($name);
}
public function __call($name, array $args) {
if ('class' === $name) {
return call_user_func_array(array($this, '_class'), $args);
} elseif ('function' === $name) {
return call_user_func_array(array($this, '_function'), $args);
}
throw new LogicException(sprintf('Method "%s" does not exist', $name));
}
}

View File

@ -1,172 +0,0 @@
<?php
class PHPParser_Lexer
{
protected $code;
protected $tokens;
protected $pos;
protected $line;
protected static $tokenMap;
protected static $dropTokens = array(
T_WHITESPACE => 1, T_COMMENT => 1, T_OPEN_TAG => 1
);
/**
* Creates a Lexer.
*
* @param string $code
*
* @throws PHPParser_Error on lexing errors (unterminated comment or unexpected character)
*/
public function __construct($code) {
self::initTokenMap();
$this->resetErrors();
$this->tokens = @token_get_all($code);
$this->handleErrors();
$this->code = $code; // keep the code around for __halt_compiler() handling
$this->pos = -1;
$this->line = 1;
}
protected function resetErrors() {
// clear error_get_last() by forcing an undefined variable error
@$undefinedVariable;
}
protected function handleErrors() {
$error = error_get_last();
if (preg_match(
'~^Unterminated comment starting line ([0-9]+)$~',
$error['message'], $matches
)) {
throw new PHPParser_Error('Unterminated comment', $matches[1]);
}
if (preg_match(
'~^Unexpected character in input: \'(.)\' \(ASCII=([0-9]+)\)~s',
$error['message'], $matches
)) {
throw new PHPParser_Error(sprintf(
'Unexpected character "%s" (ASCII %d)',
$matches[1], $matches[2]
));
}
// PHP cuts error message after null byte, so need special case
if (preg_match('~^Unexpected character in input: \'$~', $error['message'])) {
throw new PHPParser_Error('Unexpected null byte');
}
}
/**
* Returns the next token id.
*
* @param mixed $value Variable to store token content in
* @param mixed $line Variable to store line in
* @param mixed $docComment Variable to store doc comment in
*
* @return int Token id
*/
public function lex(&$value = null, &$line = null, &$docComment = null) {
$docComment = null;
while (isset($this->tokens[++$this->pos])) {
$token = $this->tokens[$this->pos];
if (is_string($token)) {
$line = $this->line;
// bug in token_get_all
if ('b"' === $token) {
$value = 'b"';
return ord('"');
} else {
$value = $token;
return ord($token);
}
} else {
$this->line += substr_count($token[1], "\n");
if (T_DOC_COMMENT === $token[0]) {
$docComment = $token[1];
} elseif (!isset(self::$dropTokens[$token[0]])) {
$value = $token[1];
$line = $token[2];
return self::$tokenMap[$token[0]];
}
}
}
return 0;
}
/**
* Handles __halt_compiler() by returning the text after it.
*
* @return string Remaining text
*/
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 ();
$textAfter = substr($this->code, strlen($textBefore));
// ensure that it is followed by ();
// this simplifies the situation, by not allowing any comments
// in between of the tokens.
if (!preg_match('~\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) {
throw new PHPParser_Error('__halt_compiler must be followed by "();"');
}
// prevent the lexer from returning any further tokens
$this->pos = count($this->tokens);
// return with (); removed
return (string) substr($textAfter, strlen($matches[0])); // (string) converts false to ''
}
/**
* Initializes the token map.
*
* The token map maps the PHP internal token identifiers
* to the identifiers used by the Parser. Additionally it
* maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'.
*/
protected static function initTokenMap() {
if (!self::$tokenMap) {
self::$tokenMap = array();
// 256 is the minimum possible token number, as everything below
// it is an ASCII value
for ($i = 256; $i < 1000; ++$i) {
// T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM
if (T_DOUBLE_COLON === $i) {
self::$tokenMap[$i] = PHPParser_Parser::T_PAAMAYIM_NEKUDOTAYIM;
// T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO
} elseif(T_OPEN_TAG_WITH_ECHO === $i) {
self::$tokenMap[$i] = PHPParser_Parser::T_ECHO;
// T_CLOSE_TAG is equivalent to ';'
} elseif(T_CLOSE_TAG === $i) {
self::$tokenMap[$i] = ord(';');
// and the others can be mapped directly
} elseif ('UNKNOWN' !== ($name = token_name($i))
&& defined($name = 'PHPParser_Parser::' . $name)
) {
self::$tokenMap[$i] = constant($name);
}
}
}
}
}

View File

@ -1,180 +0,0 @@
<?php
/**
* ATTENTION: This code is WRITE-ONLY. Do not try to read it.
*/
class PHPParser_Lexer_Emulative extends PHPParser_Lexer
{
protected static $keywords = array(
// PHP 5.4
'callable' => PHPParser_Parser::T_CALLABLE,
'insteadof' => PHPParser_Parser::T_INSTEADOF,
'trait' => PHPParser_Parser::T_TRAIT,
'__trait__' => PHPParser_Parser::T_TRAIT_C,
// PHP 5.3
'__dir__' => PHPParser_Parser::T_DIR,
'goto' => PHPParser_Parser::T_GOTO,
'namespace' => PHPParser_Parser::T_NAMESPACE,
'__namespace__' => PHPParser_Parser::T_NS_C,
);
protected $inObjectAccess;
public function __construct($code) {
$this->inObjectAccess = false;
// on PHP 5.4 don't do anything
if (version_compare(PHP_VERSION, '5.4.0RC1', '>=')) {
parent::__construct($code);
} else {
$code = $this->preprocessCode($code);
parent::__construct($code);
$this->postprocessTokens();
}
}
/*
* Replaces new features in the code by ~__EMU__{NAME}__{DATA}__~ sequences.
* ~LABEL~ is never valid PHP code, that's why we can (to some degree) safely
* use it here.
* Later when preprocessing the tokens these sequences will either be replaced
* by real tokens or replaced with their original content (e.g. if they occured
* inside a string, i.e. a place where they don't have a special meaning).
*/
protected function preprocessCode($code) {
// binary notation (0b010101101001...)
$code = preg_replace('(\b0b[01]+\b)', '~__EMU__BINARY__$0__~', $code);
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
// namespace separator (backslash not followed by some special characters,
// which are not valid after a NS separator, but would cause problems with
// escape sequence parsing if one would replace the backslash there)
$code = preg_replace('(\\\\(?!["\'`${\\\\]))', '~__EMU__NS__~', $code);
// nowdoc (<<<'ABC'\ncontent\nABC;)
$code = preg_replace_callback(
'((*BSR_ANYCRLF) # set \R to (?>\r\n|\r|\n)
(b?<<<[\t ]*\'([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\'\R) # opening token
((?:(?!\2;?\R).*\R)*) # content
(\2) # closing token
(?=;?\R) # must be followed by newline (with optional semicolon)
)x',
array($this, 'encodeNowdocCallback'),
$code
);
}
return $code;
}
/*
* As nowdocs can have arbitrary content but LABELs can only contain a certain
* range of characters, the nowdoc content is encoded as hex and separated by
* 'x' tokens. So the result of the encoding will look like this:
* ~__EMU__NOWDOC__{HEX(START_TOKEN)}x{HEX(CONTENT)}x{HEX(END_TOKEN)}~
*/
public function encodeNowdocCallback(array $matches) {
return '~__EMU__NOWDOC__'
. bin2hex($matches[1]) . 'x' . bin2hex($matches[3]) . 'x' . bin2hex($matches[4])
. '__~';
}
/*
* Replaces the ~__EMU__...~ sequences with real tokens or their original
* value.
*/
protected function postprocessTokens() {
// we need to manually iterate and manage a count because we'll change
// the tokens array on the way
for ($i = 0, $c = count($this->tokens); $i < $c; ++$i) {
// first check that the following tokens are form ~LABEL~,
// then match the __EMU__... sequence.
if ('~' === $this->tokens[$i]
&& isset($this->tokens[$i + 2])
&& '~' === $this->tokens[$i + 2]
&& T_STRING === $this->tokens[$i + 1][0]
&& preg_match('(^__EMU__([A-Z]++)__(?:([A-Za-z0-9]++)__)?$)', $this->tokens[$i + 1][1], $matches)
) {
if ('BINARY' === $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])
);
} elseif ('NS' === $matches[1]) {
// a \ single char token is returned here and replaced by a
// PHPParser_Parser::T_NS_SEPARATOR token in ->lex(). This hacks around the
// limitations arising from T_NS_SEPARATOR not being defined on 5.3
$replace = array('\\');
} elseif ('NOWDOC' === $matches[1]) {
// decode the encoded nowdoc payload; pack('H*' is bin2hex( for 5.3
list($start, $content, $end) = explode('x', $matches[2]);
list($start, $content, $end) = array(pack('H*', $start), pack('H*', $content), pack('H*', $end));
$replace = array();
$replace[] = array(T_START_HEREDOC, $start, $this->tokens[$i + 1][2]);
if ('' !== $content) {
$replace[] = array(T_ENCAPSED_AND_WHITESPACE, $content, -1);
}
$replace[] = array(T_END_HEREDOC, $end, -1);
} else {
// just ignore all other __EMU__ sequences
continue;
}
array_splice($this->tokens, $i, 3, $replace);
$c -= 3 - count($replace);
// for multichar tokens (e.g. strings) replace any ~__EMU__...~ sequences
// in their content with the original character sequence
} elseif (is_array($this->tokens[$i])
&& 0 !== strpos($this->tokens[$i][1], '__EMU__')
) {
$this->tokens[$i][1] = preg_replace_callback(
'(~__EMU__([A-Z]++)__(?:([A-Za-z0-9]++)__)?~)',
array($this, 'restoreContentCallback'),
$this->tokens[$i][1]
);
}
}
}
/*
* This method is a callback for restoring EMU sequences in
* multichar tokens (like strings) to their original value.
*/
public function restoreContentCallback(array $matches) {
if ('BINARY' === $matches[1]) {
return $matches[2];
} elseif ('NS' === $matches[1]) {
return '\\';
} elseif ('NOWDOC' === $matches[1]) {
list($start, $content, $end) = explode('x', $matches[2]);
return pack('H*', $start) . pack('H*', $content) . pack('H*', $end);
} else {
return $matches[0];
}
}
public function lex(&$value = null, &$line = null, &$docComment = null) {
$token = parent::lex($value, $line, $docComment);
// replace new keywords by their respective tokens. This is not done
// 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)
if (PHPParser_Parser::T_STRING === $token && !$this->inObjectAccess) {
if (isset(self::$keywords[strtolower($value)])) {
return self::$keywords[strtolower($value)];
}
// backslashes are replaced by T_NS_SEPARATOR tokens
} elseif (92 === $token) { // ord('\\')
return PHPParser_Parser::T_NS_SEPARATOR;
// keep track of whether we currently are in an object access (after ->)
} elseif (PHPParser_Parser::T_OBJECT_OPERATOR === $token) {
$this->inObjectAccess = true;
} else {
$this->inObjectAccess = false;
}
return $token;
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $value Value to pass
* @property bool $byRef Whether to pass by ref
*/
class PHPParser_Node_Arg extends PHPParser_NodeAbstract
{
/**
* Constructs a function call argument node.
*
* @param PHPParser_Node_Expr $value Value to pass
* @param bool $byRef Whether to pass by ref
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $value, $byRef = false, $line = -1, $docComment = null) {
parent::__construct(
array(
'value' => $value,
'byRef' => $byRef
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property string $name Name
* @property PHPParser_Node_Expr $value Value
*/
class PHPParser_Node_Const extends PHPParser_NodeAbstract
{
/**
* Constructs a const node for use in class const and const statements.
*
* @param string $name Name
* @param PHPParser_Node_Expr $value Value
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct($name, PHPParser_Node_Expr $value, $line = -1, $docComment = null) {
parent::__construct(
array(
'name' => $name,
'value' => $value,
),
$line, $docComment
);
}
}

View File

@ -1,5 +0,0 @@
<?php
abstract class PHPParser_Node_Expr extends PHPParser_NodeAbstract
{
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr_ArrayItem[] $items Items
*/
class PHPParser_Node_Expr_Array extends PHPParser_Node_Expr
{
/**
* Constructs an array node.
*
* @param PHPParser_Node_Expr_ArrayItem[] $items Items of the array
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(array $items = array(), $line = -1, $docComment = null) {
parent::__construct(
array(
'items' => $items
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
* @property null|PHPParser_Node_Expr $dim Array index / dim
*/
class PHPParser_Node_Expr_ArrayDimFetch extends PHPParser_Node_Expr
{
/**
* Constructs an array index fetch node.
*
* @param PHPParser_Node_Expr $var Variable
* @param null|PHPParser_Node_Expr $dim Array index / dim
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $dim = null, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'dim' => $dim
),
$line, $docComment
);
}
}

View File

@ -1,29 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $value Value
* @property null|PHPParser_Node_Expr $key Key
* @property bool $byRef Whether to assign by reference
*/
class PHPParser_Node_Expr_ArrayItem extends PHPParser_Node_Expr
{
/**
* Constructs an array item node.
*
* @param PHPParser_Node_Expr $value Value
* @param null|PHPParser_Node_Expr $key Key
* @param bool $byRef Whether to assign by reference
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $value, PHPParser_Node_Expr $key = null, $byRef = false, $line = -1, $docComment = null) {
parent::__construct(
array(
'key' => $key,
'value' => $value,
'byRef' => $byRef
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_Assign extends PHPParser_Node_Expr
{
/**
* Constructs an assignment node.
*
* @param PHPParser_Node_Expr $var Variable
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_AssignBitwiseAnd extends PHPParser_Node_Expr
{
/**
* Constructs an assignment with bitwise and node.
*
* @param PHPParser_Node_Expr $var Variable
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_AssignBitwiseOr extends PHPParser_Node_Expr
{
/**
* Constructs an assignment with bitwise or node.
*
* @param PHPParser_Node_Expr $var Variable
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_AssignBitwiseXor extends PHPParser_Node_Expr
{
/**
* Constructs an assignment with bitwise xor node.
*
* @param PHPParser_Node_Expr $var Variable
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_AssignConcat extends PHPParser_Node_Expr
{
/**
* Constructs an assignment with concat node.
*
* @param PHPParser_Node_Expr $var Variable
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_AssignDiv extends PHPParser_Node_Expr
{
/**
* Constructs an assignment with division node.
*
* @param PHPParser_Node_Expr $var Variable
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property array $vars List of variables to assign to
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_AssignList extends PHPParser_Node_Expr
{
/**
* Constructs a list() assignment node.
*
* @param array $vars List of variables to assign to
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(array $vars, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'vars' => $vars,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_AssignMinus extends PHPParser_Node_Expr
{
/**
* Constructs an assignment with minus node.
*
* @param PHPParser_Node_Expr $var Variable
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_AssignMod extends PHPParser_Node_Expr
{
/**
* Constructs an assignment with modulo node.
*
* @param PHPParser_Node_Expr $var Variable
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_AssignMul extends PHPParser_Node_Expr
{
/**
* Constructs an assignment with multiplication node.
*
* @param PHPParser_Node_Expr $var Variable
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_AssignPlus extends PHPParser_Node_Expr
{
/**
* Constructs an assignment with addition node.
*
* @param PHPParser_Node_Expr $var Variable
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable reference is assigned to
* @property PHPParser_Node_Expr $expr Variable which is referenced
*/
class PHPParser_Node_Expr_AssignRef extends PHPParser_Node_Expr
{
/**
* Constructs an assignment node.
*
* @param PHPParser_Node_Expr $var Variable
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_AssignShiftLeft extends PHPParser_Node_Expr
{
/**
* Constructs an assignment with left shift node.
*
* @param PHPParser_Node_Expr $var Variable
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_AssignShiftRight extends PHPParser_Node_Expr
{
/**
* Constructs an assignment with right shift node.
*
* @param PHPParser_Node_Expr $var Variable
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_BitwiseAnd extends PHPParser_Node_Expr
{
/**
* Constructs a bitwise and node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_BitwiseNot extends PHPParser_Node_Expr
{
/**
* Constructs a bitwise not node.
*
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_BitwiseOr extends PHPParser_Node_Expr
{
/**
* Constructs a bitwise or node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_BitwiseXor extends PHPParser_Node_Expr
{
/**
* Constructs a bitwise xor node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_BooleanAnd extends PHPParser_Node_Expr
{
/**
* Constructs a boolean and node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_BooleanNot extends PHPParser_Node_Expr
{
/**
* Constructs a boolean not node.
*
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_BooleanOr extends PHPParser_Node_Expr
{
/**
* Constructs a boolean or node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $expr Expression
*/
abstract class PHPParser_Node_Expr_Cast extends PHPParser_Node_Expr
{
/**
* Constructs a cast node.
*
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,5 +0,0 @@
<?php
class PHPParser_Node_Expr_Cast_Array extends PHPParser_Node_Expr_Cast
{
}

View File

@ -1,5 +0,0 @@
<?php
class PHPParser_Node_Expr_Cast_Bool extends PHPParser_Node_Expr_Cast
{
}

View File

@ -1,5 +0,0 @@
<?php
class PHPParser_Node_Expr_Cast_Double extends PHPParser_Node_Expr_Cast
{
}

View File

@ -1,5 +0,0 @@
<?php
class PHPParser_Node_Expr_Cast_Int extends PHPParser_Node_Expr_Cast
{
}

View File

@ -1,5 +0,0 @@
<?php
class PHPParser_Node_Expr_Cast_Object extends PHPParser_Node_Expr_Cast
{
}

View File

@ -1,5 +0,0 @@
<?php
class PHPParser_Node_Expr_Cast_String extends PHPParser_Node_Expr_Cast
{
}

View File

@ -1,5 +0,0 @@
<?php
class PHPParser_Node_Expr_Cast_Unset extends PHPParser_Node_Expr_Cast
{
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
* @property string $name Constant name
*/
class PHPParser_Node_Expr_ClassConstFetch extends PHPParser_Node_Expr
{
/**
* Constructs a class const fetch node.
*
* @param PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
* @param string $name Constant name
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct($class, $name, $line = -1, $docComment = null) {
parent::__construct(
array(
'class' => $class,
'name' => $name
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_Clone extends PHPParser_Node_Expr
{
/**
* Constructs a clone node.
*
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,36 +0,0 @@
<?php
/**
* @property PHPParser_Node[] $stmts Statements
* @property PHPParser_Node_Stmt_FuncParam[] $params Parameters
* @property PHPParser_Node_Expr_ClosureUse[] $uses use()s
* @property bool $byRef Whether to return by reference
* @property bool $static Whether the closure is static
*/
class PHPParser_Node_Expr_Closure extends PHPParser_Node_Expr
{
/**
* Constructs a lambda function node.
*
* @param array $subNodes Array of the following optional subnodes:
* 'stmts' => array(): Statements
* 'params' => array(): Parameters
* 'uses' => array(): use()s
* 'byRef' => false : Whether to return by reference
* 'static' => false : Whether the closure is static
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(array $subNodes = array(), $line = -1, $docComment = null) {
parent::__construct(
$subNodes + array(
'stmts' => array(),
'params' => array(),
'uses' => array(),
'byRef' => false,
'static' => false,
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_Concat extends PHPParser_Node_Expr
{
/**
* Constructs a concat node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Name $name Constant name
*/
class PHPParser_Node_Expr_ConstFetch extends PHPParser_Node_Expr
{
/**
* Constructs a const fetch node.
*
* @param PHPParser_Node_Name $name Constant name
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Name $name, $line = -1, $docComment = null) {
parent::__construct(
array(
'name' => $name
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_Div extends PHPParser_Node_Expr
{
/**
* Constructs a division node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
*/
class PHPParser_Node_Expr_Empty extends PHPParser_Node_Expr
{
/**
* Constructs an empty() node.
*
* @param PHPParser_Node_Expr $var Variable
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_Equal extends PHPParser_Node_Expr
{
/**
* Constructs a equality comparison node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_ErrorSuppress extends PHPParser_Node_Expr
{
/**
* Constructs an error suppress node.
*
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_Eval extends PHPParser_Node_Expr
{
/**
* Constructs an eval() node.
*
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property null|PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_Exit extends PHPParser_Node_Expr
{
/**
* Constructs an exit() node.
*
* @param null|PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $expr = null, $line = -1, $docComment = null) {
parent::__construct(
array(
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Name|PHPParser_Node_Expr $name Function name
* @property PHPParser_Node_Arg[] $args Arguments
*/
class PHPParser_Node_Expr_FuncCall extends PHPParser_Node_Expr
{
/**
* Constructs a function call node.
*
* @param PHPParser_Node_Name|PHPParser_Node_Expr $name Function name
* @param PHPParser_Node_Arg[] $args Arguments
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct($name, array $args = array(), $line = -1, $docComment = null) {
parent::__construct(
array(
'name' => $name,
'args' => $args
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_Greater extends PHPParser_Node_Expr
{
/**
* Constructs a greater than comparison node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_GreaterOrEqual extends PHPParser_Node_Expr
{
/**
* Constructs a greater than or equal node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_Identical extends PHPParser_Node_Expr
{
/**
* Constructs an identicality comparison node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,31 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $expr Expression
* @property int $type Type of include
*/
class PHPParser_Node_Expr_Include extends PHPParser_Node_Expr
{
const TYPE_INCLUDE = 1;
const TYPE_INCLUDE_ONCE = 2;
const TYPE_REQUIRE = 3;
const TYPE_REQUIRE_ONCE = 4;
/**
* Constructs an include node.
*
* @param PHPParser_Node_Expr $expr Expression
* @param int $type Type of include
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $expr, $type, $line = -1, $docComment = null) {
parent::__construct(
array(
'expr' => $expr,
'type' => $type
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $expr Expression
* @property PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
*/
class PHPParser_Node_Expr_Instanceof extends PHPParser_Node_Expr
{
/**
* Constructs an instanceof check node.
*
* @param PHPParser_Node_Expr $expr Expression
* @param PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $expr, $class, $line = -1, $docComment = null) {
parent::__construct(
array(
'expr' => $expr,
'class' => $class
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr[] $vars Variables
*/
class PHPParser_Node_Expr_Isset extends PHPParser_Node_Expr
{
/**
* Constructs an array node.
*
* @param PHPParser_Node_Expr[] $vars Variables
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(array $vars, $line = -1, $docComment = null) {
parent::__construct(
array(
'vars' => $vars
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_LogicalAnd extends PHPParser_Node_Expr
{
/**
* Constructs a logical and node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_LogicalOr extends PHPParser_Node_Expr
{
/**
* Constructs a logical or node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_LogicalXor extends PHPParser_Node_Expr
{
/**
* Constructs a logical xor node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,29 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable holding object
* @property string|PHPParser_Node_Expr $name Method name
* @property PHPParser_Node_Arg[] $args Arguments
*/
class PHPParser_Node_Expr_MethodCall extends PHPParser_Node_Expr
{
/**
* Constructs a function call node.
*
* @param PHPParser_Node_Expr $var Variable holding object
* @param string|PHPParser_Node_Expr $name Method name
* @param PHPParser_Node_Arg[] $args Arguments
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, $name, array $args = array(), $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'name' => $name,
'args' => $args
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_Minus extends PHPParser_Node_Expr
{
/**
* Constructs a substraction node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_Mod extends PHPParser_Node_Expr
{
/**
* Constructs a modulo node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_Mul extends PHPParser_Node_Expr
{
/**
* Constructs a multiplication node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
* @property PHPParser_Node_Arg[] $args Arguments
*/
class PHPParser_Node_Expr_New extends PHPParser_Node_Expr
{
/**
* Constructs a function call node.
*
* @param PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
* @param PHPParser_Node_Arg[] $args Arguments
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct($class, array $args = array(), $line = -1, $docComment = null) {
parent::__construct(
array(
'class' => $class,
'args' => $args
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_NotEqual extends PHPParser_Node_Expr
{
/**
* Constructs a not equal comparison node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_NotIdentical extends PHPParser_Node_Expr
{
/**
* Constructs a not identical comparison node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_Plus extends PHPParser_Node_Expr
{
/**
* Constructs an addition node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
*/
class PHPParser_Node_Expr_PostDec extends PHPParser_Node_Expr
{
/**
* Constructs a post decrement node.
*
* @param PHPParser_Node_Expr $var Variable
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
*/
class PHPParser_Node_Expr_PostInc extends PHPParser_Node_Expr
{
/**
* Constructs a post increment node.
*
* @param PHPParser_Node_Expr $var Variable
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
*/
class PHPParser_Node_Expr_PreDec extends PHPParser_Node_Expr
{
/**
* Constructs a pre decrement node.
*
* @param PHPParser_Node_Expr $var Variable
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable
*/
class PHPParser_Node_Expr_PreInc extends PHPParser_Node_Expr
{
/**
* Constructs a pre increment node.
*
* @param PHPParser_Node_Expr $var Variable
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_Print extends PHPParser_Node_Expr
{
/**
* Constructs an print() node.
*
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'expr' => $expr
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $var Variable holding object
* @property string|PHPParser_Node_Expr $name Property Name
*/
class PHPParser_Node_Expr_PropertyFetch extends PHPParser_Node_Expr
{
/**
* Constructs a function call node.
*
* @param PHPParser_Node_Expr $var Variable holding object
* @param string|PHPParser_Node_Expr $name Property name
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $var, $name, $line = -1, $docComment = null) {
parent::__construct(
array(
'var' => $var,
'name' => $name
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property array $parts Encapsed string array
*/
class PHPParser_Node_Expr_ShellExec extends PHPParser_Node_Expr
{
/**
* Constructs a shell exec (backtick) node.
*
* @param array $parts Encapsed string array
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct($parts, $line = -1, $docComment = null) {
parent::__construct(
array(
'parts' => $parts
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_ShiftLeft extends PHPParser_Node_Expr
{
/**
* Constructs a shift left node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_ShiftRight extends PHPParser_Node_Expr
{
/**
* Constructs a shift right node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_Smaller extends PHPParser_Node_Expr
{
/**
* Constructs a smaller than comparison node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $left The left hand side expression
* @property PHPParser_Node_Expr $right The right hand side expression
*/
class PHPParser_Node_Expr_SmallerOrEqual extends PHPParser_Node_Expr
{
/**
* Constructs a smaller than or equal comparison node.
*
* @param PHPParser_Node_Expr $left The left hand side expression
* @param PHPParser_Node_Expr $right The right hand side expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, $line = -1, $docComment = null) {
parent::__construct(
array(
'left' => $left,
'right' => $right
),
$line, $docComment
);
}
}

View File

@ -1,29 +0,0 @@
<?php
/**
* @property PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
* @property string|PHPParser_Node_Expr $name Method name
* @property PHPParser_Node_Arg[] $args Arguments
*/
class PHPParser_Node_Expr_StaticCall extends PHPParser_Node_Expr
{
/**
* Constructs a static method call node.
*
* @param PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
* @param string|PHPParser_Node_Expr $name Method name
* @param PHPParser_Node_Arg[] $args Arguments
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct($class, $name, array $args = array(), $line = -1, $docComment = null) {
parent::__construct(
array(
'class' => $class,
'name' => $name,
'args' => $args
),
$line, $docComment
);
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* @property PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
* @property string|PHPParser_Node_Expr $name Property name
*/
class PHPParser_Node_Expr_StaticPropertyFetch extends PHPParser_Node_Expr
{
/**
* Constructs a static property fetch node.
*
* @param PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
* @param string|PHPParser_Node_Expr $name Property name
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct($class, $name, $line = -1, $docComment = null) {
parent::__construct(
array(
'class' => $class,
'name' => $name
),
$line, $docComment
);
}
}

View File

@ -1,29 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $cond Condition
* @property null|PHPParser_Node_Expr $if Expression for true
* @property PHPParser_Node_Expr $else Expression for false
*/
class PHPParser_Node_Expr_Ternary extends PHPParser_Node_Expr
{
/**
* Constructs a ternary operator node.
*
* @param PHPParser_Node_Expr $cond Condition
* @param null|PHPParser_Node_Expr $if Expression for true
* @param PHPParser_Node_Expr $else Expression for false
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $cond, $if, PHPParser_Node_Expr $else, $line = -1, $docComment = null) {
parent::__construct(
array(
'cond' => $cond,
'if' => $if,
'else' => $else
),
$line, $docComment
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/**
* @property PHPParser_Node_Expr $expr Expression
*/
class PHPParser_Node_Expr_UnaryMinus extends PHPParser_Node_Expr
{
/**
* Constructs a unary minus node.
*
* @param PHPParser_Node_Expr $expr Expression
* @param int $line Line
* @param null|string $docComment Nearest doc comment
*/
public function __construct(PHPParser_Node_Expr $expr, $line = -1, $docComment = null) {
parent::__construct(
array(
'expr' => $expr
),
$line, $docComment
);
}
}

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