就像标题所说的那样,上周末我花了几个小时试图确定与Perl兼容的正则表达式匹配的语言类别,但不包括允许在模式内执行任意代码的任何匹配运算符。
问题在于,Internet上可用的资源几乎都停留在上下文无关的语言中,PCRE可以匹配的资源更多(参见下文);但是我真的不知道在哪里可以找到更多关于这类东西的定理或论文。
特别是:PCRE显然是常规语言的超集(因为PCRE语法具有所有常规语言运算符)。
任何CFG都可以Greibach正常形式放置,从而消除了左递归。我认为可以通过(?(DEFINE)...)
组的方式将语法“翻译”为匹配的子例程,从而避免通过翻译而使左递归阻塞:
- 每个生产的开头的非终止符成为子例程
(?<HEAD>...)
- 每个产品的主体都放在子例程中;终端保持原样,非终端成为过程调用(即
(?&NONTERMINAL)
); - 通过
|
操作员将所有具有与头部相同的非终结符的产品进行“或” 运算((?:...)
如果需要,还可以加上与的附加分组) - 然后,模式变成一个
(?(DEFINE)...)
包含所有“翻译的”产生式的组,以及对起始符号过程的调用,以匹配整个字符串,即^(?(DEFINE)...)(?&START)$
这应该处理任何CFG。因此,PCRE应该能够匹配任何CFL。
还有更多:让我们采用简单的语言 即字符串的语言重复两次。该语言不是CFL-CFL的抽奖引理失败。(尤其要注意 必须保持,因此,您不能仅泵送两个重复字符串的开头或结尾。)| v x w | ≤ p
但是,PCRE可以轻松匹配此语言:^(.*)\1$
。因此,我们绝对超越CFL。
以上多少?好吧,正如我所说,我不知道。我找不到关于CSL或介于两者之间的所有其他类的任何资源来下定决心。有专家愿意讨论这个吗?
附录:要求我确切指定必须允许PCRE语法的哪个子集。正如我在文章开头所写的那样,我想排除任何允许在模式内部执行任意代码的运算符,例如??{}
。
就参数而言,我认为我们可以坚持使用pcresyntax(3)手册页定义的语法,该语法是Perl 5.10-5.12提供的内容的合理子集,减去了标注(因为它们不在模式内)。我不确定添加或删除回溯控制动词会改变我们可以识别的语言;如果是这样,那么弄清楚我们有哪些类和没有这些类会很好。