nikic/PHP-Parser
71.6
Strong · 26 September 2026
22.1k
lines of production code
PHP
primary language
4
measurements over time
What this system is
This system is a PHP parser library that converts PHP source code into an Abstract Syntax Tree (AST) and can regenerate source code from that tree. It supports parsing and generating code for PHP versions ranging from 7.4 through 8.5, including modern features like enums, attributes, and property hooks. The library provides tools for programmatic AST construction, format-preserving code modification, and robust error recovery during parsing.
How it got here
2011–2012 — Initial scaffolding and parser foundation
16 changes.
The project established its development infrastructure, including coding standards, static analysis, and dependency management, while completely restructuring the parser engine by removing legacy components. This period focused on rebuilding the grammar and node representation from scratch, supported by comprehensive test suites covering PHP 7.4 through 8.4 syntax features.
2014 — PHP 8+ AST and Builder Modernization
20 changes.
The PhpParser library underwent a comprehensive overhaul to support modern PHP versions (8.0–8.4), introducing a redesigned AST with dedicated node classes for new syntaxes like enums, attributes, and property hooks. A fluent Builder API was rewritten to facilitate programmatic AST construction, while an emulative lexer and new node visitors enhanced parsing flexibility and traversal capabilities. The update also included a standard pretty printer and extensive test coverage to ensure accuracy and backward compatibility.
2015–2023 — PHP 7-8 parser support and format preservation
15 changes.
The project implemented dedicated parser and lexer support for PHP 7 and PHP 8 features, including modern syntax like enums, match expressions, and nullsafe operators. It introduced internal infrastructure for format-preserving pretty printing using a Myers diff algorithm to maintain original code layout during AST modifications. Extensive test coverage was added to validate these new parsing capabilities, error recovery mechanisms, and the round-trip fidelity of the pretty printer.
Features
Add support for \_\_PROPERTY\_\_ magic constant
The parser now recognizes the \\_\PROPERTY\\\ magic constant, represented by the new \Scalar\\MagicConst\\Property\ class. This change extends the existing set of supported magic constants (such as \\\CLASS\\\, \\\DIR\\\, \\\FILE\\\, \\\FUNCTION\\\, \\\LINE\\\, \\\METHOD\\\, \\\NAMESPACE\\\, and \\\TRAIT\\_\) to include property context, allowing accurate parsing of PHP code that utilizes this constant.
lib/PhpParser/Node/Scalar/MagicConst · high confidence
Added PHP 7 and PHP 8 parser implementations
The library now includes dedicated parser classes for PHP 7 and PHP 8 syntax, allowing users to parse code specific to these versions. These generated parser classes (\Php7\ and \Php8\) extend the base \ParserAbstract\ and define version-specific token constants and parsing tables, enabling accurate AST generation for PHP 7 and PHP 8 features.
lib/PhpParser/Parser · high confidence
Added PHP-Parser fuzzing infrastructure
New tools have been added to the repository to support fuzzing the PHP-Parser library. This includes a corpus generation script (generateCorpus.php) that extracts test inputs from existing parser and pretty-printer tests, a dictionary file (php.dict) containing PHP keywords and constructs to guide the fuzzer, and a target script (target.php) that configures the php-fuzzer to parse code, pretty-print it, and verify that the AST remains identical after round-tripping. The target also handles specific edge cases like clone expressions and group use statements to ensure robust testing.
tools · high confidence
Emulative lexer supports bidirectional PHP version emulation
The lexer now includes an Emulative class that allows tokenizing PHP code for a target version different from the host runtime. It automatically detects whether forward emulation (host older than target) or reverse emulation (host newer than target) is needed and applies the appropriate token emulators, such as those for match expressions, nullsafe operators, attributes, and readonly modifiers, ensuring accurate parsing across PHP version mismatches.
lib/PhpParser/Lexer · high confidence
Expanded lexer emulation for modern PHP syntax features
The lexer now supports token emulation for a wide range of newer PHP language features, enabling the parser to handle code written for PHP 8.0 through 8.5 on older runtimes. This includes support for PHP 8.0 features such as the nullsafe operator (?-\>), match expressions, and the \#\[ attribute syntax; PHP 8.1 additions like enums, explicit octal literals (0o...), and readonly properties (including handling readonly as a function name); and PHP 8.4/8.5 capabilities including asymmetric visibility modifiers (e.g., public(set)), the \_\property\\_ magic constant, the pipe operator (\|\>), and the void cast operator ((void)). A new KeywordEmulator base class and ReverseEmulator wrapper were introduced to streamline and unify these emulation implementations.
lib/PhpParser/Lexer/TokenEmulator · high confidence
Initial project scaffolding and configuration
The repository is initialized with essential configuration files to standardize development and distribution. An .editorconfig enforces consistent coding styles (UTF-8, LF line endings, 4-space indentation). A .gitattributes file defines export-ignores to exclude development artifacts (tests, docs, tools, CI configs) from release archives. A .gitignore file excludes local IDE and build caches. Coding standards are enforced via a PHP-CS-Fixer configuration based on PSR-12. Static analysis is configured with PHPStan (level 6) and a baseline file. Testing is set up with a PHPUnit configuration. Additionally, a Makefile provides shortcuts for running PHPStan, PHP-CS-Fixer, and tests, and a comprehensive CONTRIBUTING.md guide outlines the process for adding new syntax support.
(repo-wide) · high confidence
Internal refactoring for format-preserving pretty printing
The library introduces several internal classes in the PhpParser\\Internal namespace to support format-preserving pretty printing (FPPP). This includes a Myers diff algorithm implementation (Differ, DiffElem) to calculate edit scripts for code changes, a TokenStream class to manage token positions and indentation, and a TokenPolyfill to normalize tokenization across PHP versions. Additionally, a PrintableNewAnonClassNode is added to correctly handle the token offset ordering of anonymous classes during printing.
lib/PhpParser/Internal · high confidence
Introduce Standard pretty printer with support for modern PHP syntax
The library now includes a new \PrettyPrinter\\Standard\ class that handles the generation of PHP code from AST nodes. This implementation adds support for modern PHP features including union and intersection types, named arguments, attributes, and property hooks. It also correctly formats complex string literals (including heredocs and nowdocs with flexible indentation) and ensures proper precedence handling for operators like null coalescing and spaceship.
lib/PhpParser/PrettyPrinter · high confidence
Introduce php-parse CLI tool with error recovery and stdin support
Adds a new \bin/php-parse\ executable that parses PHP source code into an abstract syntax tree and supports multiple output operations including node dumping, pretty-printing, JSON serialization, and name resolution. The tool now allows parsing from standard input (using \-\ as a filename) and includes an error recovery mode (\--with-recovery\) that continues parsing despite syntax errors while reporting them to stderr, rather than failing immediately. It also supports specifying the target PHP version for parsing and displays detailed column information for errors when requested.
bin · high confidence
New AST node visitors for cloning, finding, and parent/sibling linking
Added several new node visitors to the library: CloningVisitor creates deep copies of AST nodes while linking them to their originals via an 'origNode' attribute (required for format-preserving pretty printing); CommentAnnotatingVisitor attaches comment nodes to AST elements based on token positions; FindingVisitor and FirstFindingVisitor allow users to locate all or the first nodes matching a custom filter callback; NodeConnectingVisitor links child nodes to their parents and siblings (previous/next) using attributes, with optional weak references to avoid memory leaks; and ParentConnectingVisitor provides a simpler version that only links to the parent node. These visitors enhance the ability to traverse, analyze, and manipulate PHP ASTs with better context awareness and immutability support.
lib/PhpParser/NodeVisitor · high confidence
PHP 8.0+ syntax support in the AST
The AST node definitions in \lib/PhpParser/Node/Expr\ have been updated to support modern PHP syntax. This includes new nodes for arrow functions (\ArrowFunction\), match expressions (\Match\\), throw expressions (\Throw\\), and the nullsafe operator (\NullsafeMethodCall\, \NullsafePropertyFetch\). Call expressions (\FuncCall\, \MethodCall\, \StaticCall\, \New\_\) now extend a \CallLike\ base class to support partial function application and first-class callables. Additionally, \ClassConstFetch\ now supports dynamic class constant fetches.
lib/PhpParser/Node/Expr · high confidence
PHP 8.4 language features: property hooks and asymmetric visibility
The AST node definitions in lib/PhpParser/Node/Stmt have been updated to support PHP 8.4 syntax. The Property node now includes a $hooks array to represent property hooks and new flags (PUBLIC\_SET, PROTECTED\_SET, PRIVATE\SET) to model asymmetric visibility modifiers. Additionally, the ClassLike node now provides getTraitUses() to retrieve trait usage statements, and the Class\ node includes an isReadonly() method to check for readonly class declarations.
lib/PhpParser/Node/Stmt · high confidence
Removals
Removal of legacy Lexer, NodeAbstract, and Parser components
The \lib\ directory has removed the \Lexer.php\, \NodeAbstract.php\, and \Parser.php\ files. This eliminates the previous hand-written or generated lexer and parser infrastructure, along with the abstract node base class, from the library's public API.
lib · high confidence
Behavioural changes
AST node model overhaul with support for modern PHP features
The internal AST node structure has been completely redesigned to support newer PHP syntaxes and improve type safety. This update introduces dedicated node classes for PHP 8.0+ features, including \Attribute\ and \AttributeGroup\ for attributes, \PropertyHook\ for property hooks, and \MatchArm\ for match expressions. It also adds support for partial function application via \ArgPlaceholder\, first-class callables via \VariadicPlaceholder\, and complex type declarations through \NullableType\, \UnionType\, and \IntersectionType\. The \Name\ class now uses a string representation instead of an array of parts, and the \Param\ node has been expanded to handle constructor property promotion, visibility flags, and readonly modifiers. Additionally, several legacy node names have been updated (e.g., \DeclareDeclare\ to \DeclareItem\, \UseUse\ to \UseItem\) with backward-compatibility aliases provided.
lib/PhpParser/Node · high confidence
Add explicit getType() methods to AssignOp node classes
The AssignOp node classes in lib/PhpParser/Node/Expr/AssignOp now include explicit public getType() methods that return their specific node type strings (e.g., 'Expr\_AssignOp\_BitwiseAnd', 'Expr\_AssignOp\_Coalesce'). This change ensures consistent type identification across all assignment operation nodes, supporting features like the ??= operator and pow operator (PHP 5.6) mentioned in the commit history, while maintaining backward compatibility with existing code.
lib/PhpParser/Node/Expr/AssignOp · high confidence
Binary operators now have dedicated node classes
The library has refactored binary expression handling by introducing a distinct class for each operator (e.g., \BitwiseAnd\, \Coalesce\, \Spaceship\, \Pow\) under \PhpParser\\Node\\Expr\\BinaryOp\. Each class implements \getOperatorSigil()\ to return the specific symbol (such as \??\, \\<=\>\, or \\\\) and \getType()\ to provide a unique type identifier. This change replaces the previous monolithic approach, allowing consumers to identify and handle specific binary operations more precisely.
lib/PhpParser/Node/Expr/BinaryOp · high confidence
Cast nodes split into dedicated classes with explicit kind constants
The \lib/PhpParser/Node/Expr/Cast\ directory now contains separate classes for each cast type (\Array\\, \Bool\\, \Double\, \Int\\, \Object\\, \String\\, \Unset\\, \Void\\), replacing the previous monolithic structure. This change introduces specific \KIND\\*\ constants to distinguish between PHP syntax variants (e.g., \bool\ vs \boolean\, \int\ vs \integer\, \float\/\double\/\real\, \string\ vs \binary\), allowing users to precisely identify the exact cast syntax used in the source code rather than just the target type.
lib/PhpParser/Node/Expr/Cast · high confidence
Comprehensive rewrite of the PHP code builder API
The builder classes in lib/PhpParser/Builder have been completely rewritten to support modern PHP features and provide a more consistent, fluent API. This update introduces dedicated builders for new language constructs, including enums (Enum\_, EnumCase), readonly classes, and typed class constants. It also adds support for PHP 8.1+ features such as constructor property promotion (via visibility modifiers on ParamBuilder), asymmetric visibility (makePrivateSet/makeProtectedSet), and property hooks. The API has been unified with consistent method naming (e.g., setType, addAttribute) and improved type handling, allowing users to generate code for the latest PHP versions with greater precision and ease.
lib/PhpParser/Builder · high confidence
Grammar files restructured and preprocessor updated
The grammar directory has been reorganized: the old \zend\_language\parser.\\ files and the \analyzer.php\ tool have been removed, while new files \php.y\, \parser.template\, and \rebuildParsers.php\ have been added to define and build the parser. The preprocessor script (renamed to \phpyLang.php\) has been updated to support these new grammar constructs, including changes to how node creation and macros are resolved.
grammar · high confidence
PhpParser library refactored with modern PHP 8+ features and expanded builder support
The PhpParser library has been significantly refactored to target PHP 8.0+, introducing a new Builder API for constructing AST nodes programmatically (including builders for classes, interfaces, traits, enums, and use statements) and a ConstExprEvaluator for evaluating constant expressions at runtime. The internal architecture has been modernized with strict typing, the introduction of a Modifiers class for handling visibility and other modifiers, and a new ErrorHandler interface with Collecting and Throwing implementations. Additionally, the library now supports PHP 8.4 features such as asymmetric visibility modifiers and property hooks, and improves error reporting with column information.
lib/PhpParser · high confidence
Removal of legacy PHP parser node classes
The \lib/Node\ directory has been completely cleared of all previously existing PHP parser node classes (such as \Node\_ClassStmt\, \Node\_FuncStmt\, and \Node\_Expr\ variants). These files, which previously defined the AST node structure for the parser, have been deleted, indicating a significant restructuring or migration of the parser's internal node representation.
lib/Node · high confidence
Renamed scalar AST nodes and added support for modern PHP numeric/string syntax
The scalar node classes have been renamed to align with PHP 7 type naming conventions: \LNumber\ is now \Int\\, \DNumber\ is now \Float\\, \Encapsed\ is now \InterpolatedString\, and \EncapsedStringPart\ is now \InterpolatedStringPart\. Deprecated compatibility aliases are provided for existing code. These nodes now support modern PHP features, including numeric literal separators (underscores) in integers and floats, explicit octal prefixes (\0o\), binary literals, and PHP 7 Unicode escape sequences (\\\u{...}\) in strings. The \Int\\ node exposes a \kind\ attribute to distinguish between decimal, octal, hex, and binary literals, while \Float\\ and \String\_\ nodes expose a \rawValue\ attribute preserving the original source representation.
lib/PhpParser/Node/Scalar · high confidence
Test coverage
Added comprehensive test suite for PhpParser components; Added dedicated test classes for PHP 7 and PHP 8 parsers; Added function statement parser tests; Added parser statement tests for PHP 8.0+ features and syntax updates; Added parser tests for Uniform Variable Syntax (UVS) expressions; Added parser tests for comment handling, reserved keywords, and formatting attributes; Added parser tests for fetch and call expressions; Added parser tests for generator yield expressions; Added parser tests for loop statements; Added parser tests for namespace and use statement handling; Added parser tests for scalar literals and string handling; Added test coverage for PHP 8.4 class statement parsing; Added test coverage for the pretty printer; Added test infrastructure and code parsing test utilities; Added tests for CallLike node behavior; Added tests for NodeVisitor utilities; Added tests for parser error handling and recovery; Added tests for scalar node raw value attributes and magic constant methods; Added tests for the emulative lexer's keyword replacement and tokenization; Added tests for the internal Differ component; Added unit tests for Node classes; Added unit tests for PHP-Parser builder classes; Added unit tests for statement node modifiers and accessors; Expanded expression-level pretty printer test coverage; Expanded formatting-preservation test coverage for PHP 8+ syntax; Expanded pretty-printer test coverage for statement-level PHP features; Expanded test coverage for PHP expression parsing; New test runner for php-src integration tests.
Dependencies
Initial composer.json setup with PHP 7.4+ and PHPUnit 9 requirements
This change introduces the project's dependency manifest (composer.json), establishing a minimum PHP version of 7.4 and requiring the ext-tokenizer and ext-json extensions. It sets up PHPUnit 9 for development testing and configures PSR-4 autoloading for the library and its tests, while also defining a bin entry for the php-parse tool. A separate tools/composer.json is added to manage development utilities like php-cs-fixer and phpstan.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Score
- CAI 47 → 72 (+25.1)
- Rubric changed (rubric-2026.08.15 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 85 → 88 (+3.1)
- Architecture 94 → 100 (+5.6)
- Maturity 57 → 56 (-1.5)
- Readiness 27 → 80 (+53.0)
- Security 56 → 92 (+35.8)
Resolved (75)
- Coverage not measured — test suite did not build
- Dimension evaluation failed
- Duplicated block (10 lines × 2) (lib/PhpParser/Parser/Php7.php)
- Duplicated block (10 lines × 2) (lib/PhpParser/Parser/Php7.php)
- Duplicated block (10 lines × 2) (lib/PhpParser/Parser/Php7.php)
- Duplicated block (10 lines × 2) (lib/PhpParser/Parser/Php7.php)
- Duplicated block (10 lines × 2) (lib/PhpParser/Parser/Php8.php)
- Duplicated block (10 lines × 2) (lib/PhpParser/Parser/Php8.php)
- Duplicated block (10 lines × 2) (lib/PhpParser/Parser/Php8.php)
- Duplicated block (10 lines × 2) (lib/PhpParser/Parser/Php8.php)
- Duplicated block (16 lines × 4) (lib/PhpParser/Parser/Php7.php)
- Duplicated block (16 lines × 4) (lib/PhpParser/Parser/Php8.php)
- Duplicated block (5 lines × 2) (lib/PhpParser/Parser/Php7.php)
- Duplicated block (5 lines × 2) (lib/PhpParser/Parser/Php7.php)
- Duplicated block (5 lines × 2) (lib/PhpParser/Parser/Php7.php)
- Duplicated block (5 lines × 2) (lib/PhpParser/Parser/Php7.php)
- Duplicated block (5 lines × 2) (lib/PhpParser/Parser/Php7.php)
- Duplicated block (5 lines × 2) (lib/PhpParser/Parser/Php7.php)
- Duplicated block (5 lines × 2) (lib/PhpParser/Parser/Php8.php)
- Duplicated block (5 lines × 2) (lib/PhpParser/Parser/Php8.php)
- …and 55 more
New (111)
- BuilderHelpers.normalizeValue (cognitive 17) (lib/PhpParser/BuilderHelpers.php)
- Change coupling: DNumber.php ↔ LNumber.php (lib/PhpParser/Node/Scalar/DNumber.php)
- Change coupling: Php7.php ↔ Php8.php (lib/PhpParser/Parser/Php7.php)
- ClassTooLong: ParserAbstract (lib/PhpParser/ParserAbstract.php)
- ClassTooLong: Php7 (lib/PhpParser/Parser/Php7.php)
- ClassTooLong: Php8 (lib/PhpParser/Parser/Php8.php)
- ClassTooLong: PrettyPrinterAbstract (lib/PhpParser/PrettyPrinterAbstract.php)
- ClassTooLong: Standard (lib/PhpParser/PrettyPrinter/Standard.php)
- CommentAnnotatingVisitor.enterNode (cognitive 20) (lib/PhpParser/NodeVisitor/CommentAnnotatingVisitor.php)
- Consistent use of addStmt across all declaration builders. Declaration also provides addStmts for bulk addition, which is a helpful convenience method. No inconsistency.
- Differ.calculateTrace (cognitive 18) (lib/PhpParser/Internal/Differ.php)
- Differ.coalesceReplacements (cognitive 18) (lib/PhpParser/Internal/Differ.php)
- Documentation: no installation or build instructions (README.md)
- Documentation: no licence statement (README.md)
- Documentation: no usage examples (README.md)
- Duplicated block (10 lines × 2) (lib/PhpParser/Error.php)
- Duplicated block (10 lines × 2) (lib/PhpParser/Node/Stmt/Goto_.php)
- Duplicated block (11 lines × 2) (lib/PhpParser/Node/Expr/NullsafePropertyFetch.php)
- Duplicated block (11 lines × 3) (lib/PhpParser/Builder/Class_.php)
- Duplicated block (16 lines × 2) (lib/PhpParser/Node/Expr/MethodCall.php)
- …and 91 more
Changes since last survey
- 5 commits — 5 feature/other, 0 fixes
By area
- lib/PhpParser — 4 commits
- (root) — 1 commit
Notable commits
- change: Cheap check first in dereferenceLhsRequiresParens() (#1160)
- change: Implement support for partial function application
- change: Release PHP-Parser 5.9.0
- change: Suppress warning on hexdec/bindec/octdec overflow
- change: Use iteration over recursion in PrettyPrinterAbstract:: newOperandRequiresParens()
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
nikic/PHP-Parser was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 26 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 5d907dc3c30e379b9168436286e9a2c2f699a2dd — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-a9cd699f3cd5.