Chris@0
|
1 Other node tree representations
|
Chris@0
|
2 ===============================
|
Chris@0
|
3
|
Chris@0
|
4 It is possible to convert the AST into several textual representations, which serve different uses.
|
Chris@0
|
5
|
Chris@0
|
6 Simple serialization
|
Chris@0
|
7 --------------------
|
Chris@0
|
8
|
Chris@0
|
9 It is possible to serialize the node tree using `serialize()` and also unserialize it using
|
Chris@0
|
10 `unserialize()`. The output is not human readable and not easily processable from anything
|
Chris@0
|
11 but PHP, but it is compact and generates quickly. The main application thus is in caching.
|
Chris@0
|
12
|
Chris@0
|
13 Human readable dumping
|
Chris@0
|
14 ----------------------
|
Chris@0
|
15
|
Chris@0
|
16 Furthermore it is possible to dump nodes into a human readable format using the `dump` method of
|
Chris@0
|
17 `PhpParser\NodeDumper`. This can be used for debugging.
|
Chris@0
|
18
|
Chris@0
|
19 ```php
|
Chris@0
|
20 $code = <<<'CODE'
|
Chris@0
|
21 <?php
|
Chris@0
|
22
|
Chris@0
|
23 function printLine($msg) {
|
Chris@0
|
24 echo $msg, "\n";
|
Chris@0
|
25 }
|
Chris@0
|
26
|
Chris@0
|
27 printLine('Hello World!!!');
|
Chris@0
|
28 CODE;
|
Chris@0
|
29
|
Chris@0
|
30 $parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7);
|
Chris@0
|
31 $nodeDumper = new PhpParser\NodeDumper;
|
Chris@0
|
32
|
Chris@0
|
33 try {
|
Chris@0
|
34 $stmts = $parser->parse($code);
|
Chris@0
|
35
|
Chris@0
|
36 echo $nodeDumper->dump($stmts), "\n";
|
Chris@0
|
37 } catch (PhpParser\Error $e) {
|
Chris@0
|
38 echo 'Parse Error: ', $e->getMessage();
|
Chris@0
|
39 }
|
Chris@0
|
40 ```
|
Chris@0
|
41
|
Chris@0
|
42 The above script will have an output looking roughly like this:
|
Chris@0
|
43
|
Chris@0
|
44 ```
|
Chris@0
|
45 array(
|
Chris@0
|
46 0: Stmt_Function(
|
Chris@0
|
47 byRef: false
|
Chris@0
|
48 params: array(
|
Chris@0
|
49 0: Param(
|
Chris@0
|
50 name: msg
|
Chris@0
|
51 default: null
|
Chris@0
|
52 type: null
|
Chris@0
|
53 byRef: false
|
Chris@0
|
54 )
|
Chris@0
|
55 )
|
Chris@0
|
56 stmts: array(
|
Chris@0
|
57 0: Stmt_Echo(
|
Chris@0
|
58 exprs: array(
|
Chris@0
|
59 0: Expr_Variable(
|
Chris@0
|
60 name: msg
|
Chris@0
|
61 )
|
Chris@0
|
62 1: Scalar_String(
|
Chris@0
|
63 value:
|
Chris@0
|
64
|
Chris@0
|
65 )
|
Chris@0
|
66 )
|
Chris@0
|
67 )
|
Chris@0
|
68 )
|
Chris@0
|
69 name: printLine
|
Chris@0
|
70 )
|
Chris@0
|
71 1: Expr_FuncCall(
|
Chris@0
|
72 name: Name(
|
Chris@0
|
73 parts: array(
|
Chris@0
|
74 0: printLine
|
Chris@0
|
75 )
|
Chris@0
|
76 )
|
Chris@0
|
77 args: array(
|
Chris@0
|
78 0: Arg(
|
Chris@0
|
79 value: Scalar_String(
|
Chris@0
|
80 value: Hello World!!!
|
Chris@0
|
81 )
|
Chris@0
|
82 byRef: false
|
Chris@0
|
83 )
|
Chris@0
|
84 )
|
Chris@0
|
85 )
|
Chris@0
|
86 )
|
Chris@0
|
87 ```
|
Chris@0
|
88
|
Chris@0
|
89 JSON encoding
|
Chris@0
|
90 -------------
|
Chris@0
|
91
|
Chris@0
|
92 Nodes (and comments) implement the `JsonSerializable` interface. As such, it is possible to JSON
|
Chris@0
|
93 encode the AST directly using `json_encode()`:
|
Chris@0
|
94
|
Chris@0
|
95 ```php
|
Chris@0
|
96 $code = <<<'CODE'
|
Chris@0
|
97 <?php
|
Chris@0
|
98
|
Chris@0
|
99 function printLine($msg) {
|
Chris@0
|
100 echo $msg, "\n";
|
Chris@0
|
101 }
|
Chris@0
|
102
|
Chris@0
|
103 printLine('Hello World!!!');
|
Chris@0
|
104 CODE;
|
Chris@0
|
105
|
Chris@0
|
106 $parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7);
|
Chris@0
|
107 $nodeDumper = new PhpParser\NodeDumper;
|
Chris@0
|
108
|
Chris@0
|
109 try {
|
Chris@0
|
110 $stmts = $parser->parse($code);
|
Chris@0
|
111
|
Chris@0
|
112 echo json_encode($stmts, JSON_PRETTY_PRINT), "\n";
|
Chris@0
|
113 } catch (PhpParser\Error $e) {
|
Chris@0
|
114 echo 'Parse Error: ', $e->getMessage();
|
Chris@0
|
115 }
|
Chris@0
|
116 ```
|
Chris@0
|
117
|
Chris@0
|
118 This will result in the following output (which includes attributes):
|
Chris@0
|
119
|
Chris@0
|
120 ```json
|
Chris@0
|
121 [
|
Chris@0
|
122 {
|
Chris@0
|
123 "nodeType": "Stmt_Function",
|
Chris@0
|
124 "byRef": false,
|
Chris@0
|
125 "name": "printLine",
|
Chris@0
|
126 "params": [
|
Chris@0
|
127 {
|
Chris@0
|
128 "nodeType": "Param",
|
Chris@0
|
129 "type": null,
|
Chris@0
|
130 "byRef": false,
|
Chris@0
|
131 "variadic": false,
|
Chris@0
|
132 "name": "msg",
|
Chris@0
|
133 "default": null,
|
Chris@0
|
134 "attributes": {
|
Chris@0
|
135 "startLine": 3,
|
Chris@0
|
136 "endLine": 3
|
Chris@0
|
137 }
|
Chris@0
|
138 }
|
Chris@0
|
139 ],
|
Chris@0
|
140 "returnType": null,
|
Chris@0
|
141 "stmts": [
|
Chris@0
|
142 {
|
Chris@0
|
143 "nodeType": "Stmt_Echo",
|
Chris@0
|
144 "exprs": [
|
Chris@0
|
145 {
|
Chris@0
|
146 "nodeType": "Expr_Variable",
|
Chris@0
|
147 "name": "msg",
|
Chris@0
|
148 "attributes": {
|
Chris@0
|
149 "startLine": 4,
|
Chris@0
|
150 "endLine": 4
|
Chris@0
|
151 }
|
Chris@0
|
152 },
|
Chris@0
|
153 {
|
Chris@0
|
154 "nodeType": "Scalar_String",
|
Chris@0
|
155 "value": "\n",
|
Chris@0
|
156 "attributes": {
|
Chris@0
|
157 "startLine": 4,
|
Chris@0
|
158 "endLine": 4,
|
Chris@0
|
159 "kind": 2
|
Chris@0
|
160 }
|
Chris@0
|
161 }
|
Chris@0
|
162 ],
|
Chris@0
|
163 "attributes": {
|
Chris@0
|
164 "startLine": 4,
|
Chris@0
|
165 "endLine": 4
|
Chris@0
|
166 }
|
Chris@0
|
167 }
|
Chris@0
|
168 ],
|
Chris@0
|
169 "attributes": {
|
Chris@0
|
170 "startLine": 3,
|
Chris@0
|
171 "endLine": 5
|
Chris@0
|
172 }
|
Chris@0
|
173 },
|
Chris@0
|
174 {
|
Chris@0
|
175 "nodeType": "Expr_FuncCall",
|
Chris@0
|
176 "name": {
|
Chris@0
|
177 "nodeType": "Name",
|
Chris@0
|
178 "parts": [
|
Chris@0
|
179 "printLine"
|
Chris@0
|
180 ],
|
Chris@0
|
181 "attributes": {
|
Chris@0
|
182 "startLine": 7,
|
Chris@0
|
183 "endLine": 7
|
Chris@0
|
184 }
|
Chris@0
|
185 },
|
Chris@0
|
186 "args": [
|
Chris@0
|
187 {
|
Chris@0
|
188 "nodeType": "Arg",
|
Chris@0
|
189 "value": {
|
Chris@0
|
190 "nodeType": "Scalar_String",
|
Chris@0
|
191 "value": "Hello World!!!",
|
Chris@0
|
192 "attributes": {
|
Chris@0
|
193 "startLine": 7,
|
Chris@0
|
194 "endLine": 7,
|
Chris@0
|
195 "kind": 1
|
Chris@0
|
196 }
|
Chris@0
|
197 },
|
Chris@0
|
198 "byRef": false,
|
Chris@0
|
199 "unpack": false,
|
Chris@0
|
200 "attributes": {
|
Chris@0
|
201 "startLine": 7,
|
Chris@0
|
202 "endLine": 7
|
Chris@0
|
203 }
|
Chris@0
|
204 }
|
Chris@0
|
205 ],
|
Chris@0
|
206 "attributes": {
|
Chris@0
|
207 "startLine": 7,
|
Chris@0
|
208 "endLine": 7
|
Chris@0
|
209 }
|
Chris@0
|
210 }
|
Chris@0
|
211 ]
|
Chris@0
|
212 ```
|
Chris@0
|
213
|
Chris@0
|
214 There is currently no mechanism to convert JSON back into a node tree. Furthermore, not all ASTs
|
Chris@0
|
215 can be JSON encoded. In particular, JSON only supports UTF-8 strings.
|
Chris@0
|
216
|
Chris@0
|
217 Serialization to XML
|
Chris@0
|
218 --------------------
|
Chris@0
|
219
|
Chris@0
|
220 It is also possible to serialize the node tree to XML using `PhpParser\Serializer\XML->serialize()`
|
Chris@0
|
221 and to unserialize it using `PhpParser\Unserializer\XML->unserialize()`. This is useful for
|
Chris@0
|
222 interfacing with other languages and applications or for doing transformation using XSLT.
|
Chris@0
|
223
|
Chris@0
|
224 ```php
|
Chris@0
|
225 <?php
|
Chris@0
|
226 $code = <<<'CODE'
|
Chris@0
|
227 <?php
|
Chris@0
|
228
|
Chris@0
|
229 function printLine($msg) {
|
Chris@0
|
230 echo $msg, "\n";
|
Chris@0
|
231 }
|
Chris@0
|
232
|
Chris@0
|
233 printLine('Hello World!!!');
|
Chris@0
|
234 CODE;
|
Chris@0
|
235
|
Chris@0
|
236 $parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7);
|
Chris@0
|
237 $serializer = new PhpParser\Serializer\XML;
|
Chris@0
|
238
|
Chris@0
|
239 try {
|
Chris@0
|
240 $stmts = $parser->parse($code);
|
Chris@0
|
241
|
Chris@0
|
242 echo $serializer->serialize($stmts);
|
Chris@0
|
243 } catch (PhpParser\Error $e) {
|
Chris@0
|
244 echo 'Parse Error: ', $e->getMessage();
|
Chris@0
|
245 }
|
Chris@0
|
246 ```
|
Chris@0
|
247
|
Chris@0
|
248 Produces:
|
Chris@0
|
249
|
Chris@0
|
250 ```xml
|
Chris@0
|
251 <?xml version="1.0" encoding="UTF-8"?>
|
Chris@0
|
252 <AST xmlns:node="http://nikic.github.com/PHPParser/XML/node" xmlns:subNode="http://nikic.github.com/PHPParser/XML/subNode" xmlns:scalar="http://nikic.github.com/PHPParser/XML/scalar">
|
Chris@0
|
253 <scalar:array>
|
Chris@0
|
254 <node:Stmt_Function line="2">
|
Chris@0
|
255 <subNode:byRef>
|
Chris@0
|
256 <scalar:false/>
|
Chris@0
|
257 </subNode:byRef>
|
Chris@0
|
258 <subNode:params>
|
Chris@0
|
259 <scalar:array>
|
Chris@0
|
260 <node:Param line="2">
|
Chris@0
|
261 <subNode:name>
|
Chris@0
|
262 <scalar:string>msg</scalar:string>
|
Chris@0
|
263 </subNode:name>
|
Chris@0
|
264 <subNode:default>
|
Chris@0
|
265 <scalar:null/>
|
Chris@0
|
266 </subNode:default>
|
Chris@0
|
267 <subNode:type>
|
Chris@0
|
268 <scalar:null/>
|
Chris@0
|
269 </subNode:type>
|
Chris@0
|
270 <subNode:byRef>
|
Chris@0
|
271 <scalar:false/>
|
Chris@0
|
272 </subNode:byRef>
|
Chris@0
|
273 </node:Param>
|
Chris@0
|
274 </scalar:array>
|
Chris@0
|
275 </subNode:params>
|
Chris@0
|
276 <subNode:stmts>
|
Chris@0
|
277 <scalar:array>
|
Chris@0
|
278 <node:Stmt_Echo line="3">
|
Chris@0
|
279 <subNode:exprs>
|
Chris@0
|
280 <scalar:array>
|
Chris@0
|
281 <node:Expr_Variable line="3">
|
Chris@0
|
282 <subNode:name>
|
Chris@0
|
283 <scalar:string>msg</scalar:string>
|
Chris@0
|
284 </subNode:name>
|
Chris@0
|
285 </node:Expr_Variable>
|
Chris@0
|
286 <node:Scalar_String line="3">
|
Chris@0
|
287 <subNode:value>
|
Chris@0
|
288 <scalar:string>
|
Chris@0
|
289 </scalar:string>
|
Chris@0
|
290 </subNode:value>
|
Chris@0
|
291 </node:Scalar_String>
|
Chris@0
|
292 </scalar:array>
|
Chris@0
|
293 </subNode:exprs>
|
Chris@0
|
294 </node:Stmt_Echo>
|
Chris@0
|
295 </scalar:array>
|
Chris@0
|
296 </subNode:stmts>
|
Chris@0
|
297 <subNode:name>
|
Chris@0
|
298 <scalar:string>printLine</scalar:string>
|
Chris@0
|
299 </subNode:name>
|
Chris@0
|
300 </node:Stmt_Function>
|
Chris@0
|
301 <node:Expr_FuncCall line="6">
|
Chris@0
|
302 <subNode:name>
|
Chris@0
|
303 <node:Name line="6">
|
Chris@0
|
304 <subNode:parts>
|
Chris@0
|
305 <scalar:array>
|
Chris@0
|
306 <scalar:string>printLine</scalar:string>
|
Chris@0
|
307 </scalar:array>
|
Chris@0
|
308 </subNode:parts>
|
Chris@0
|
309 </node:Name>
|
Chris@0
|
310 </subNode:name>
|
Chris@0
|
311 <subNode:args>
|
Chris@0
|
312 <scalar:array>
|
Chris@0
|
313 <node:Arg line="6">
|
Chris@0
|
314 <subNode:value>
|
Chris@0
|
315 <node:Scalar_String line="6">
|
Chris@0
|
316 <subNode:value>
|
Chris@0
|
317 <scalar:string>Hello World!!!</scalar:string>
|
Chris@0
|
318 </subNode:value>
|
Chris@0
|
319 </node:Scalar_String>
|
Chris@0
|
320 </subNode:value>
|
Chris@0
|
321 <subNode:byRef>
|
Chris@0
|
322 <scalar:false/>
|
Chris@0
|
323 </subNode:byRef>
|
Chris@0
|
324 </node:Arg>
|
Chris@0
|
325 </scalar:array>
|
Chris@0
|
326 </subNode:args>
|
Chris@0
|
327 </node:Expr_FuncCall>
|
Chris@0
|
328 </scalar:array>
|
Chris@0
|
329 </AST>
|
Chris@0
|
330 ``` |