与Perl兼容的正则表达式可以识别哪些语言?


23

就像标题所说的那样,上周末我花了几个小时试图确定与Perl兼容的正则表达式匹配的语言类别,但不包括允许在模式内执行任意代码的任何匹配运算符

如果您不知道什么是PCRE,请阅读此内容本内容

问题在于,Internet上可用的资源几乎都停留在上下文无关的语言中,PCRE可以匹配的资源更多(参见下文);但是我真的不知道在哪里可以找到更多关于这类东西的定理或论文。

特别是:PCRE显然是常规语言的超集(因为PCRE语法具有所有常规语言运算符)。

任何CFG都可以Greibach正常形式放置,从而消除了左递归。我认为可以通过(?(DEFINE)...)组的方式将语法“翻译”为匹配的子例程,从而避免通过翻译而使左递归阻塞:

  • 每个生产的开头的非终止符成为子例程 (?<HEAD>...)
  • 每个产品的主体都放在子例程中;终端保持原样,非终端成为过程调用(即(?&NONTERMINAL));
  • 通过|操作员将所有具有与头部相同的非终结符的产品进行“或” 运算((?:...)如果需要,还可以加上与的附加分组)
  • 然后,模式变成一个(?(DEFINE)...)包含所有“翻译的”产生式的组,以及对起始符号过程的调用,以匹配整个字符串,即^(?(DEFINE)...)(?&START)$

这应该处理任何CFG。因此,PCRE应该能够匹配任何CFL。

还有更多:让我们采用简单的语言 即字符串的语言重复两次。该语言不是CFL-CFL的抽奖引理失败。(尤其要注意 必须保持,因此,您不能仅泵送两个重复字符串的开头或结尾。)| v x w | p

大号={ww|wΛ}
|vXw|p

但是,PCRE可以轻松匹配此语言:^(.*)\1$。因此,我们绝对超越CFL。

以上多少?好吧,正如我所说,我不知道。我找不到关于CSL或介于两者之间的所有其他类的任何资源来下定决心。有专家愿意讨论这个吗?

附录:要求我确切指定必须允许PCRE语法的哪个子集。正如我在文章开头所写的那样,我想排除任何允许在模式内部执行任意代码的运算符,例如??{}

就参数而言,我认为我们可以坚持使用pcresyntax(3)手册页定义的语法,该语法是Perl 5.10-5.12提供的内容的合理子集,减去了标注(因为它们不在模式内)。我不确定添加或删除回溯控制动词会改变我们可以识别的语言;如果是这样,那么弄清楚我们有哪些类和没有这些类会很好。


2
请在您的问题中包括您选择的PCRE定义,因为不同版本之间的定义有所变化。真正的Perl正则表达式可以包含任意Perl代码,从而使它们成为图灵完整的。
吉尔斯(Gilles)'所以

我在最后添加了一个注释,希望这一点更加清楚。
2012年

Answers:


7

我也发现此博客帖子非常有趣,http://nikic.github.io/2012/06/15/The-true-power-of-regular-expressions.html。它提供了我之前给出的关于正则表达式可以识别CFL(通过DEFINE块重写语法)甚至某些CSL(例如重复字符串的语言)的事实的证明。它在此基础上继续进行,从而证明带有反向引用的正则表达式是NP难的(通过将3-SAT减少为正则表达式)。


2
当作者说“ NP-complete”时,他们应该说“ NP-hard”。他们没有提供证明PCRE语言的类别包含在NP中的证据。
安德拉斯·萨拉蒙

没错,评论中也有注明。
peppe

5

它们最多决定上下文相关的语言(如您所指出的,它是上下文无关语言的超集)。请参阅此perl僧侣职位

基本的见解是,机器的“内存”是捕获组的数量,捕获组是线性限制的。


5
您在第二段中给出的论点解释了为什么PCRE不能接受比CS 多的原因,但不能解释为什么此包含是准确的(您在第一段中建议)。似乎该链接文章也没有提供任何证明。
拉斐尔

嗯,您不能对输入字符串中的内容进行更多的分组,并且分组的数目在给定的模式中是固定的,因此您对模式使用的内存有上限(线性)限制。不过,我仍然错过了PCRE的正式证明->线性有界自动机转换...
peppe 2012年

是的,你们两个是对的。我已经修改了答案。
Xodarap 2012年

另请参见perlmonks.org/?node_id=406253,以获取更早的讨论。
安德拉斯·萨拉蒙
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.