Name Date Size #Lines LOC

..28-Sep-2023-

.github/workflows/H17-Apr-2021-

ci/H27-Nov-2021-

scripts/H12-Nov-2023-

tests/H12-Nov-2023-

.appveyor.ymlH A D07-Aug-20229.3 KiB217207

.dockerignoreH A D17-Apr-2021448 4140

.editorconfigH A D22-Oct-2020369 2120

.gitignoreH A D06-Dec-2019396 3837

.travis.ymlH A D05-Apr-2021542 2621

LICENSEH A D06-Dec-20191.5 KiB3225

README.mdH A D12-Nov-202321.4 KiB627520

RELEASE_CHECKLISTH A D12-Nov-2023514 1413

ast.cH A D12-Nov-202345.7 KiB1,5741,325

ast.stub.phpH A D12-Feb-20221.4 KiB4213

ast_arginfo.hH A D12-Feb-20222.3 KiB6246

ast_data.cH A D12-Nov-202326.4 KiB681673

ast_str_defs.hH A D14-Jun-2020701 5552

ast_stub.phpH A D09-Aug-20228.7 KiB342245

config.m4H A D06-Dec-2019225 96

config.w32H A D06-Dec-2019135 95

package.xmlH A D12-Nov-202322.5 KiB616614

php_ast.hH A D12-Nov-20232.8 KiB10967

util.phpH A D09-Aug-20222.4 KiB8673

README.md

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