【问题标题】:Any decent PHP parser written in PHP? [closed]任何用 PHP 编写的像样的 PHP 解析器? [关闭]
【发布时间】:2022-04-01 17:14:34
【问题描述】:

我在处理和分析 PHP 代码方面做了大量工作。通常我只使用Tokenizer 来执行此操作。对于大多数应用程序来说,这就足够了。但有时使用词法分析器进行解析不够可靠(显然)。

因此,我正在寻找一些用 PHP 编写的 PHP 解析器。我找到了hnw/PhpParserkumatch/stagehand-php-parser。两者都是通过使用 PHP 而不是 C 将 zend_language_parser.y 自动转换为 .y 文件创建的(然后编译为 LALR(1) 解析器)。但是这种自动转换无法使用。

那么,有没有用 PHP 编写的像样的 PHP 解析器? (我需要一个用于 PHP 5.2 和一个用于 5.3。但只要其中一个也是一个很好的起点。)

【问题讨论】:

  • 你的目标是什么?你想在这里完成什么?
  • @Charles:我会用它来做很多事情。任何需要 AST 表示形式的 PHP 源代码的东西;)
  • @mario:那个丢了很多信息。它实际上仅用于提取有关文件的一些信息的任务。所以它只保留类语句、方法语句或返回语句之类的东西,而忽略了我实际上最感兴趣的所有内容:代码。
  • 我认为您不会找到任何用 PHP 编码的大规模、健壮的语言解析器。只是没有要求。
  • 上周我自己编写了一个解析器的初始版本:github.com/nikic/PHP-Parser 我针对我的代码库进行了测试,它运行良好。我将努力改进界面,使其真正可用。

标签: php parsing


【解决方案1】:

在这里找不到完整且稳定的解析器后,我决定自己编写一个。结果如下:

PHP-Parser:用 PHP 编写的 PHP 解析器

该项目支持解析为 PHP 5.2 和 PHP 8.1 之间的任何 PHP 版本编写的代码。

除了解析器本身,该库还提供了一些相关组件:

  • 将 AST 编译回 PHP(“漂亮的打印”)
  • 用于遍历和更改 AST 的基础设施
  • 与 XML 之间的序列化(以及以人类可读的形式转储)
  • 将 AST 转换为 JSON 并返回。
  • 命名空间名称(别名等)的解析

有关使用概述,请参阅documentation"Usage of basic components" 部分。

【讨论】:

  • 这太棒了!你有维护它的计划吗?
  • @NikiC 谢谢老兄!这是一个很棒的图书馆:-)
  • 哇,2011 年 12 月初支持 PHP 7.1!
【解决方案2】:

这对您来说不是一个好选择,因为它违反了纯 PHP 约束,但是:

不久前,php-internals 人员决定改用Lemon 作为他们的解析技术。有一个 branch in the PHP svn repo 包含所需的更改。

他们决定not to continue with this,因为他们发现他们的 Lemon 解决方案慢了大约 10-15%。但是,分支还在。

有一个older Lemon parser 编写为 PHP 扩展。你也许可以使用它。还有this PEAR package。还有this other lemon package(来自this关于PGN的博文)。

当然,即使你让它正常工作,我也不确定你会如何处理这些数据,或者数据看起来是什么样子。

另一个古怪的选择是peeking at Quercus,这是一个用Java 实现的PHP。他们必须编写一个解析器,也许值得研究。

【讨论】:

  • 首先:+1 进行广泛的研究。主要问题不在于无法在 PHP 中构建解析器。您已经提到使用 Lemon PHP 语法并对其进行编译。更简单的可能是使用“真正的”yacc/bison 语法(也有编译器)。问题更多的是,将用于生成操作码的 yacc C 代码转换为用于生成 AST 的 yacc PHP 代码确实需要做很多工作。所以我在寻找是否有人已经完成了这项工作。
  • @nikic IMO,目前还没有人这样做的原因之一是对于 PHP 的真正含义以及如何解析它,没有规范。 php-internals 之前完全拒绝了整个概念。因此,在 PHP 源代码本身之外,没有关于如何实际完成解析的权威 源。如果没有权威的参考资料,构建一个正确的解析器将是一次真正的冒险。不幸的是,这意味着从 yacc 或 Lemon 数据开始可能是最佳选择。
  • @nikic, Charles:对于我们的 PHP 解析器来说,这是一次真正的冒险。方法:提出词法分析器/语法,尝试数千个文件,出错,调整,再试一次。大约需要一年的时间才能得到一个健壮的解析器来处理一种文档不足的语言。至少它为我们做了。 YMMV,但可能不会太多。
