Chris@0
|
1 PHP Parser
|
Chris@0
|
2 ==========
|
Chris@0
|
3
|
Chris@0
|
4 [](https://travis-ci.org/nikic/PHP-Parser) [](https://coveralls.io/github/nikic/PHP-Parser?branch=master)
|
Chris@0
|
5
|
Chris@17
|
6 This is a PHP 5.2 to PHP 7.3 parser written in PHP. Its purpose is to simplify static code analysis and
|
Chris@0
|
7 manipulation.
|
Chris@0
|
8
|
Chris@17
|
9 [**Documentation for version 4.x**][doc_master] (stable; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 7.3).
|
Chris@0
|
10
|
Chris@17
|
11 [Documentation for version 3.x][doc_3_x] (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2).
|
Chris@0
|
12
|
Chris@13
|
13 Features
|
Chris@13
|
14 --------
|
Chris@0
|
15
|
Chris@13
|
16 The main features provided by this library are:
|
Chris@0
|
17
|
Chris@13
|
18 * Parsing PHP 5 and PHP 7 code into an abstract syntax tree (AST).
|
Chris@13
|
19 * Invalid code can be parsed into a partial AST.
|
Chris@13
|
20 * The AST contains accurate location information.
|
Chris@13
|
21 * Dumping the AST in human-readable form.
|
Chris@13
|
22 * Converting an AST back to PHP code.
|
Chris@13
|
23 * Experimental: Formatting can be preserved for partially changed ASTs.
|
Chris@13
|
24 * Infrastructure to traverse and modify ASTs.
|
Chris@13
|
25 * Resolution of namespaced names.
|
Chris@13
|
26 * Evaluation of constant expressions.
|
Chris@13
|
27 * Builders to simplify AST construction for code generation.
|
Chris@13
|
28 * Converting an AST into JSON and back.
|
Chris@13
|
29
|
Chris@13
|
30 Quick Start
|
Chris@13
|
31 -----------
|
Chris@13
|
32
|
Chris@13
|
33 Install the library using [composer](https://getcomposer.org):
|
Chris@13
|
34
|
Chris@13
|
35 php composer.phar require nikic/php-parser
|
Chris@13
|
36
|
Chris@13
|
37 Parse some PHP code into an AST and dump the result in human-readable form:
|
Chris@0
|
38
|
Chris@0
|
39 ```php
|
Chris@0
|
40 <?php
|
Chris@13
|
41 use PhpParser\Error;
|
Chris@13
|
42 use PhpParser\NodeDumper;
|
Chris@13
|
43 use PhpParser\ParserFactory;
|
Chris@13
|
44
|
Chris@13
|
45 $code = <<<'CODE'
|
Chris@13
|
46 <?php
|
Chris@13
|
47
|
Chris@13
|
48 function test($foo)
|
Chris@13
|
49 {
|
Chris@13
|
50 var_dump($foo);
|
Chris@13
|
51 }
|
Chris@13
|
52 CODE;
|
Chris@13
|
53
|
Chris@13
|
54 $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
|
Chris@13
|
55 try {
|
Chris@13
|
56 $ast = $parser->parse($code);
|
Chris@13
|
57 } catch (Error $error) {
|
Chris@13
|
58 echo "Parse error: {$error->getMessage()}\n";
|
Chris@13
|
59 return;
|
Chris@13
|
60 }
|
Chris@13
|
61
|
Chris@13
|
62 $dumper = new NodeDumper;
|
Chris@13
|
63 echo $dumper->dump($ast) . "\n";
|
Chris@0
|
64 ```
|
Chris@0
|
65
|
Chris@13
|
66 This dumps an AST looking something like this:
|
Chris@0
|
67
|
Chris@13
|
68 ```
|
Chris@0
|
69 array(
|
Chris@13
|
70 0: Stmt_Function(
|
Chris@13
|
71 byRef: false
|
Chris@13
|
72 name: Identifier(
|
Chris@13
|
73 name: test
|
Chris@13
|
74 )
|
Chris@13
|
75 params: array(
|
Chris@13
|
76 0: Param(
|
Chris@13
|
77 type: null
|
Chris@13
|
78 byRef: false
|
Chris@13
|
79 variadic: false
|
Chris@13
|
80 var: Expr_Variable(
|
Chris@13
|
81 name: foo
|
Chris@13
|
82 )
|
Chris@13
|
83 default: null
|
Chris@0
|
84 )
|
Chris@0
|
85 )
|
Chris@13
|
86 returnType: null
|
Chris@13
|
87 stmts: array(
|
Chris@13
|
88 0: Stmt_Expression(
|
Chris@13
|
89 expr: Expr_FuncCall(
|
Chris@13
|
90 name: Name(
|
Chris@13
|
91 parts: array(
|
Chris@13
|
92 0: var_dump
|
Chris@13
|
93 )
|
Chris@0
|
94 )
|
Chris@13
|
95 args: array(
|
Chris@13
|
96 0: Arg(
|
Chris@13
|
97 value: Expr_Variable(
|
Chris@13
|
98 name: foo
|
Chris@13
|
99 )
|
Chris@13
|
100 byRef: false
|
Chris@13
|
101 unpack: false
|
Chris@13
|
102 )
|
Chris@0
|
103 )
|
Chris@0
|
104 )
|
Chris@0
|
105 )
|
Chris@0
|
106 )
|
Chris@0
|
107 )
|
Chris@0
|
108 )
|
Chris@0
|
109 ```
|
Chris@0
|
110
|
Chris@13
|
111 Let's traverse the AST and perform some kind of modification. For example, drop all function bodies:
|
Chris@0
|
112
|
Chris@13
|
113 ```php
|
Chris@13
|
114 use PhpParser\Node;
|
Chris@13
|
115 use PhpParser\Node\Stmt\Function_;
|
Chris@13
|
116 use PhpParser\NodeTraverser;
|
Chris@13
|
117 use PhpParser\NodeVisitorAbstract;
|
Chris@0
|
118
|
Chris@13
|
119 $traverser = new NodeTraverser();
|
Chris@13
|
120 $traverser->addVisitor(new class extends NodeVisitorAbstract {
|
Chris@13
|
121 public function enterNode(Node $node) {
|
Chris@13
|
122 if ($node instanceof Function_) {
|
Chris@13
|
123 // Clean out the function body
|
Chris@13
|
124 $node->stmts = [];
|
Chris@13
|
125 }
|
Chris@13
|
126 }
|
Chris@13
|
127 });
|
Chris@0
|
128
|
Chris@13
|
129 $ast = $traverser->traverse($ast);
|
Chris@13
|
130 echo $dumper->dump($ast) . "\n";
|
Chris@13
|
131 ```
|
Chris@0
|
132
|
Chris@13
|
133 This gives us an AST where the `Function_::$stmts` are empty:
|
Chris@13
|
134
|
Chris@13
|
135 ```
|
Chris@13
|
136 array(
|
Chris@13
|
137 0: Stmt_Function(
|
Chris@13
|
138 byRef: false
|
Chris@13
|
139 name: Identifier(
|
Chris@13
|
140 name: test
|
Chris@13
|
141 )
|
Chris@13
|
142 params: array(
|
Chris@13
|
143 0: Param(
|
Chris@13
|
144 type: null
|
Chris@13
|
145 byRef: false
|
Chris@13
|
146 variadic: false
|
Chris@13
|
147 var: Expr_Variable(
|
Chris@13
|
148 name: foo
|
Chris@13
|
149 )
|
Chris@13
|
150 default: null
|
Chris@13
|
151 )
|
Chris@13
|
152 )
|
Chris@13
|
153 returnType: null
|
Chris@13
|
154 stmts: array(
|
Chris@13
|
155 )
|
Chris@13
|
156 )
|
Chris@13
|
157 )
|
Chris@13
|
158 ```
|
Chris@13
|
159
|
Chris@13
|
160 Finally, we can convert the new AST back to PHP code:
|
Chris@13
|
161
|
Chris@13
|
162 ```php
|
Chris@13
|
163 use PhpParser\PrettyPrinter;
|
Chris@13
|
164
|
Chris@13
|
165 $prettyPrinter = new PrettyPrinter\Standard;
|
Chris@13
|
166 echo $prettyPrinter->prettyPrintFile($ast);
|
Chris@13
|
167 ```
|
Chris@13
|
168
|
Chris@13
|
169 This gives us our original code, minus the `var_dump()` call inside the function:
|
Chris@13
|
170
|
Chris@13
|
171 ```php
|
Chris@13
|
172 <?php
|
Chris@13
|
173
|
Chris@13
|
174 function test($foo)
|
Chris@13
|
175 {
|
Chris@13
|
176 }
|
Chris@13
|
177 ```
|
Chris@13
|
178
|
Chris@13
|
179 For a more comprehensive introduction, see the documentation.
|
Chris@0
|
180
|
Chris@0
|
181 Documentation
|
Chris@0
|
182 -------------
|
Chris@0
|
183
|
Chris@0
|
184 1. [Introduction](doc/0_Introduction.markdown)
|
Chris@0
|
185 2. [Usage of basic components](doc/2_Usage_of_basic_components.markdown)
|
Chris@0
|
186
|
Chris@0
|
187 Component documentation:
|
Chris@0
|
188
|
Chris@13
|
189 * [Walking the AST](doc/component/Walking_the_AST.markdown)
|
Chris@13
|
190 * Node visitors
|
Chris@13
|
191 * Modifying the AST from a visitor
|
Chris@13
|
192 * Short-circuiting traversals
|
Chris@13
|
193 * Interleaved visitors
|
Chris@13
|
194 * Simple node finding API
|
Chris@13
|
195 * Parent and sibling references
|
Chris@13
|
196 * [Name resolution](doc/component/Name_resolution.markdown)
|
Chris@13
|
197 * Name resolver options
|
Chris@13
|
198 * Name resolution context
|
Chris@13
|
199 * [Pretty printing](doc/component/Pretty_printing.markdown)
|
Chris@13
|
200 * Converting AST back to PHP code
|
Chris@13
|
201 * Customizing formatting
|
Chris@13
|
202 * Formatting-preserving code transformations
|
Chris@16
|
203 * [AST builders](doc/component/AST_builders.markdown)
|
Chris@13
|
204 * Fluent builders for AST nodes
|
Chris@13
|
205 * [Lexer](doc/component/Lexer.markdown)
|
Chris@13
|
206 * Lexer options
|
Chris@13
|
207 * Token and file positions for nodes
|
Chris@13
|
208 * Custom attributes
|
Chris@13
|
209 * [Error handling](doc/component/Error_handling.markdown)
|
Chris@13
|
210 * Column information for errors
|
Chris@13
|
211 * Error recovery (parsing of syntactically incorrect code)
|
Chris@16
|
212 * [Constant expression evaluation](doc/component/Constant_expression_evaluation.markdown)
|
Chris@13
|
213 * Evaluating constant/property/etc initializers
|
Chris@13
|
214 * Handling errors and unsupported expressions
|
Chris@16
|
215 * [JSON representation](doc/component/JSON_representation.markdown)
|
Chris@13
|
216 * JSON encoding and decoding of ASTs
|
Chris@13
|
217 * [Performance](doc/component/Performance.markdown)
|
Chris@13
|
218 * Disabling XDebug
|
Chris@13
|
219 * Reusing objects
|
Chris@13
|
220 * Garbage collection impact
|
Chris@16
|
221 * [Frequently asked questions](doc/component/FAQ.markdown)
|
Chris@13
|
222 * Parent and sibling references
|
Chris@0
|
223
|
Chris@13
|
224 [doc_3_x]: https://github.com/nikic/PHP-Parser/tree/3.x/doc
|
Chris@0
|
225 [doc_master]: https://github.com/nikic/PHP-Parser/tree/master/doc
|