phabel/php-parser

用PHP编写的PHP解析器


README

Coverage Status

这是一个用PHP编写的从PHP 5.2到PHP 8.0的解析器。其目的是简化静态代码分析和操作。

4.x版本文档(稳定版;在PHP >= 7.0上运行;解析PHP 5.2到PHP 8.0)。

3.x版本文档(不受支持;在PHP >= 5.5上运行;解析PHP 5.2到PHP 7.2)。

特性

该库提供的主要特性包括

  • 将PHP 5、PHP 7和PHP 8代码解析为抽象语法树(AST)。
    • 无效代码可以解析为部分AST。
    • AST包含精确的位置信息。
  • 以人类可读的格式导出AST。
  • 将AST转换回PHP代码。
    • 实验性:对于部分修改的AST,可以保留格式。
  • 遍历和修改AST的基础设施。
  • 解析命名空间名称。
  • 评估常量表达式。
  • 用于简化AST构造的构建器。
  • 将AST转换为JSON并返回。

快速入门

使用 composer 安装库

php composer.phar require nikic/php-parser

将一些PHP代码解析为AST并以人类可读的格式导出结果

<?php
use PhpParser\Error;
use PhpParser\NodeDumper;
use PhpParser\ParserFactory;

$code = <<<'CODE'
<?php

function test($foo)
{
    var_dump($foo);
}
CODE;

$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
try {
    $ast = $parser->parse($code);
} catch (Error $error) {
    echo "Parse error: {$error->getMessage()}\n";
    return;
}

$dumper = new NodeDumper;
echo $dumper->dump($ast) . "\n";

这会导出类似以下的AST

array(
    0: Stmt_Function(
        byRef: false
        name: Identifier(
            name: test
        )
        params: array(
            0: Param(
                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(
                        parts: array(
                            0: var_dump
                        )
                    )
                    args: array(
                        0: Arg(
                            value: Expr_Variable(
                                name: foo
                            )
                            byRef: false
                            unpack: false
                        )
                    )
                )
            )
        )
    )
)

让我们遍历AST并执行某种修改。例如,删除所有函数体

use PhpParser\Node;
use PhpParser\Node\Stmt\Function_;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitorAbstract;

$traverser = new NodeTraverser();
$traverser->addVisitor(new class extends NodeVisitorAbstract {
    public function enterNode(Node $node) {
        if ($node instanceof Function_) {
            // Clean out the function body
            $node->stmts = [];
        }
    }
});

$ast = $traverser->traverse($ast);
echo $dumper->dump($ast) . "\n";

这会给我们一个其中 Function_::$stmts 为空的AST

array(
    0: Stmt_Function(
        byRef: false
        name: Identifier(
            name: test
        )
        params: array(
            0: Param(
                type: null
                byRef: false
                variadic: false
                var: Expr_Variable(
                    name: foo
                )
                default: null
            )
        )
        returnType: null
        stmts: array(
        )
    )
)

最后,我们可以将新的AST转换回PHP代码

use PhpParser\PrettyPrinter;

$prettyPrinter = new PrettyPrinter\Standard;
echo $prettyPrinter->prettyPrintFile($ast);

这给了我们原始代码,但是函数内部没有 var_dump() 调用

<?php

function test($foo)
{
}

对于更全面的介绍,请参阅文档。

文档

  1. 简介
  2. 基本组件的使用

组件文档

  • 遍历AST
    • 节点访问者
    • 从访问者修改AST
    • 短路遍历
    • 交错访问者
    • 简单的节点查找API
    • 父级和同级引用
  • 名称解析
    • 名称解析选项
    • 名称解析上下文
  • 美观打印
    • 将AST转换回PHP代码
    • 自定义格式
    • 保留格式的代码转换
  • AST构建器
    • AST节点的流畅构建器
  • 词法分析器
    • 词法分析器选项
    • 节点和文件位置的标记
    • 自定义属性
  • 错误处理
    • 错误列信息
    • 错误恢复(解析语法不正确的代码)
  • 常量表达式评估
    • 评估常量/属性等初始化器
    • 处理错误和不支持的表达式
  • JSON表示
    • AST的JSON编码和解码
  • 性能
    • 禁用Xdebug
    • 重用对象
    • 垃圾回收影响
  • 常见问题解答
    • 父级和同级引用