我正在尝试学习和理解javascript中的正则表达式,并希望了解javascript中正则表达式的回溯概念。任何人都可以指向我的源代码或引用我的谷歌Chrome(V8引擎)中的javascript用来解析正则表达式并检查它如何回溯的算法。由于谷歌的V8引擎是开源的,这一定不难。
答案 0 :(得分:1)
V8 Engine的源代码并不是一个开始学习回溯的友好场所。
乍一看,根据我阅读Java Pattern
类的实现经验,文件trunk/src/x87/regexp-macro-assembler-x87.cc
包含JS RegExp的源代码。您基本上是在源代码中的级别阅读汇编。
您可能对trunk/src/runtime/runtime-regexp.cc
感兴趣,其中包含RegExp方法的实现。但是,代码并没有包含有关RegExp内部工作的任何信息。
回溯的概念类似于搜索算法。由于您不知道结果,您将执行强力搜索,但根据您定义搜索顺序的方式,您可以更快或更慢地得出结果。
对于连接,每个节点以线性方式连接到下一个节点。没有分支,所以没有回溯。
对于分支P1|P2|...|Pn
,您可以将其视为具有n
个节点的搜索树,您将首先尝试节点P1
,然后尝试P2
,. ..最后Pn
。分支中的所有n
个节点都连接到续集原子,因此如果任何节点成功,它将继续移动到续集原子,并且当下一个原子上的所有可能性时,仅回溯分支中的下一个节点已经筋疲力尽了。
对于(贪婪)量词0或更多A*
,您可以将其视为具有2个分支的节点,一个分支到A
然后回到自身,另一个分支到下一个分支原子。将首先尝试到A的分支。请注意,这是简化描述,因为引擎还必须处理0长度匹配。
对于(懒惰)量词0或更多A*?
,它基本上与上面相同,除了首先尝试到下一个原子的分支。
当您将上限和下限添加到量词时,您可以想象添加一个计数器来记录A
已匹配的次数。根据计数器的不同,任何一个分支都无法在某个柜台进行分支。
因此,您将使用上面的搜索树执行搜索,并且每次卡住(无法达到树的目标状态),您将回溯并尝试其他分支。
希望这有助于您开始回溯的概念。