【解决方案3】:

指标工具PHP Depend 包含从完全用 PHP 编写的 PHP 源代码生成 AST 的代码。但是,它确实使用 PHP 自己的 token_get_all 进行标记化。

源码在github上:https://github.com/manuelpichler/pdepend/tree/master/src/main/php/PHP/Depend

我上次检查的某些部分(如数学表达式)的 AST 实现尚未完成,但据其作者称,这就是目标。

【讨论】:

  • 有一个 AST 但不是用于“数学运算”(我想你的意思是“表达式”?这是语言的关键部分,尤其是当你考虑双引号的“字符串文字”(嵌入表达式)实际上只是复杂的字符串表达式。
  • 你得到了赏金,因为这是最接近问题的答案。但显然它并不是真正可用的,因为它缺少,嗯,PHP 语法的一半......
  • 这篇文章的内容已经过时了。从那以后一直在积极开发,虽然我不知道它对 PHP 语法的支持程度。
【解决方案4】:

嗯,这不在 PHP 中,抱歉,但是构建这种机器很困难,而且 PHP 并不是特别适合语言处理任务。

我们的PHP Front End 提供完整的 PHP 4.x 和 5.x(编辑 9/2016:现在处理 PHP 7)解析,自动构建具有完整 PHP 语法的所有细节的 AST,可以从AST。当您考虑所有棘手的细节(包括奇怪的字符串文字、捕获的 cmets、带基数的数字等)时,这比听起来更难。

但是ASTs are hardly enough(您已经观察到令牌甚至还不够)。

DMS Software Reengineering Toolkit 是构建它的基础,为 AST 的分析和任意转换提供支持。它还可以一次读取大量文件,支持 PHP 文件的分析和转换。

【讨论】:

  • 正如对第一句话的回应:已经有解析器生成器,可以从yacc语法生成解析器(例如kmyacc)。 IE。用 PHP 构建它和用任何其他语言构建它没有太大区别。您所要做的就是“只是”(讽刺地)用一些构建节点树的 PHP 代码替换 zend_language_parser.y 中的 C 代码。
  • 关于其余的:我真的很想有一个 PHP 解决方案。但是如果(这似乎很可能)没有类似的东西,我可能会使用其他东西。我已经在 SO 上多次听说过 DMS,我会研究一下。
  • @ninkic:所有图灵机(包括 PHP)都可以模拟所有其他图灵机,当然可以用 PHP 构建它。但是 a) 正在构建 just 解析器;我认为 PHP 解析器不是为构建树而设计的,而是为 PHP p 代码生成器提供数据,我认为您会发现需求有所不同,并且 b) 人们反复制作错误地认为如果他们有 AST,其他一切都很容易;他们犯这个错误主要是因为他们没有使用 AST 做复杂事情的经验。我构建了 DMS,因为这个假设是错误的。
  • a) 是的,PHP 解析器并非旨在构建解析树,而是旨在构建操作码流。这就是为什么几乎不可能将 zend 语言解析器自动转换为 PHP 的原因。 b)我可能是犯这个错误的人之一;)鉴于已经可以使用纯令牌流完成大量复杂的操作,我得出结论(在您看来是错误的?)使用 AST 会更容易并且更稳定。
  • @nikic:从 50 年的编译器技术中汲取的教训是,每个程序表示都使某些事情变得容易。您可以仅对文本进行一些程序操作。你可以在代币上做更多的事情。你可以在 AST 上做更多的事情。如果你有符号表、控制和数据流信息(图表)、变量别名数据(指向分析),你可以做一些非常有趣的事情。当您尝试进行复杂的代码生成时,您会发现这都是非常非常有用的东西。
【解决方案5】:

有一个ANTLR到PHP的端口:http://code.google.com/p/antlrphpruntime/w/list

它已被废弃,但我认为它应该仍然有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-24
    • 1970-01-01
    • 1970-01-01
    • 2010-09-22
    • 2012-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多