xref: /php-ast/README.md (revision 152b420e)
1php-ast
2=======
3
4This extension exposes the abstract syntax tree generated by PHP 7 and 8.
5
6**This is the documentation for version 1.x.y. See also [documentation for version 0.1.x][v0_1_x].**
7
8Table of Contents
9-----------------
10
11 * [Installation](#installation)
12 * [API overview](#api-overview)
13 * [Basic usage](#basic-usage)
14 * [Example](#example)
15 * [Metadata](#metadata)
16 * [Flags](#flags)
17 * [AST node kinds](#ast-node-kinds)
18 * [AST versioning](#ast-versioning)
19 * [Differences to PHP-Parser](#differences-to-php-parser)
20
21Installation
22------------
23
24**Windows**: Download a [prebuilt Windows DLL](https://downloads.php.net/~windows/pecl/releases/ast/)
25and move it into the `ext/` directory of your PHP installation. Furthermore, add
26`extension=php_ast.dll` to your `php.ini` file.
27(The [php-ast PECL page](https://downloads.php.net/~windows/pecl/releases/ast/) also links to the same DLLs for Windows.)
28
29**Unix (PECL)**: Run `pecl install ast` and add `extension=ast.so` to your `php.ini`.
30
31**Unix (Compile)**: Compile and install the extension as follows.
32
33```sh
34phpize
35./configure
36make
37sudo make install
38```
39
40Additionally add `extension=ast.so` to your `php.ini` file.
41
42API overview
43------------
44
45Defines:
46
47 * `ast\Node` class
48 * `ast\Metadata` class
49 * `ast\AST_*` kind constants
50 * `ast\flags\*` flag constants
51 * `ast\parse_file(string $filename, int $version)`
52 * `ast\parse_code(string $code, int $version [, string $filename = "string code"])`
53 * `ast\get_kind_name(int $kind)`
54 * `ast\kind_uses_flags(int $kind)`
55 * `ast\get_metadata()`
56 * `ast\get_supported_versions(bool $exclude_deprecated = false)`
57
58Basic usage
59-----------
60
61Code can be parsed using either `ast\parse_code()`, which accepts a code string, or
62`ast\parse_file()`, which accepts a file path. Additionally, both functions require a `$version`
63argument to ensure forward-compatibility. The current version is 110.
64
65```php
66$ast = ast\parse_code('<?php ...', $version=100);
67// or
68$ast = ast\parse_file('file.php', $version=100);
69```
70
71The abstract syntax tree returned by these functions consists of `ast\Node` objects.
72`ast\Node` is declared as follows:
73
74```php
75namespace ast;
76class Node {
77    public $kind;
78    public $flags;
79    public $lineno;
80    public $children;
81}
82```
83
84The `kind` property specifies the type of the node. It is an integral value, which corresponds to
85one of the `ast\AST_*` constants, for example `ast\AST_STMT_LIST`. See the
86[AST node kinds section](#ast-node-kinds) for an overview of the available node kinds.
87
88The `flags` property contains node specific flags. It is always defined, but for most nodes it is
89always zero. See the [flags section](#flags) for a list of flags supported by the different node
90kinds.
91
92The `lineno` property specifies the *starting* line number of the node.
93
94The `children` property contains an array of child-nodes. These children can be either other
95`ast\Node` objects or plain values. There are two general categories of nodes: Normal AST nodes,
96which have a fixed set of named child nodes, as well as list nodes, which have a variable number
97of children. The [AST node kinds section](#ast-node-kinds) contains a list of the child names for
98the different node kinds.
99
100Example
101-------
102
103Simple usage example:
104
105```php
106<?php
107
108$code = <<<'EOC'
109<?php
110$var = 42;
111EOC;
112
113var_dump(ast\parse_code($code, $version=70));
114
115// Output:
116object(ast\Node)#1 (4) {
117  ["kind"]=>
118  int(132)
119  ["flags"]=>
120  int(0)
121  ["lineno"]=>
122  int(1)
123  ["children"]=>
124  array(1) {
125    [0]=>
126    object(ast\Node)#2 (4) {
127      ["kind"]=>
128      int(517)
129      ["flags"]=>
130      int(0)
131      ["lineno"]=>
132      int(2)
133      ["children"]=>
134      array(2) {
135        ["var"]=>
136        object(ast\Node)#3 (4) {
137          ["kind"]=>
138          int(256)
139          ["flags"]=>
140          int(0)
141          ["lineno"]=>
142          int(2)
143          ["children"]=>
144          array(1) {
145            ["name"]=>
146            string(3) "var"
147          }
148        }
149        ["expr"]=>
150        int(42)
151      }
152    }
153  }
154}
155```
156
157The [`util.php`][util] file defines an `ast_dump()` function, which can be used to create a more
158compact and human-readable dump of the AST structure:
159
160```php
161<?php
162
163require 'path/to/util.php';
164
165$code = <<<'EOC'
166<?php
167$var = 42;
168EOC;
169
170echo ast_dump(ast\parse_code($code, $version=70)), "\n";
171
172// Output:
173AST_STMT_LIST
174    0: AST_ASSIGN
175        var: AST_VAR
176            name: "var"
177        expr: 42
178```
179
180To additionally show line numbers pass the `AST_DUMP_LINENOS` option as the second argument to
181`ast_dump()`.
182
183A more substantial AST dump can be found [in the tests][test_dump].
184
185Metadata
186--------
187
188There are a number of functions which provide meta-information for the AST structure:
189
190`ast\get_kind_name()` returns a string name for an integral node kind.
191
192`ast\kind_uses_flags()` determines whether the `flags` of a node kind may ever be non-zero.
193
194`ast\get_metadata()` returns metadata about all AST node kinds. The return value is a map from AST
195node kinds to `ast\Metadata` objects defined as follows.
196
197```php
198namespace ast;
199class Metadata
200{
201    public $kind;
202    public $name;
203    public $flags;
204    public $flagsCombinable;
205}
206```
207
208The `kind` is the integral node kind, while `name` is the same name as returned by the
209`get_kind_name()` function.
210
211`flags` is an array of flag constant names, which may be used by the node kind. `flagsCombinable`
212specifies whether the flag should be checked using `===` (not combinable) or using `&` (combinable).
213Together these two values provide programmatic access to the information listed in the
214[flags section](#flags).
215
216The AST metadata is intended for use in tooling for working the AST, such as AST dumpers.
217
218Flags
219-----
220
221This section lists which flags are used by which AST node kinds. The "combinable" flags can be
222combined using bitwise or and should be checked by using `$ast->flags & ast\flags\FOO`. The
223"exclusive" flags are used standalone and should be checked using `$ast->flags === ast\flags\BAR`.
224
225```
226// Used by ast\AST_NAME (exclusive)
227ast\flags\NAME_FQ (= 0)    // example: \Foo\Bar
228ast\flags\NAME_NOT_FQ      // example: Foo\Bar
229ast\flags\NAME_RELATIVE    // example: namespace\Foo\Bar
230
231// Used by ast\AST_METHOD, ast\AST_PROP_DECL, ast\AST_PROP_GROUP,
232// ast\AST_CLASS_CONST_DECL, ast\AST_CLASS_CONST_GROUP, and ast\AST_TRAIT_ALIAS (combinable)
233ast\flags\MODIFIER_PUBLIC
234ast\flags\MODIFIER_PROTECTED
235ast\flags\MODIFIER_PRIVATE
236ast\flags\MODIFIER_STATIC
237ast\flags\MODIFIER_ABSTRACT
238ast\flags\MODIFIER_FINAL
239ast\flags\MODIFIER_READONLY
240
241// Used by ast\AST_CLOSURE, ast\AST_ARROW_FUNC (combinable)
242ast\flags\MODIFIER_STATIC
243
244// Used by ast\AST_FUNC_DECL, ast\AST_METHOD, ast\AST_CLOSURE, ast\AST_ARROW_FUNC (combinable)
245ast\flags\FUNC_RETURNS_REF  // legacy alias: ast\flags\RETURNS_REF
246ast\flags\FUNC_GENERATOR    // used only in PHP >= 7.1
247
248// Used by ast\AST_CLOSURE_VAR
249ast\flags\CLOSURE_USE_REF
250
251// Used by ast\AST_CLASS (combinable since PHP 8.1 enums)
252ast\flags\CLASS_ABSTRACT
253ast\flags\CLASS_FINAL
254ast\flags\CLASS_TRAIT
255ast\flags\CLASS_INTERFACE
256ast\flags\CLASS_ANONYMOUS
257ast\flags\CLASS_ENUM      // php 8.1 enums
258ast\flags\CLASS_READONLY  // php 8.2 readonly classes
259
260// Used by ast\AST_PARAM (combinable)
261ast\flags\PARAM_REF
262ast\flags\PARAM_VARIADIC
263ast\flags\PARAM_MODIFIER_PUBLIC (available since 1.0.8, same as ast\flags\MODIFIER_* in PHP >= 8.0)
264ast\flags\PARAM_MODIFIER_PROTECTED (available since 1.0.8)
265ast\flags\PARAM_MODIFIER_PRIVATE (available since 1.0.8)
266
267// Used by ast\AST_TYPE (exclusive)
268ast\flags\TYPE_ARRAY
269ast\flags\TYPE_CALLABLE
270ast\flags\TYPE_VOID
271ast\flags\TYPE_BOOL
272ast\flags\TYPE_LONG
273ast\flags\TYPE_DOUBLE
274ast\flags\TYPE_STRING
275ast\flags\TYPE_ITERABLE
276ast\flags\TYPE_OBJECT
277ast\flags\TYPE_NULL    // php 8.0 union types
278ast\flags\TYPE_FALSE   // php 8.0 union types
279ast\flags\TYPE_TRUE    // php 8.2 true type
280ast\flags\TYPE_STATIC  // php 8.0 static return type
281ast\flags\TYPE_MIXED   // php 8.0 mixed type
282ast\flags\TYPE_NEVER   // php 8.1 never type
283
284// Used by ast\AST_CAST (exclusive)
285ast\flags\TYPE_NULL
286ast\flags\TYPE_BOOL
287ast\flags\TYPE_LONG
288ast\flags\TYPE_DOUBLE
289ast\flags\TYPE_STRING
290ast\flags\TYPE_ARRAY
291ast\flags\TYPE_OBJECT
292
293// Used by ast\AST_UNARY_OP (exclusive)
294ast\flags\UNARY_BOOL_NOT
295ast\flags\UNARY_BITWISE_NOT
296ast\flags\UNARY_MINUS
297ast\flags\UNARY_PLUS
298ast\flags\UNARY_SILENCE
299
300// Used by ast\AST_BINARY_OP and ast\AST_ASSIGN_OP (exclusive)
301ast\flags\BINARY_BITWISE_OR
302ast\flags\BINARY_BITWISE_AND
303ast\flags\BINARY_BITWISE_XOR
304ast\flags\BINARY_CONCAT
305ast\flags\BINARY_ADD
306ast\flags\BINARY_SUB
307ast\flags\BINARY_MUL
308ast\flags\BINARY_DIV
309ast\flags\BINARY_MOD
310ast\flags\BINARY_POW
311ast\flags\BINARY_SHIFT_LEFT
312ast\flags\BINARY_SHIFT_RIGHT
313ast\flags\BINARY_COALESCE
314
315// Used by ast\AST_BINARY_OP (exclusive)
316ast\flags\BINARY_BOOL_AND
317ast\flags\BINARY_BOOL_OR
318ast\flags\BINARY_BOOL_XOR
319ast\flags\BINARY_IS_IDENTICAL
320ast\flags\BINARY_IS_NOT_IDENTICAL
321ast\flags\BINARY_IS_EQUAL
322ast\flags\BINARY_IS_NOT_EQUAL
323ast\flags\BINARY_IS_SMALLER
324ast\flags\BINARY_IS_SMALLER_OR_EQUAL
325ast\flags\BINARY_IS_GREATER
326ast\flags\BINARY_IS_GREATER_OR_EQUAL
327ast\flags\BINARY_SPACESHIP
328
329// Used by ast\AST_MAGIC_CONST (exclusive)
330ast\flags\MAGIC_LINE
331ast\flags\MAGIC_FILE
332ast\flags\MAGIC_DIR
333ast\flags\MAGIC_NAMESPACE
334ast\flags\MAGIC_FUNCTION
335ast\flags\MAGIC_METHOD
336ast\flags\MAGIC_CLASS
337ast\flags\MAGIC_TRAIT
338
339// Used by ast\AST_USE, ast\AST_GROUP_USE and ast\AST_USE_ELEM (exclusive)
340ast\flags\USE_NORMAL
341ast\flags\USE_FUNCTION
342ast\flags\USE_CONST
343
344// Used by ast\AST_INCLUDE_OR_EVAL (exclusive)
345ast\flags\EXEC_EVAL
346ast\flags\EXEC_INCLUDE
347ast\flags\EXEC_INCLUDE_ONCE
348ast\flags\EXEC_REQUIRE
349ast\flags\EXEC_REQUIRE_ONCE
350
351// Used by ast\AST_ARRAY (exclusive), since PHP 7.1
352ast\flags\ARRAY_SYNTAX_SHORT
353ast\flags\ARRAY_SYNTAX_LONG
354ast\flags\ARRAY_SYNTAX_LIST
355
356// Used by ast\AST_ARRAY_ELEM (exclusive)
357ast\flags\ARRAY_ELEM_REF
358
359// Used by ast\AST_DIM (combinable), since PHP 7.4
360ast\flags\DIM_ALTERNATIVE_SYNTAX
361ast\flags\ENCAPS_VAR_DOLLAR_CURLY  // php 8.2 deprecation, only available in php 8.2+
362
363// Used by ast\AST_VAR (combinable), since PHP 8.2
364ast\flags\ENCAPS_VAR_DOLLAR_CURLY
365ast\flags\ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR
366
367// Used by ast\AST_CONDITIONAL (combinable), since PHP 7.4
368ast\flags\PARENTHESIZED_CONDITIONAL
369```
370
371AST node kinds
372--------------
373
374This section lists the AST node kinds that are supported and the names of their child nodes.
375
376```
377AST_ARRAY_ELEM:           value, key
378AST_ARROW_FUNC:           name, docComment, params, stmts, returnType, attributes // name removed in version 110
379AST_ASSIGN:               var, expr
380AST_ASSIGN_OP:            var, expr
381AST_ASSIGN_REF:           var, expr
382AST_ATTRIBUTE:            class, args            // php 8.0+ attributes (version 80+)
383AST_BINARY_OP:            left, right
384AST_BREAK:                depth
385AST_CALL:                 expr, args
386AST_CALLABLE_CONVERT:                            // php 8.1+ first-class callable syntax
387AST_CAST:                 expr
388AST_CATCH:                class, var, stmts
389AST_CLASS:                name, docComment, extends, implements, stmts, (for enums) type
390AST_CLASS_CONST:          class, const
391AST_CLASS_CONST_GROUP     class, attributes, type // version 80+
392AST_CLASS_NAME:           class                   // version 70+
393AST_CLONE:                expr
394AST_CLOSURE:              name, docComment, params, uses, stmts, returnType, attributes // name removed in version 110
395AST_CLOSURE_VAR:          name
396AST_CONDITIONAL:          cond, true, false
397AST_CONST:                name
398AST_CONST_ELEM:           name, value, docComment
399AST_CONTINUE:             depth
400AST_DECLARE:              declares, stmts
401AST_DIM:                  expr, dim
402AST_DO_WHILE:             stmts, cond
403AST_ECHO:                 expr
404AST_EMPTY:                expr
405AST_ENUM_CASE:            name, expr, docComment, attributes // php 8.1+ enums
406AST_EXIT:                 expr
407AST_FOR:                  init, cond, loop, stmts
408AST_FOREACH:              expr, value, key, stmts
409AST_FUNC_DECL:            name, docComment, params, stmts, returnType, attributes
410                          uses                   // prior to version 60
411AST_GLOBAL:               var
412AST_GOTO:                 label
413AST_GROUP_USE:            prefix, uses
414AST_HALT_COMPILER:        offset
415AST_IF_ELEM:              cond, stmts
416AST_INCLUDE_OR_EVAL:      expr
417AST_INSTANCEOF:           expr, class
418AST_ISSET:                var
419AST_LABEL:                name
420AST_MAGIC_CONST:
421AST_MATCH:                cond, stmts            // php 8.0+ match
422AST_MATCH_ARM:            cond, expr             // php 8.0+ match
423AST_METHOD:               name, docComment, params, stmts, returnType, attributes
424                          uses                   // prior to version 60
425AST_METHOD_CALL:          expr, method, args
426AST_METHOD_REFERENCE:     class, method
427AST_NAME:                 name
428AST_NAMED_ARG:            name, expr             // php 8.0 named parameters
429AST_NAMESPACE:            name, stmts
430AST_NEW:                  class, args
431AST_NULLABLE_TYPE:        type                   // Used only since PHP 7.1
432AST_NULLSAFE_METHOD_CALL: expr, method, args     // php 8.0 null safe operator
433AST_NULLSAFE_PROP:        expr, prop             // php 8.0 null safe operator
434AST_PARAM:                type, name, default, attributes, docComment, hooks // 'hooks' field added in version 110
435AST_POST_DEC:             var
436AST_POST_INC:             var
437AST_PRE_DEC:              var
438AST_PRE_INC:              var
439AST_PRINT:                expr
440AST_PROP:                 expr, prop
441AST_PROP_ELEM:            name, default, docComment, hooks // 'hooks' field added in version 110
442AST_PROP_GROUP:           type, props, attributes // version 70+
443AST_PROPERTY_HOOK:        name, docComment, params, stmts, attributes // version 110+
444AST_PROPERTY_HOOK_SHORT_BODY: expr
445AST_REF:                  var                    // only used in foreach ($a as &$v)
446AST_RETURN:               expr
447AST_SHELL_EXEC:           expr
448AST_STATIC:               var, default
449AST_STATIC_CALL:          class, method, args
450AST_STATIC_PROP:          class, prop
451AST_SWITCH:               cond, stmts
452AST_SWITCH_CASE:          cond, stmts
453AST_THROW:                expr
454AST_TRAIT_ALIAS:          method, alias
455AST_TRAIT_PRECEDENCE:     method, insteadof
456AST_TRY:                  try, catches, finally
457AST_TYPE:
458AST_UNARY_OP:             expr
459AST_UNPACK:               expr
460AST_UNSET:                var
461AST_USE_ELEM:             name, alias
462AST_USE_TRAIT:            traits, adaptations
463AST_VAR:                  name
464AST_WHILE:                cond, stmts
465AST_YIELD:                value, key
466AST_YIELD_FROM:           expr
467
468// List nodes (numerically indexed children):
469AST_ARG_LIST
470AST_ARRAY
471AST_ATTRIBUTE_LIST        // php 8.0+ attributes (version 80+)
472AST_ATTRIBUTE_GROUP       // php 8.0+ attributes (version 80+)
473AST_CATCH_LIST
474AST_CLASS_CONST_DECL
475AST_CLOSURE_USES
476AST_CONST_DECL
477AST_ENCAPS_LIST           // interpolated string: "foo$bar"
478AST_EXPR_LIST
479AST_IF
480AST_LIST
481AST_MATCH_ARM_LIST        // php 8.0+ match
482AST_NAME_LIST
483AST_PARAM_LIST
484AST_PROP_DECL
485AST_STMT_LIST
486AST_SWITCH_LIST
487AST_TRAIT_ADAPTATIONS
488AST_USE
489AST_TYPE_UNION            // php 8.0+ union types
490AST_TYPE_INTERSECTION     // php 8.1+ intersection types
491```
492
493AST Versioning
494--------------
495
496The `ast\parse_code()` and `ast\parse_file()` functions each accept a required AST `$version`
497argument. The idea behind the AST version is that we may need to change the format of the AST to
498account for new features in newer PHP versions, or to improve it in other ways. Such changes will
499always be made under a new AST version, while previous formats continue to be supported for some
500time.
501
502Old AST versions may be deprecated in minor versions and removed in major versions of the AST extension.
503
504A list of currently supported versions is available through `ast\get_supported_versions()`. The
505function accepts a boolean argument that determines whether deprecated versions should be excluded.
506
507In the following the changes in the respective AST versions, as well as their current support state,
508are listed.
509
510### 110 (current)
511
512Supported since 1.1.2 (2024-08-10).
513
514* Add a `hooks` child node for `AST_PROP_ELEM` (PHP 8.4 property hooks) and `AST_PARAM` (constructor property promotion can have property hooks)
515* Add new node kinds `AST_PROPERTY_HOOK` and `AST_PROPERTY_HOOK_SHORT_BODY`.
516* Remove the `name` child node from the `AST_ARROW_FUNC` and `AST_CLOSURE` nodes (previously `"{closure}"`)
517
518### 100 (stable)
519
520Supported since 1.1.1 (2023-11-12).
521
522* Add a `type` child node for all `AST_CLASS_CONST_GROUP` nodes.
523
524### 90 (stable)
525
526Supported since 1.0.14 (2021-07-24)
527
528* Same as AST version 85.
529
530### 85 (stable)
531
532Supported since 1.0.11 (2021-04-20)
533
534* Add a `type` child node (for enum type) for all `AST_CLASS` nodes.
535
536### 80 (stable)
537
538Supported since 1.0.10 (2020-09-12).
539
540* `mixed` type hints are now reported as an `AST_TYPE` with type `TYPE_MIXED` instead of an `AST_NAME`.
541* `AST_CLASS_CONST_GROUP` nodes are emitted for class constant declarations wrapping the `AST_CLASS_CONST_DECL` and any attributes.
542  Previously, `AST_CLASS_CONST_DECL` would be emitted.
543* `AST_PARAM`, `AST_CLASS_DECL`, `AST_METHOD`, `AST_PROP_DECL`, `AST_CLOSURE`, `AST_FUNC_DECL`, and `AST_ARROW_FUNC` nodes
544  now contain an attributes child.
545
546### 70 (stable)
547
548Supported since 1.0.1 (2019-02-11).
549
550* `AST_PROP_GROUP` was added to support PHP 7.4's typed properties.
551  The property visibility modifiers are now part of `AST_PROP_GROUP` instead of `AST_PROP_DECL`.
552
553  Note that property group type information is only available with AST versions 70+.
554* `AST_CLASS_NAME` is created instead of `AST_CLASS_CONST` for `SomeClass::class`.
555
556### 60 (deprecated)
557
558Supported since 0.1.7 (2018-10-06).
559Deprecated in php-ast 1.1.0.
560
561* `AST_FUNC_DECL` and `AST_METHOD` no longer generate a `uses` child. Previously this child was
562  always `null`.
563* `AST_CONST_ELEM` now always has a `docComment` child. Previously it was absent on PHP 7.0.
564  On PHP 7.0 the value is always `null`.
565
566### 50 (deprecated)
567
568Supported since 0.1.5 (2017-07-19).
569Deprecated in php-ast 1.1.0.
570
571This is the oldest AST version available in 1.0.0. See the
572[0.1.x AST version changelog][v0_1_x_versions] for information on changes prior to this version.
573
574Differences to PHP-Parser
575-------------------------
576
577Next to php-ast I also maintain the [PHP-Parser][php-parser] library, which has some overlap with
578this extension. This section summarizes the main differences between php-ast and PHP-Parser so you
579may decide which is preferable for your use-case.
580
581The primary difference is that php-ast is a PHP extension (written in C) which exports the AST
582internally used by PHP 7 and 8. PHP-Parser on the other hand is library written in PHP. This has a number
583of consequences:
584
585 * php-ast is significantly faster than PHP-Parser, because the AST construction is implemented in
586   C.
587 * php-ast needs to be installed as an extension, on Linux either by compiling it manually or
588   retrieving it from a package manager, on Windows by loading a DLL. PHP-Parser is installed as a
589   Composer dependency.
590 * php-ast only runs on PHP >= 7.0 (php-ast 1.0.16 was the last version supporting php <= 7.1), as prior versions did not use an internal AST. PHP-Parser
591   supports PHP >= 5.5.
592 * php-ast may only parse code that is syntactically valid on the version of PHP it runs on. This
593   means that it's not possible to parse code using features of newer versions (e.g. PHP 7.4 code
594   while running on PHP 7.2). Similarly, it is not possible to parse code that is no longer
595   syntactically valid on the used version (e.g. some PHP 5 code may no longer be parsed -- however
596   most code will work). PHP-Parser supports parsing both newer and older (up to PHP 5.2) versions.
597 * php-ast can only parse code which is syntactically valid, while PHP-Parser can provide a partial
598   AST for code that contains errors (e.g., because it is currently being edited).
599 * php-ast only provides the starting line number (and for declarations the ending line number) of
600   nodes, because this is the only part that PHP itself stores. PHP-Parser provides precise file
601   offsets.
602
603There are a number of differences in the AST representation and available support code:
604
605 * The PHP-Parser library uses a separate class for every node type, with child nodes stored as
606   type-annotated properties. php-ast uses one class for everything, with children stored as
607   arrays. The former approach is friendlier to developers because it has very good IDE integration.
608   The php-ast extension does not use separate classes, because registering hundreds of classes was
609   judged a no-go for a bundled extension.
610 * The PHP-Parser library contains various support code for working with the AST, while php-ast only
611   handles AST construction. The reason for this is that implementing this support code in C is
612   extremely complicated and there is little other benefit to implementing it in C. The main
613   components that PHP-Parser offers that may be of interest are:
614    * Node dumper (human readable representation): While the php-ast extension does not directly
615      implement this, a `ast_dump` function is provided in the `util.php` file.
616    * Pretty printer (converting the AST back to PHP code): This is not provided natively, but the
617      [php-ast-reverter][php-ast-reverter] package implements this functionality.
618    * Name resolution (resolving namespace prefixes and aliases): There is currently no standalone
619      package for this.
620    * AST traversal / visitation: There is currently no standalone package for this either, but
621      implementing a recursive AST walk is easy.
622
623The [tolerant-php-parser-to-php-ast][tolerant-php-parser-to-php-ast] project can convert the AST produced by
624[tolerant-php-parser][tolerant-php-parser] (Another pure PHP parser library) into the format used by the php-ast extension.
625This can be used as a slow fallback in
626case the php-ast extension is not available. It may also be used to produce a partial php-ast output
627for code with syntax errors.
628
629  [parser]: http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_language_parser.y
630  [util]: https://github.com/nikic/php-ast/blob/master/util.php
631  [test_dump]: https://github.com/nikic/php-ast/blob/master/tests/001.phpt
632  [php-parser]: https://github.com/nikic/PHP-Parser
633  [php-ast-reverter]: https://github.com/tpunt/php-ast-reverter
634  [tolerant-php-parser]: https://github.com/Microsoft/tolerant-php-parser
635  [tolerant-php-parser-to-php-ast]: https://github.com/tysonandre/tolerant-php-parser-to-php-ast
636  [v0_1_x]: https://github.com/nikic/php-ast/tree/v0.1.x#php-ast
637  [v0_1_x_versions]: https://github.com/nikic/php-ast/tree/v0.1.x#ast-versioning
638