![优化正则表达式以实现 PHP 方法补全](https://linux22.com/image/1519379/%E4%BC%98%E5%8C%96%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E4%BB%A5%E5%AE%9E%E7%8E%B0%20PHP%20%E6%96%B9%E6%B3%95%E8%A1%A5%E5%85%A8.png)
我正在开发一个正则表达式,用于触发 vim 中 deoplete 的 php 语法方法补全。有两种类型的方法需要补全:使用双冒号 (::) 完成静态方法,使用箭头 (->) 完成实例方法。
[my] 实例方法规则
- 美元符号
- 后面跟着的第一个字符(对象名称)是字母或下划线
- 第一个字符之后的任何字符都是字母、数字或下划线
- 箭头表示方法名称的开始,可以出现在对象名称之后或下一行
实例方法的正则表达式
\$\([a-zA-Z_][a-zA-Z0-9_]*\)\v?\h?\->
[my] 静态方法的规则
- 必须以大写字母开头
- 第一个字符之后的任何字符都是字母、数字或下划线,或者整个单词可以是(自身、父级或静态)
- 双冒号表示方法名的开始
正则表达式静态方法
\(self|parent|static|[A-Z][a-zA-Z0-9_]*\)::
问题是我是否可以通过做一些前瞻魔法或类似的东西,特别是静态方法正则表达式来加快速度?
测试文本
// Should match
$this
->
// Should match
$someObject->
// Should not match
"somethingInAString->"
// Should not match
stdClass::
// Should match
SomeClass::
// Should match
parent::
答案1
您可以通过将以 开头的两个单词的首字母组合起来进行微小的优化s
,例如
(s(elf|tatic)|parent|[A-Z][a-zA-Z0-9_]*)::
但实际上,速度上的差异很小,但可读性的差异很大,所以我不建议这样做。
真正的问题是您的正则表达式是否由 deoplete 优化和编译。我快速扫描了源代码,但并不清楚是否如此。
如果你允许我继续说下去,......
通常正则表达式(特别是确定性的正则表达式)的优点是它们可以实现没有通过将它们变成有限状态自动机阅读更多类似文章;您每次处理一个字符,然后转换到另一个状态,无需回溯。如果使用此方法,它无论如何都非常快,并且您可以进行的手动优化将在将非确定性有限状态自动机变成确定性自动机的阶段完成。
答案2
该正则表达式不会花费超过几十毫秒的时间。在完成用例中,这永远不会成为您的瓶颈。无论如何,有几种方法可以提高 vim 正则表达式的性能:
\@>
这是一个占有多重,
\{-}
是非贪婪版本*
这篇文章的作者 Russ Cox 也对此进行了有趣的补充https://swtch.com/~rsc/regexp/regexp1.html,帮助制作 vim 的正则表达式引擎https://groups.google.com/forum/#!topic/vim_dev/o-oDH91G8NI