DFA正则表达式引擎可以处理原子组吗?

时间:2013-11-12 23:06:44

标签: regex dfa

根据this page(以及其他一些人),DFA正则表达式引擎可以很好地处理群组。我对原子团体(或占有量词)感到好奇,因为我最近使用它们很多,无法想象如何做到这一点。


我不同意答案的第一部分:

  

DFA不需要像原子分组那样处理构造......原子分组是一种帮助引擎完成匹配的方法,否则会导致无休止的回溯

原子组不仅对于NFA引擎的速度很重要,而且还允许编写更简单且不易出错的正则表达式。假设我需要在程序中找到所有C风格的多行注释。确切的正则表达式将是:

  • 从文字/*
  • 开始
  • 吃以下任何东西
    • *
    • 以外的任何字符
    • 一个*后跟除/
    • 之外的任何内容
  • 尽可能重复
  • 以文字*/
  • 结尾

这听起来有点复杂,正则表达式

/\* ( [^*] | \*[^/] )+ \*/

复杂而错误(它无法正确处理/* foo **/)。使用不情愿(懒惰)量词更好

/\* .*? \*/

但也错了,因为它可以吃掉整条线

/* foo */ @#$!!**@#$ /* bar */

当由于后来的子表达式失败而导致的回溯发生时。将上述内容放在一个原子组中很好地解决了这个问题:

(?> /\* .*? \*/ )

这总是(我希望)并且尽可能快(对于NFA)。所以我想知道DFA引擎是否能以某种方式处理它。

1 个答案:

答案 0 :(得分:1)

DFA不需要处理像原子分组这样的结构。 DFA是“文本导向的”,与NFA不同,后者是“正则表达式”,换句话说: 原子分组是一种帮助引擎完成匹配的方法,否则会导致无休止的回溯,因为(NFA)引擎尝试在每个排列位置找到匹配,甚至不可能匹配。

简单地说,原子分组会抛弃后退位置。由于DFA不会回溯(要匹配的文本是针对正则表达式进行检查,而不是像NFA那样对文本进行正则表达式检查 - DFA会为每个决定打开一个分支),丢弃一些不存在的东西是毫无意义的。

我建议J.F.Friedl的掌握正则表达式(Google Books),他解释了DFA的一般概念:

  

DFA引擎:文字导向

     

将正则表达式导向的NFA引擎与引擎对比   扫描字符串,跟踪“当前在中的所有匹配”   “在今晚的例子中,当发动机达到t时,它会增加   与其当前正在进行的列表的潜在匹配:

     

[...]

     

扫描的每个后续字符都会更新可能的列表   火柴。经过几个字符匹配后的情况   变

     

[...]

     

有两个可能的比赛正在进行中(还有一个替代,骑士,   排除)。随后的g,只有第三种选择   仍然可行。一旦h和t被扫描,发动机   意识到它完全匹配并且可以返回成功。

     

我将此称为“文本导向”匹配,因为每个字符都是扫描的   从文本控制引擎。如示例中所示,部分匹配   可能是任何数量的不同但可能的比赛的开始。   不再可行的匹配被修剪为后续字符   扫描。甚至有些情况下“部分匹配”   进步“也是完全匹配。如果正则表达式是⌈to(...)?⌋,那么   例如,带括号的表达式变为可选,但它仍然是   贪心,所以总是尝试。部分匹配的所有时间   在这些括号内进行,完全匹配('to')   已经确认并保留,以防较长的比赛不平息   进行。

(资料来源:http://my.safaribooksonline.com/book/programming/regular-expressions/0596528124/regex-directed-versus-text-directed/i87

关于捕获群组和DFA:就我能从您的链接中理解而言,这些方法不是纯粹的DFA引擎,而是DFA和NFA的混合。