### Setup for PHP Namespaced Code Conversion Example Source: https://github.com/nikic/php-parser/blob/master/doc/2_Usage_of_basic_components.markdown This PHP snippet provides the initial setup for a code conversion example, demonstrating how to instantiate the necessary components from `nikic/php-parser`. It includes importing required classes, defining placeholder input/output directories, and initializing the parser, traverser, and pretty printer objects essential for AST manipulation. ```php use PhpParser\ParserFactory; use PhpParser\PrettyPrinter; use PhpParser\NodeTraverser; use PhpParser\NodeVisitor\NameResolver; $inDir = '/some/path'; $outDir = '/some/other/path'; $parser = (new ParserFactory())->createForNewestSupportedVersion(); $traverser = new NodeTraverser; $prettyPrinter = new PrettyPrinter\Standard; ``` -------------------------------- ### PHP-Parser Factory Method Usage Example Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Demonstrates the updated `ParserFactory` methods in PHP-Parser 5.0, showing how to replace old `create()` calls with `createForNewestSupportedVersion()`, `createForHostVersion()`, and `createForVersion()` for parsing PHP code. ```php use PhpParser\ParserFactory; use PhpParser\PhpVersion; $factory = new ParserFactory(); # Before $parser = $factory->create(ParserFactory::PREFER_PHP7); # After (this is roughly equivalent to PREFER_PHP7 behavior) $parser = $factory->createForNewestSupportedVersion(); # Or $parser = $factory->createForHostVersion(); # Before $parser = $factory->create(ParserFactory::ONLY_PHP5); # After (supported on a best-effort basis) $parser = $factory->createForVersion(PhpVersion::fromString("5.6")); ``` -------------------------------- ### Node Traverser Constructor with Visitors Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Illustrates a new, more concise way to initialize the `NodeTraverser`. Visitors can now be passed directly to the constructor, simplifying the setup boilerplate. The traditional `addVisitor()` method remains fully supported. ```php # Before (and still supported) $traverser = new NodeTraverser(); $traverser->addVisitor(new NameResolver()); # After $traverser = new NodeTraverser(new NameResolver()); ``` -------------------------------- ### PHP-Parser Initialization and Node Traversal (Before) Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Illustrates the previous method for initializing the PHP-Parser, including explicit Lexer configuration with 'usedAttributes' and separate 'NodeTraverser' and 'NodeVisitor\CloningVisitor' instantiation. ```PHP $lexer = new Lexer\Emulative([ 'usedAttributes' => [ 'comments', 'startLine', 'endLine', 'startTokenPos', 'endTokenPos', ], ]); $parser = new Parser\Php7($lexer); $oldStmts = $parser->parse($code); $oldTokens = $lexer->getTokens(); $traverser = new NodeTraverser(); $traverser->addVisitor(new NodeVisitor\CloningVisitor()); $newStmts = $traverser->traverse($oldStmts); ``` -------------------------------- ### Pretty Printer Operator Implementation Examples Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Illustrates how pretty printer methods for operators, such as binary and unary operations, should be adjusted. This involves passing the new `$precedence` and `$lhsPrecedence` arguments down to helper methods like `pInfixOp()` and `pPrefixOp()` to ensure correct precedence resolution. ```php protected function pExpr_BinaryOp_Plus( BinaryOp\Plus $node, int $precedence, int $lhsPrecedence ): string { return $this->pInfixOp( BinaryOp\Plus::class, $node->left, ' + ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_UnaryPlus( Expr\UnaryPlus $node, int $precedence, int $lhsPrecedence ): string { return $this->pPrefixOp(Expr\UnaryPlus::class, '+', $node->expr, $precedence, $lhsPrecedence); } ``` -------------------------------- ### PHP-Parser Initialization and Node Traversal (After) Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Demonstrates the updated approach for initializing the PHP-Parser using 'ParserFactory', retrieving tokens directly from the parser, and simplifying 'NodeTraverser' instantiation by passing the visitor directly to its constructor. ```PHP $parser = (new ParserFactory())->createForNewestSupportedVersion(); $oldStmts = $parser->parse($code); $oldTokens = $parser->getTokens(); $traverser = new NodeTraverser(new NodeVisitor\CloningVisitor()); $newStmts = $traverser->traverse($oldStmts); ``` -------------------------------- ### Pretty Printer Closure Use Statement Spacing Update Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Demonstrates the addition of a space between `use` and the following parenthesis for closures in the pretty printer's output, enhancing readability and adhering to common style guides. ```php # Before function () use($var) { }; # After function () use ($var) { }; ``` -------------------------------- ### Deprecated PHP-Parser Methods and Their Replacements Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Documents various deprecated methods across 'Builder\Param', 'Error', 'Comment', and 'Node' classes in the PHP-Parser library, providing their recommended replacements and usage notes for migration. ```APIDOC Builder\Param::setTypeHint() - Deprecated: Use Builder\Param::setType() instead. Error constructor - Deprecated: Constructor taking a start line has been removed. - Replacement: Pass ['startLine' => $startLine] attributes instead. Comment::getLine() Comment::getTokenPos() Comment::getFilePos() - Deprecated: Use Comment::getStartLine(), Comment::getStartTokenPos(), and Comment::getStartFilePos() respectively. Comment::getReformattedText() - Behavior Change: Now normalizes CRLF newlines to LF newlines. Node::getLine() - Deprecated: Use Node::getStartLine() instead. ``` -------------------------------- ### Example of PHP code generated from modified AST Source: https://github.com/nikic/php-parser/blob/master/README.md Shows the final PHP code output after converting the modified AST back to a string. This example reflects the AST modification where the function body was removed, resulting in an empty function definition in the generated PHP code. ```php tokens = $tokens; } public function leaveNode(PhpParser\Node $node) { if ($node instanceof PhpParser\Node\Stmt\Property) { var_dump(isDeclaredUsingVar($this->tokens, $node)); } } } $parser = (new PhpParser\ParserFactory())->createForHostVersion($lexerOptions); $visitor = new MyNodeVisitor(); $traverser = new PhpParser\NodeTraverser($visitor); try { $stmts = $parser->parse($code); $visitor->setTokens($parser->getTokens()); $stmts = $traverser->traverse($stmts); } catch (PhpParser\Error $e) { echo 'Parse Error: ', $e->getMessage(); } ``` -------------------------------- ### PHP-Parser 2.0 Parser Instantiation with Custom Lexer Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-2.0.md This snippet demonstrates how to create a PHP-Parser 2.0 instance using the `ParserFactory` while providing a custom lexer. The custom lexer is passed as the second argument to the `create()` method, allowing for specialized tokenization. The example uses `PREFER_PHP7` for parsing preference. ```php use PhpParser\ParserFactory; $lexer = new MyLexer; $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7, $lexer); ``` -------------------------------- ### Pretty Printer Modifier Order Formatting Update Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Shows the updated order of `abstract` and `final` modifiers, which are now printed before visibility modifiers by the pretty printer to align with modern PHP coding conventions. ```php # Before public abstract function test(); # After abstract public function test(); ``` -------------------------------- ### PHP-Parser 5.0 API Changes: Abstract Syntax Tree (AST) Representation Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Describes the modifications to how `throw` statements and array destructuring are represented in the Abstract Syntax Tree (AST) in PHP-Parser 5.0 for improved consistency. ```APIDOC Throw Statement Representation: - Before: `throw $e;` was represented as `Stmt\Throw_`. - After: `throw $e;` is now represented as `Stmt\Expression` containing `Expr\Throw_`. - The `Stmt\Throw_` class has been removed. Array Destructuring Representation: - Before: `list($x) = $y` used `Node\Expr\List_`; `[$x] = $y` used `Node\Expr\Array_`. - After: Both `list($x) = $y` and `[$x] = $y` are now consistently represented using `Node\Expr\List_`. - A `kind` attribute (`Node\Expr\List_::KIND_LIST` or `Node\Expr\List_::KIND_ARRAY`) specifies the original syntax used. ``` -------------------------------- ### Building Complex PHP Class AST with Fluent Builders Source: https://github.com/nikic/php-parser/blob/master/doc/component/AST_builders.markdown Demonstrates how to use `PhpParser\BuilderFactory` to programmatically construct a complex Abstract Syntax Tree (AST) for a PHP class. This includes defining namespaces, use statements, traits with adaptations, methods with parameters and doc comments, and properties. The example also shows how to convert the generated AST back into PHP code using `PrettyPrinter\Standard`. ```php use PhpParser\BuilderFactory; use PhpParser\PrettyPrinter; use PhpParser\Node; $factory = new BuilderFactory; $node = $factory->namespace('Name\Space') ->addStmt($factory->use('Some\Other\Thingy')->as('SomeClass')) ->addStmt($factory->useFunction('strlen')) ->addStmt($factory->useConst('PHP_VERSION')) ->addStmt($factory->class('SomeOtherClass') ->extend('SomeClass') ->implement('A\Few', '\Interfaces') ->makeAbstract() // ->makeFinal() ->addStmt($factory->useTrait('FirstTrait')) ->addStmt($factory->useTrait('SecondTrait', 'ThirdTrait') ->and('AnotherTrait') ->with($factory->traitUseAdaptation('foo')->as('bar')) ->with($factory->traitUseAdaptation('AnotherTrait', 'baz')->as('test')) ->with($factory->traitUseAdaptation('AnotherTrait', 'func')->insteadof('SecondTrait'))) ->addStmt($factory->method('someMethod') ->makePublic() ->makeAbstract() // ->makeFinal() ->setReturnType('bool') // ->makeReturnByRef() ->addParam($factory->param('someParam')->setType('SomeClass')) ->setDocComment('/** * This method does something. * * @param SomeClass And takes a parameter */') ) ->addStmt($factory->method('anotherMethod') ->makeProtected() // ->makePublic() [default], ->makePrivate() ->addParam($factory->param('someParam')->setDefault('test')) // it is possible to add manually created nodes ->addStmt(new Node\Expr\Print_(new Node\Expr\Variable('someParam'))) ) // properties will be correctly reordered above the methods ->addStmt($factory->property('someProperty')->makeProtected()) ->addStmt($factory->property('anotherProperty')->makePrivate()->setDefault(array(1, 2, 3))) ) ->getNode() ; $stmts = array($node); $prettyPrinter = new PrettyPrinter\Standard(); echo $prettyPrinter->prettyPrintFile($stmts); ``` -------------------------------- ### Node Traverser `leaveNode()` and `afterTraverse()` Order Change Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Demonstrates the revised execution order for `leaveNode()` and `afterTraverse()` methods when multiple visitors are registered with the node traverser. The updated behavior ensures these methods are now called in the reverse order of their corresponding `enterNode()` and `beforeTraverse()` calls. ```php # Before $visitor1->enterNode($node); $visitor2->enterNode($node); $visitor1->leaveNode($node); $visitor2->leaveNode($node); # After $visitor1->enterNode($node); $visitor2->enterNode($node); $visitor2->leaveNode($node); $visitor1->leaveNode($node); ``` -------------------------------- ### Example of Recursive Constant Definition in PHP Source: https://github.com/nikic/php-parser/blob/master/doc/component/Constant_expression_evaluation.markdown Demonstrates a scenario of mutually recursive constant definitions in PHP, which can lead to infinite recursion if not handled carefully by a constant lookup mechanism. ```php `. - Removed methods: `startLexing()`, `getNextToken()`. - Removed options array support. Parser-added Node Attributes (unconditional): - `comments`: array of comments associated with the node. - `startLine`: int, starting line number. - `endLine`: int, ending line number. - `startFilePos`: int, starting byte offset in the file. - `endFilePos`: int, ending byte offset in the file. - `startTokenPos`: int, starting token index. - `endTokenPos`: int, ending token index. ``` -------------------------------- ### Parse PHP Code with PhpParser and Error Handling Source: https://github.com/nikic/php-parser/blob/master/doc/2_Usage_of_basic_components.markdown This PHP example illustrates how to parse a string of PHP code into an Abstract Syntax Tree (AST) using PhpParser. It includes a `try-catch` block to gracefully handle `PhpParser\Error` exceptions that may occur during parsing due to syntax errors in the input code. ```php createForHostVersion(); try { $stmts = $parser->parse($code); // $stmts is an array of statement nodes } catch (Error $e) { echo 'Parse Error: ', $e->getMessage(), "\n"; } ``` -------------------------------- ### Run Multiple Node Visitors in Parallel on PHP AST Source: https://github.com/nikic/php-parser/blob/master/doc/component/Walking_the_AST.markdown This example shows how to add multiple visitors to a single `NodeTraverser` instance. When executed, the visitors will be interleaved, meaning `enterNode()` and `leaveNode()` are called for all visitors on each node. This approach improves performance by traversing the AST only once. ```php $traverser = new NodeTraverser; $traverser->addVisitor($visitorA); $traverser->addVisitor($visitorB); $stmts = $traverser->traverse($stmts); ``` -------------------------------- ### Applying NameResolver to AST Source: https://github.com/nikic/php-parser/blob/master/doc/component/Name_resolution.markdown This snippet demonstrates how to initialize and apply the `NameResolver` visitor to an Abstract Syntax Tree (AST) using `NodeTraverser`. It shows the basic setup required to resolve names within PHP code parsed by `php-parser`, transforming names to their fully-qualified form. ```php $nameResolver = new PhpParser\NodeVisitor\NameResolver; $nodeTraverser = new PhpParser\NodeTraverser; $nodeTraverser->addVisitor($nameResolver); // Resolve names $stmts = $nodeTraverser->traverse($stmts); ``` -------------------------------- ### Pretty Printer phpVersion Option and Behavior Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Details the new `phpVersion` option for the pretty printer, which accepts a `PhpVersion` object and defaults to PHP 7.4. This option controls various formatting choices to ensure the generated code is valid for the specified PHP version. ```APIDOC Pretty Printer `phpVersion` Option: - Accepts: `PhpVersion` object - Default: PHP 7.4 - Controls the following behaviors: - For PHP >= 7.0 (default), short array syntax `[]` will be used by default. This does not affect nodes that specify an explicit array syntax using the `kind` attribute. - For PHP >= 7.0 (default), parentheses around `yield` expressions will only be printed when necessary. Previously, parentheses were always printed, even if `yield` was used as a statement. - For PHP >= 7.1 (default), the short array syntax `[]` will be used for destructuring by default (instead of `list()`). This does not affect nodes that specify an explicit syntax using the `kind` attribute. - For PHP >= 7.3 (default), a newline is no longer forced after heredoc/nowdoc strings, as the requirement for this has been removed with the introduction of flexible heredoc/nowdoc strings. - For PHP >= 7.3 (default), heredoc/nowdoc strings are now indented just like regular code. This was allowed with the introduction of flexible heredoc/nowdoc strings. ``` -------------------------------- ### Node Traverser Return Value Constant Relocation Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Documents the relocation of special return value constants used by node visitors. These constants have been moved from `PhpParser\NodeTraverser` to `PhpParser\NodeVisitor`, promoting better separation of concerns. The old constants are deprecated but remain supported for backward compatibility. ```APIDOC PhpParser\NodeTraverser::REMOVE_NODE -> PhpParser\NodeVisitor::REMOVE_NODE PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN -> PhpParser\NodeVisitor::DONT_TRAVERSE_CHILDREN PhpParser\NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN -> PhpParser\NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN PhpParser\NodeTraverser::STOP_TRAVERSAL -> PhpParser\NodeVisitor::STOP_TRAVERSAL ``` -------------------------------- ### PHP-Parser AST: Renamed and Re-parented Nodes Reference Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Comprehensive list of AST nodes that have been renamed or moved within the AST hierarchy. Old class names are retained as aliases for backward compatibility, but the `Node::getType()` method now consistently returns the new names. ```APIDOC Node Renames and Hierarchy Changes: * `Node\Scalar\LNumber` is now `Node\Scalar\Int_`. * `Node\Scalar\DNumber` is now `Node\Scalar\Float_`. * `Node\Scalar\Encapsed` is now `Node\Scalar\InterpolatedString`. * `Node\Scalar\EncapsedStringPart` is now `Node\InterpolatedStringPart` and no longer extends `Node\Scalar` or `Node\Expr`. * `Node\Expr\ArrayItem` is now `Node\ArrayItem` and no longer extends `Node\Expr`. * `Node\Expr\ClosureUse` is now `Node\ClosureUse` and no longer extends `Node\Expr`. * `Node\Stmt\DeclareDeclare` is now `Node\DeclareItem` and no longer extends `Node\Stmt`. * `Node\Stmt\PropertyProperty` is now `Node\PropertyItem` and no longer extends `Node\Stmt`. * `Node\Stmt\StaticVar` is now `Node\StaticVar` and no longer extends `Node\Stmt`. * `Node\Stmt\UseUse` is now `Node\UseItem` and no longer extends `Node\Stmt`. Note: Old class names are aliased for backward compatibility. `Node::getType()` returns new names (e.g., `ClosureUse` instead of `Expr_ClosureUse`). ``` -------------------------------- ### Example of PHP Parser AST structure Source: https://github.com/nikic/php-parser/blob/master/README.md Illustrates the hierarchical structure of an Abstract Syntax Tree (AST) generated by PHP Parser. It shows how functions, parameters, and expressions are represented as various node types like `Stmt_Function`, `Param`, `Expr_Variable`, and `Expr_FuncCall`, including their attributes and nested structures. ```php array( 0: Stmt_Function( attrGroups: array( ) byRef: false name: Identifier( name: test ) params: array( 0: Param( attrGroups: array( ) flags: 0 type: null byRef: false variadic: false var: Expr_Variable( name: foo ) default: null ) ) returnType: null stmts: array( 0: Stmt_Expression( expr: Expr_FuncCall( name: Name( name: var_dump ) args: array( 0: Arg( name: null value: Expr_Variable( name: foo ) byRef: false unpack: false ) ) ) ) ) ) ) ``` -------------------------------- ### Finding AST Nodes with PHP-Parser NodeFinder Source: https://github.com/nikic/php-parser/blob/master/doc/component/Walking_the_AST.markdown This snippet demonstrates how to use `NodeFinder` in PHP-Parser to locate specific nodes within an Abstract Syntax Tree (AST) without the overhead of creating a full visitor. It provides examples for finding all instances of a particular class type, filtering nodes based on custom conditions, and efficiently finding the first occurrence of a node by type or name. ```php use PhpParser\{Node, NodeFinder}; $nodeFinder = new NodeFinder; // Find all class nodes. $classes = $nodeFinder->findInstanceOf($stmts, Node\Stmt\Class_::class); // Find all classes that extend another class $extendingClasses = $nodeFinder->find($stmts, function(Node $node) { return $node instanceof Node\Stmt\Class_ && $node->extends !== null; }); // Find first class occurring in the AST. Returns null if no class exists. $class = $nodeFinder->findFirstInstanceOf($stmts, Node\Stmt\Class_::class); // Find first class that has name $name $class = $nodeFinder->findFirst($stmts, function(Node $node) use ($name) { return $node instanceof Node\Stmt\Class_ && $node->resolvedName->toString() === $name; }); ``` -------------------------------- ### PHP-Parser AST: Explicit Block Node Introduction Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Demonstrates the introduction of an explicit `Stmt\Block` node for nested code blocks. Previously, nested blocks were flattened into their parent statement list; now, they are represented as distinct `Stmt\Block` nodes within the AST, improving structural fidelity and preserving block semantics. ```php while ($x) { $a; { $b; } $c; } ``` ```php-parser-ast # Before Stmt_While( cond: Expr_Variable( name: x ) stmts: array( 0: Stmt_Expression( expr: Expr_Variable( name: a ) ) 1: Stmt_Expression( expr: Expr_Variable( name: b ) ) 2: Stmt_Expression( expr: Expr_Variable( name: c ) ) ) ) ``` ```php-parser-ast # After Stmt_While( cond: Expr_Variable( name: x ) stmts: array( 0: Stmt_Expression( expr: Expr_Variable( name: a ) ) 1: Stmt_Block( stmts: array( 0: Stmt_Expression( expr: Expr_Variable( name: b ) ) ) ) 2: Stmt_Expression( expr: Expr_Variable( name: c ) ) ) ) ``` -------------------------------- ### Collecting PHP Parser Errors for Partial AST Generation Source: https://github.com/nikic/php-parser/blob/master/doc/component/Error_handling.markdown This example illustrates how to use `PhpParser\ErrorHandler\Collecting` to gather all parsing errors into an array instead of throwing exceptions immediately. This strategy allows the parser to continue processing and generate a best-effort partial Abstract Syntax Tree (AST), which can then be inspected for errors. ```php $parser = (new PhpParser\ParserFactory())->createForHostVersion(); $errorHandler = new PhpParser\ErrorHandler\Collecting; $stmts = $parser->parse($code, $errorHandler); if ($errorHandler->hasErrors()) { foreach ($errorHandler->getErrors() as $error) { // $error is an ordinary PhpParser\Error } } if (null !== $stmts) { // $stmts is a best-effort partial AST } ``` -------------------------------- ### Example AST Output for PHP Echo Statement Source: https://github.com/nikic/php-parser/blob/master/doc/0_Introduction.markdown This snippet illustrates the Abstract Syntax Tree (AST) generated by the PHP-Parser for the simple PHP code `getAttribute('parent')`, `$node->getAttribute('previous')`, and `$node->getAttribute('next')`. It also explains how to use the `$weakReferences` constructor parameter to prevent cyclic references, in which case attributes are accessed via `weak_parent`, `weak_previous`, and `weak_next`. ```php use PhpParser\NodeTraverser; use PhpParser\NodeVisitor\NodeConnectingVisitor; use PhpParser\ParserFactory; $code = '...'; $traverser = new NodeTraverser(new NodeConnectingVisitor); $parser = (new ParserFactory())->createForHostVersion(); $ast = $parser->parse($code); $ast = $traverser->traverse($ast); ``` -------------------------------- ### PHP-Parser AST: Comment Assignment Logic Update Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Shows the revised logic for comment assignment in the AST. Previously, comments were assigned to all nodes starting at the same position; now, they are assigned only to the outermost node at that position, simplifying comment handling and reducing redundancy in the AST. ```php // Comment $a + $b; ``` ```php-parser-ast # Before Stmt_Expression( expr: Expr_BinaryOp_Plus( left: Expr_Variable( name: a comments: array( 0: // Comment ) ) right: Expr_Variable( name: b ) comments: array( 0: // Comment ) ) comments: array( 0: // Comment ) ) ``` ```php-parser-ast # After Stmt_Expression( expr: Expr_BinaryOp_Plus( left: Expr_Variable( name: a ) right: Expr_Variable( name: b ) ) comments: array( 0: // Comment ) ) ``` -------------------------------- ### rebuildParsers.php Utility Reference Source: https://github.com/nikic/php-parser/blob/master/grammar/README.md Documentation for the `rebuildParsers.php` script, which preprocesses the grammar and builds the PHP parser. It includes command-line usage, available options, and environment variable configuration for customizing the build process. ```APIDOC php grammar/rebuildParsers.php [OPTIONS] Description: Rebuilds the PHP parsers by preprocessing the grammar and invoking kmyacc. Options: --debug Enables emission of debug symbols and creates the 'y.output' file. --keep-tmp-grammar Preserves the preprocessed grammar file instead of deleting it. Environment Variables: KMYACC Specifies an alternative kmyacc binary to use. Default: Uses the 'phpyacc' dev dependency. To use original kmyacc: Compile moriyoshi's fork (https://github.com/moriyoshi/kmyacc-forked). ``` -------------------------------- ### Instantiating PHP-Parser components with new namespaces Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-1.0.md Shows the recommended way to instantiate PHP-Parser components (`Parser`, `Lexer\Emulative`, `PrettyPrinter\Standard`) using the new, proper namespaced class names introduced in version 1.0. Note the change from `PHPParser` to `PhpParser` prefix for autoloading compatibility. ```php $parser = new \PhpParser\Parser(new PhpParser\Lexer\Emulative); $prettyPrinter = new \PhpParser\PrettyPrinter\Standard; ``` -------------------------------- ### Create PhpParser Parser Instance Source: https://github.com/nikic/php-parser/blob/master/doc/2_Usage_of_basic_components.markdown This PHP code demonstrates how to instantiate a parser using `PhpParser\ParserFactory`. It shows options for creating a parser targeting the host PHP version, the newest supported version, or a specific PHP version, depending on the analysis requirements. ```php use PhpParser\ParserFactory; use PhpParser\PhpVersion; // Parser for the version you are running on. $parser = (new ParserFactory())->createForHostVersion(); // Parser for the newest PHP version supported by the PHP-Parser library. $parser = (new ParserFactory())->createForNewestSupportedVersion(); // Parser for a specific PHP version. $parser = (new ParserFactory())->createForVersion(PhpVersion::fromString('8.1')); ``` -------------------------------- ### Instantiating PHP-Parser components with old namespaces Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-1.0.md Demonstrates how PHP-Parser components like `Parser` and `PrettyPrinter` were instantiated using the old, discouraged underscore-separated class names before the move to proper namespaces. This syntax is still functional but not recommended for new code. ```php $parser = new \PHPParser_Parser(new \PHPParser_Lexer_Emulative); $prettyPrinter = new \PHPParser_PrettyPrinter_Default; ``` -------------------------------- ### .phpy Pseudo-Language Node Syntax Source: https://github.com/nikic/php-parser/blob/master/grammar/README.md Describes the custom syntax for node creation within the `.phpy` pseudo-language grammar files and its transformation into PHP code, along with notes on how function-like constructs are handled. ```APIDOC Node Creation Syntax: Input: Name[arg1, arg2, ...] Transformation: This syntax is transformed into a PHP object instantiation: new Name(arg1, arg2, ..., attributes()) Notes: - 'Name' refers to the class name of the node. - 'arg1, arg2, ...' are arguments passed to the constructor. - 'attributes()' is a function call that provides additional attributes, automatically added during transformation. Function-like Constructs: Some function-like constructs within the .phpy grammar are resolved during preprocessing. (Refer to 'rebuildParsers.php' for a detailed list of these constructs.) ``` -------------------------------- ### Pretty Printer Single-Quoted String Backslash Escaping Update Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Illustrates how the pretty printer now only prints necessary backslashes in single-quoted strings, simplifying output and making it more concise. ```php # Before 'Foo\\Bar'; '\\\\'; # After 'Foo\Bar'; '\\\\'; ``` -------------------------------- ### Initializing NodeTraverser with Multiple Visitors in PHP Source: https://github.com/nikic/php-parser/blob/master/doc/component/Walking_the_AST.markdown Illustrates two equivalent ways to add multiple `NodeVisitor` instances to a `NodeTraverser`: either by passing them directly to the constructor during instantiation or by using the `addVisitor()` method for each visitor individually. ```php $traverser = new NodeTraverser($visitor1, $visitor2, $visitor3);\n\n// Equivalent to:\n$traverser = new NodeTraverser();\n$traverser->addVisitor($visitor1);\n$traverser->addVisitor($visitor2);\n$traverser->addVisitor($visitor3); ``` -------------------------------- ### PHP-Parser AST Change for Array Destructuring Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Shows the unified Abstract Syntax Tree (AST) representation for array destructuring (`[$x] = $y;`) in PHP-Parser 5.0, now consistently using `Node\Expr\List_`. ```php [$x] = $y; ``` -------------------------------- ### PHP-Parser AST Change for Throw Statements Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Illustrates the new Abstract Syntax Tree (AST) representation for `throw` statements in PHP-Parser 5.0. Previously `Stmt_Throw`, it is now `Stmt_Expression` containing `Expr_Throw`. ```php throw $e; ``` ```APIDOC Before: Stmt_Throw( expr: Expr_Variable( name: e ) ) After: Stmt_Expression( expr: Expr_Throw( expr: Expr_Variable( name: e ) ) ) ``` -------------------------------- ### Parse, Traverse, and Pretty Print PHP Code with php-parser Source: https://github.com/nikic/php-parser/blob/master/doc/2_Usage_of_basic_components.markdown This PHP snippet demonstrates the basic workflow of using `nikic/php-parser` to process PHP code. It involves reading a file, parsing its content into an Abstract Syntax Tree (AST), adding and traversing the AST with a custom visitor, and then pretty printing the modified AST back into PHP code. Basic error handling for parsing is also included. ```php $prettyPrinter = new PrettyPrinter\Standard; // add your visitor $traverser->addVisitor(new MyNodeVisitor); try { $code = file_get_contents($fileName); // parse $stmts = $parser->parse($code); // traverse $stmts = $traverser->traverse($stmts); // pretty print $code = $prettyPrinter->prettyPrintFile($stmts); echo $code; } catch (PhpParser\Error $e) { echo 'Parse Error: ', $e->getMessage(); } ``` -------------------------------- ### Basic PHP Pretty Printing with php-parser Source: https://github.com/nikic/php-parser/blob/master/doc/component/Pretty_printing.markdown Demonstrates the fundamental usage of the `php-parser`'s `PrettyPrinter\Standard` class to convert a parsed Abstract Syntax Tree (AST) back into PHP code. It shows how to parse code, modify the AST, and then pretty print it into a new code string. ```php $stmts = $parser->parse($code); // MODIFY $stmts here $prettyPrinter = new PhpParser\PrettyPrinter\Standard; $newCode = $prettyPrinter->prettyPrintFile($stmts); ``` -------------------------------- ### Pretty Printer Else If Parentheses Omission Update Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Shows how the pretty printer now omits redundant parentheses in `else if` structures for cleaner and more streamlined code, aligning with common PHP style practices. ```php # Before else { if ($x) { // ... } } # After else if ($x) { // ... } ``` -------------------------------- ### New PHP-Parser 2.0 Parser Instantiation with ParserFactory Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-2.0.md This snippet illustrates the recommended way to create a parser instance in PHP-Parser 2.0 using the `ParserFactory`. It shows how to create a parser that prefers PHP 7 parsing rules, falling back to PHP 5 if necessary. This factory-based approach replaces direct instantiation. ```php use PhpParser\ParserFactory; $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7); ``` -------------------------------- ### Remove Else Statements from PHP AST Source: https://github.com/nikic/php-parser/blob/master/doc/component/Walking_the_AST.markdown This example illustrates how to remove `else` statements from the AST by replacing them with `null`. This method is safe only if the subnode where the node is stored is nullable, as is the case for `Node\Stmt\If_::$else`. ```php public function leaveNode(Node $node) { if ($node instanceof Node\Stmt\Else_) { return NodeVisitor::REPLACE_WITH_NULL; } } ``` -------------------------------- ### Old PHP-Parser 1.x Parser Instantiation Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-2.0.md This snippet demonstrates the deprecated method of creating a parser instance in PHP-Parser 1.x. It involves direct instantiation of the `PhpParser\Parser` class, passing a `Lexer\Emulative` instance to its constructor. This approach is no longer valid in PHP-Parser 2.0. ```php use PhpParser\Parser, PhpParser\Lexer; $parser = new Parser(new Lexer\Emulative); ``` -------------------------------- ### Update PHP-Parser Modifier Constants Usage Source: https://github.com/nikic/php-parser/blob/master/UPGRADE-5.0.md Demonstrates the migration from deprecated `PhpParser\Node\Stmt\Class_` modifier constants to the new, centralized `PhpParser\Modifiers` class constants. This change aims to clarify that these flags are used across various node types. ```php PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC -> PhpParser\Modifiers::PUBLIC PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED -> PhpParser\Modifiers::PROTECTED PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE -> PhpParser\Modifiers::PRIVATE PhpParser\Node\Stmt\Class_::MODIFIER_STATIC -> PhpParser\Modifiers::STATIC PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT -> PhpParser\Modifiers::ABSTRACT PhpParser\Node\Stmt\Class_::MODIFIER_FINAL -> PhpParser\Modifiers::FINAL PhpParser\Node\Stmt\Class_::MODIFIER_READONLY -> PhpParser\Modifiers::READONLY PhpParser\Node\Stmt\Class_::VISIBILITY_MODIFIER_MASK -> PhpParser\Modifiers::VISIBILITY_MASK ``` -------------------------------- ### Replacing a Single Node in PHP AST Traversal Source: https://github.com/nikic/php-parser/blob/master/doc/component/Walking_the_AST.markdown Demonstrates how to replace an existing AST node with a new one by returning the new node from the `leaveNode` method. The example converts all `&&` (BooleanAnd) expressions into their negated form, `!($a && $b)`. ```php public function leaveNode(Node $node) { if ($node instanceof Node\Expr\BinaryOp\BooleanAnd) { // Convert all $a && $b expressions into !($a && $b) return new Node\Expr\BooleanNot($node); } } ```