这是一个早期阶段的 PHP 解析器,从一开始就为 IDE 使用场景而设计(更多详细信息,请参阅设计目标)。还有大量工作要做,因此此时此存储库主要充当实验和对话的开始。
这是 v0.1 分支,它更改了数据结构以支持在初始 0.0.x 发行版之后添加的语法。
配置机器后,您可以使用解析器通过友好的 API 生成并使用抽象语法树 (AST)。
<?php// 自动加载所需的类require __DIR__ . "/vendor/autoload.php";use MicrosoftPhpParser{DiagnosticsProvider, Node, Parser, PositionUtilities};// 实例化新的解析器实例$parser = new Parser();// 从字符串内容返回并打印 AST$astNode = $parser ->parseSourceFile('<?php /* comment */ echo "hi!"');var_dump($astNode);// 获取 and从 AST 节点打印错误。解析器优雅地处理错误,//因此可以在 IDE 使用场景中使用(代码通常不完整)。$errors = DiagnosticsProvider::getDiagnostics($astNode);var_dump($errors);// 遍历所有 Node 后代$astNodeforeach ($astNode->getDescendantNodes() as $descendant) {if ($descendant instanceof NodeStringLiteral) {// 打印节点文本(没有空格或注释)var_dump($descendant->getText());// 所有节点都链接回其父节点,因此很容易导航树。$grandParent = $descendant->getParent()->getParent() ;var_dump($grandParent->getNodeKindName());// AST 具有完全代表性,并且可往返于原始源。// 这使消费者能够构建可靠的格式化和重构工具。var_dump($grandParent->getLeadingCommentAndWhitespaceText()); }// 除了检索 Node 的所有子节点或后代之外,// 节点还公开特定于 Node 类型的属性。 if ($descendant instanceof NodeExpressionEchoExpression) {$echoKeywordStartPosition = $descendant->echoKeyword->getStartPosition();//为了减少内存消耗,位置被表示为文档中的单个整数//索引,但它们的行和字符位置很容易检索到。$lineCharacterPosition = PositionUtilities::getLineCharacterPositionFromPosition($echoKeywordStartPosition,$descendant->getFileContents() );echo "行:$lineCharacterPosition->行,字符:$lineCharacterPosition->字符"; } }
注意:API 尚未最终确定,因此请提交问题让我们知道您想要公开哪些功能,我们将看看我们能做什么!另外,请在解析树中提交任何具有意外行为的错误。我们仍处于早期阶段,非常感谢您提供的任何反馈。
容错设计——在 IDE 场景中,根据定义,代码是不完整的。在输入无效代码的情况下,解析器仍然应该能够恢复并生成有效的完整树以及相关的诊断。
快速且轻量级(应该能够每秒解析几 MB 的源代码,为其他功能留出空间)。
内存高效的数据结构
允许将来增量解析
遵守PHP语言规范,支持PHP5和PHP7语法
生成的 AST 提供语义和转换操作所需的属性(完全代表性等),这些操作也需要具有高性能。
完全具有代表性且可往返返回到解析的文本(所有空格和注释“琐事”都包含在解析树中)
可以轻松地通过父/子节点遍历树
UI 响应时间 < 100 毫秒,因此每个语言服务器操作应< 50 毫秒,以便为并行进行的所有其他操作留出空间。
随着时间的推移,简单且可维护 - 解析器往往会变得非常混乱,而且速度非常快,因此可读性和调试能力是重中之重。
可测试 - 解析器应该生成可证明有效的解析树。我们通过定义并持续测试一组关于树的不变量来实现这一点。
友好且描述性的 API 让其他人可以轻松地进行构建。
用 PHP 编写 - 让 PHP 社区尽可能轻松地使用和贡献。
为了确保每一步都有足够的正确性,解析器正在使用以下增量方法进行开发:
第 1 阶段:编写不支持 PHP 语法,但支持 EOF 和 Unknown token 的词法分析器。为所有不变量编写测试。
第2阶段:支持PHP词法语法,大量测试
第 3 阶段:编写一个不支持 PHP 语法的解析器,但生成错误节点树。为所有不变量编写测试。
第四阶段:支持PHP句法语法,大量测试
第 5 阶段(进行中):现实世界验证和优化
正确性:验证示例代码库上没有产生错误,与其他解析器进行基准测试(调查任何不一致的实例),模糊测试
性能:针对大型 PHP 应用程序的配置文件、基准测试
第 6 阶段:最终确定 API,使人们尽可能轻松地使用。
一些 PHP 语法结构(即 Yield-Expression 和模板字符串)尚不支持,并且还存在其他杂项错误。但是,由于解析器是容错的,因此这些错误会得到妥善处理,并且生成的树是完整的。为了更全面地了解我们所处的位置,您可以运行“验证”测试套件(有关运行测试的更多信息,请参阅贡献指南)。或者简单地看一下当前的验证测试结果。
尽管我们还没有开始性能优化阶段,但到目前为止我们已经看到了有希望的结果,并且还有很大的改进空间。有关我们当前方法的详细信息,请参阅它的工作原理,并在您自己的计算机上运行性能测试以亲自查看。
设计目标- 了解项目的设计目标(功能、性能指标等)。
文档- 了解如何从项目中引用解析器,以及如何对 AST 执行操作来回答有关代码的问题。
语法可视化工具- 更切实地感受 AST。发挥创意——看看你能否打破它!
当前状态和方法- 支持多少语法?表现?记忆? API稳定性?
它是如何工作的——了解架构、设计决策和权衡。
词法分析器和解析器
容错策略
增量解析
开放性问题
验证策略
贡献! - 了解如何参与,查看一些教育提交的指示,这将帮助您提高代码库(即使您以前从未使用过解析器),以及更容易迭代的推荐工作流程。
该项目采用了微软开源行为准则。有关详细信息,请参阅行为准则常见问题解答或联系 [email protected] 提出任何其他问题或意见。