任何用PHP编写的体面的PHP解析器?[关闭]


80

我做了很多工作来处理和分析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,我需要一个。但是,其中一个也是一个很好的起点。)


1
你的目标是什么?您想在这里完成什么?
查尔斯

3
@查尔斯:我会用到很多东西。只需使用AST表示形式的任何PHP源代码;)
NikiC 2011年

1
@mario:那会丢很多信息。它实际上仅用于提取有关文件的某些信息的任务。因此,它仅保留类语句,方法语句或return语句之类的内容,而忽略了我实际上最感兴趣的一切:代码。
NikiC 2011年

2
我认为您不会找到用PHP编码的任何大型,健壮的语言解析器。根本没有要求。
艾拉·巴克斯特

4
在过去的一周中,我自己编写了一个解析器的初始版本:github.com/nikic/PHP-Parser我在我的代码库中对其进行了测试,并且运行良好。我将努力改进接口,以使其实际可用。
NikiC 2011年

Answers:


128

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

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

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

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

  • 将AST编译回PHP(“漂亮打印”)
  • 遍历和更改AST的基础结构
  • 与XML的串行化(以及以人类可读形式进行转储)
  • 命名空间名称的解析(别名等)

有关用法概述,请参见文档“基本组件的用法”部分。


2
这太棒了!您有维护计划吗?
MikeSchinkel 2015年

1
@NikiC谢谢你!那是一个很棒的图书馆:-)
BVengerov '16

1
哇,11年12月上旬才支持PHP 7.1!
dotancohen

9

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

不久前,内部使用PHP的人决定将其转换为Lemon作为其解析技术。PHP svn存储库中有一个分支,其中包含必需的更改。

他们决定不继续进行此操作,因为他们发现自己的Lemon解决方案的速度降低了10-15%。但是,分支仍然存在。

有一个较旧的Lemon解析器,编写为PHP扩展。您也许可以使用它。还有这个PEAR包。还有这等柠檬包(通过这个博客帖子大约PGN)。

当然,即使您可以使用它,我也不确定您将如何处理数据,或者数据看起来像什么。

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


首先:+1进行广泛的研究。主要问题不是没有办法在PHP中构建解析器。您已经提到使用Lemon PHP语法并进行编译。甚至更容易的是使用“实际的” yacc / bison语法(也有针对该语法的编译器)。问题是,将用于生成操作码的yacc C代码转换为用于生成AST的yacc PHP代码确实是很多工作。所以我在寻找是否有人已经完成了这项工作。
NikiC 2011年

@nikic IMO的原因之一是尚未有人做到这一点,因为它没有关于PHP到底是什么以及如何解析它的规范。php-internals以前完全拒绝了整个概念。结果,在PHP源代码本身之外,没有权威的源来说明如何真正完成解析。如果没有可供参考的权威资源,构建正确的解析器将是一次真正的冒险。不幸的是,这意味着从yacc或Lemon数据开始可能是最佳选择。
查尔斯

@nikic,查尔斯:对于我们的PHP解析器而言,这是一次真正的冒险。方法:建议词法分析器/语法,尝试上千个文件,弄错了,调整后再试一次。这种强大的解析器需要花一年左右的时间才能获得针对不良文档的语言的解析器。至少它对我们有用。YMMV,但可能不会太多。
艾拉·巴克斯特

7

度量工具PHP Depend包含从完全用PHP编写的PHP源代码生成AST的代码。但是,它确实使用了PHP自己的token_get_all来进行令牌化。

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

上次我检查过AST的某些部分(如数学表达式)的实现还没有完成,但是据作者说,这是目标。


是否具有AST,但不适用于“数学运算”(我想您的意思是“表达式”?这是语言的关键组成部分,尤其是当您认为双引号的“字符串文字”(带有嵌入式表达式)确实很复杂时)字符串表达式
Ira Baxter

2
您得到了赏金,因为这是最接近问题的答案。但是显然它并不是真正有用的,因为它缺少一半的PHP语法...
NikiC 2011年

这篇文章的内容已经过时。从那时起,一直在积极地进行开发,尽管我不知道它对PHP语法的支持程度。
nhahtdh 2015年

4

好吧,对不起,这不是用PHP编写的,但是构建这种机器很困难,PHP并不特别适合于语言处理任务。

我们的PHP前端提供完整的PHP 4.x和5.x(编辑9/2016:现在可以处理PHP 7)解析,自动构建具有完整PHP语法所有详细信息的AST,可以从AST生成可编译的源文本。这比您考虑所有棘手的细节(包括奇怪的字符串文字,捕获的注释,带底数的数字等)时听起来的难。

但是AST并不足够(您已经观察到令牌还远远不够)。

DMS软件再造工具包是其基础,它为AST的分析和任意转换提供了支持。它还将一次读取大量文件,从而可以PHP文件进行分析和转换。


1
就像对第一句话的回应:已经有解析器生成器,可以从yacc语法生成器(例如kmyacc)生成解析器。也就是说,用PHP构建它和以任何其他语言构建它之间没有太大区别。您所要做的只是“讽刺”(讽刺)用一些构建节点树的PHP代码替换zend_language_parser.y中的C代码。
NikiC 2011年

关于其余内容:我真的很想拥有一个PHP解决方案。但是,如果(似乎很有可能)没有那样的东西,我可能会使用其他东西。在SO上,我已经多次听说过DMS,我将对其进行研究。
NikiC 2011年

@ninkic:所有图灵机(包括PHP)都可以模拟所有其他图灵机,是的,当然可以在PHP中构建它。但是a)在构建解析器;我认为PHP解析器不是为了构建树而设计的,而是为了馈送PHP p代码生成器,并且我认为您会发现需求有所不同,并且b)人们反复犯错误的假设: AST,其他一切都很容易;他们之所以犯此错误,很大程度上是因为他们没有使用AST进行复杂操作的经验。我建立DMS是因为这个假设是错误的。
伊拉·巴克斯特

1
a)是的,PHP解析器并非旨在构建解析树,而是旨在构建操作码流。这就是为什么几乎不可能将zend语言解析器自动转换为PHP的原因。b)我可能是犯此错误的人之一;)从使用纯令牌流已经可以完成大量复杂操作的事实出发,我得出结论(在您眼中是错误的?),使用AST会更容易并且更稳定。
NikiC 2011年

@nikic:50年来的编译器技术教训是,每个程序表示都使某些事情变得容易。您可以仅对文本进行一些程序操作。您可以在令牌上做更多的事情。您还可以在AST上做更多的事情。如果您具有符号表,控制和数据流信息(图形),变量别名数据(指向分析),则可以做真正有趣的事情。当您尝试进行复杂的代码生成时发现,这些都是非常有用的东西。
艾拉·巴克斯特

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.