我正在尝试基于Exploring Ruby's Regular Expression Algorithm中概述的回溯方法来实现正则表达式匹配器。编译后的正则表达式被翻译成一组虚拟机命令;用于回溯当前命令和输入字符串索引以及捕获组信息都保存在堆栈上。
在正则表达式匹配:虚拟机方法中,Cox 提供了有关如何将某些正则表达式组件编译为 VM 命令的更详细信息,尽管讨论的实现有些不同。根据这些文章,我的实现对于标准分组、字符类和重复组件非常有效。
现在我想看看这种类型的实现有哪些扩展和优化选项。Cox 在他的文章中提供了很多关于 DFA/NFA 方法的有用信息,但是关于回溯方法的扩展或优化技术的信息有点少。
例如,关于他所说的反向引用
反向引用在回溯实现中是微不足道的。
并给出了 DFA 方法的想法。但我不清楚如何用 VM 方法“简单地”完成这项工作。当到达反向引用命令时,您必须将先前匹配的字符串从相应的组编译到另一个 VM 命令列表中,并以某种方式将这些命令合并到当前 VM 中,或者维护第二个 VM 并将执行临时切换到那个。
他还提到了通过使用前瞻对重复进行可能的优化,但没有详细说明它是如何工作的。在我看来,这可以用来减少回溯堆栈上的项目数。
tl;dr基于 VM 的回溯正则表达式实现存在哪些通用优化技术,它们是如何工作的?请注意,我不是在寻找特定于某种编程语言的优化,而是针对这种类型的正则表达式实现的一般技术。
编辑:正如第一个链接中提到的,Oniguruma 库实现了一个正则表达式匹配器,具有完全基于堆栈的回溯方法。也许有人可以解释该库所做的优化,这些优化可以推广到其他实现。不幸的是,该库似乎没有提供任何有关源代码的文档,而且代码也缺少注释。
编辑 2:在阅读有关解析表达式语法 (PEG) 的内容时,我偶然发现了一篇关于 Lua PEG 实现的论文,它使用了类似的基于 VM 的方法。该论文提到了几个优化选项,以减少执行的 VM 命令的数量和回溯堆栈的不必要增长。