递归语法定义的Ruby正则表达式?

递归语法定义的Ruby正则表达式?,ruby,regex,Ruby,Regex,如何使用正则表达式验证递归语法定义?例如,假设我有以下语法: alpha := <beta> gamma | <alpha> <beta> beta := delta epsilon α:=γ| β:=δε 这只是我所说的递归定义的一个例子——我不是在寻找一个专门解决这个问题的正则表达式,而是寻找如何用正则表达式处理类似问题的更多方法。这里有一种方法可以匹配Ruby 1.9中的递归模式,在这种情况下,可以使用任意级别的嵌套大括号: #!/usr/bin

如何使用正则表达式验证递归语法定义?例如,假设我有以下语法:

alpha := <beta> gamma | <alpha> <beta> beta := delta epsilon α:=γ| β:=δε
这只是我所说的递归定义的一个例子——我不是在寻找一个专门解决这个问题的正则表达式,而是寻找如何用正则表达式处理类似问题的更多方法。

这里有一种方法可以匹配Ruby 1.9中的递归模式,在这种情况下,可以使用任意级别的嵌套大括号:

#!/usr/bin/env ruby

text = "... { a { b { c } b } a { d } a } ...";
match = text.match(/(?<entire>\{(?:[^{}]+|\g<entire>)*\})/).captures
puts match
模式的快速分解:

(?<entire>        # start named capture group called <entire>
  \{              #   match the literal '{'
  (?:             #   start non capture group 1
    [^{}]+        #     match one or more chars other than '{' and '}'
    |             #     OR
    \g<entire>    #     recursively match named group <entire>
  )*              #   end non capture group 1 and repeat it zero or more times
  \}              #   match the literal '}'
)                 # end named capture group called <entire>
(?#启动名为
\{#匹配文字'{'
(?:#启动非捕获组1
[^{}]+#匹配除“{”和“}”以外的一个或多个字符
|#或
\g#递归匹配命名组
)*#结束非捕获组1并重复零次或多次
\}#匹配文字'}'
)#结束名为的捕获组

您的语法似乎只生成无限单词:-)正则表达式只生成正则语言,而不是任意递归语言-这可能是不可能的。检查支持递归的味道。@Kvass Bergi在第一条评论中说的是错误的。你不应该在意它。大多数现代正则表达式引擎(包括在Ruby中采用的Onigom)都比正则语法强大得多。自从Ruby 1.9以来,Ruby的正则表达式可以处理递归。@JörgWMittag根据您刚才所写的内容,正则表达式和regex/regexen之间的区别只是Perl社区内的一项发明,在该社区之外并不存在(Larry Wall和一些追随者)。人们通常不会区分它们,正因为如此,我不认为这种区分有助于避免混淆。这只是增加了另一层混乱。如果他们想纠正这个用法,他们应该引入一个完全不同于“regex”的词。无论如何,在Ruby的上下文中,正则表达式和正则表达式是相同的。@JörgWMittag此外,Bergi的主张是,可能不可能进行递归,因为它是正则表达式。但是很明显,OP所指的正则表达式就是您(perler)所称的regex,因为Ruby中没有您(perler)所称的正则表达式。它具有处理递归的能力,所以我反对Bergi的观点是正确的,不管我们是否采用Perlish术语。
(?<entire>        # start named capture group called <entire>
  \{              #   match the literal '{'
  (?:             #   start non capture group 1
    [^{}]+        #     match one or more chars other than '{' and '}'
    |             #     OR
    \g<entire>    #     recursively match named group <entire>
  )*              #   end non capture group 1 and repeat it zero or more times
  \}              #   match the literal '}'
)                 # end named capture group called <entire>