Treetop回溯类似于正则表达式?

时间:2012-10-17 04:38:06

标签: ruby treetop peg

我读到的一切都表明Treetop像正则表达式一样回溯,但我很难做到这一点。

假设我有以下语法:

grammar TestGrammar
  rule open_close
    '{' .+ '}'
  end
end

这与字符串{abc}不匹配。我怀疑那是因为.+消耗了a以后的所有内容。即当我只想要消费abc}时,它会消耗abc

这似乎与类似的正则表达式不同。正则表达式/{.+}/将匹配{abc}。我的理解是这是可能的,因为正则表达式引擎在使用}作为.+的一部分后关闭}后回溯,然后无法匹配。

Treetop可以做那样的回溯吗?如果是这样,怎么样?

我知道你可以使用否定来匹配“{ab}c}以外的任何东西”。但这不是我的意图。假设我希望能够匹配字符串{。在这种情况下,我想要的标记是开头ab}c,中间字符串}和结束{a b {c d}}。这是一个人为的例子,但在使用{{1}}等嵌套表达式时它变得非常重要。

1 个答案:

答案 0 :(得分:2)

Treetop是Parsing Expression Grammar解析器的实现。 PEG的一个好处是它们的灵活性,速度和内存要求的结合。然而,这种平衡行为有一些权衡。

引自维基百科的文章:

  零或多个,一个或多个和可选的运算符分别消耗其子表达式e的零个或多个,一个或多个,或零个或一个连续重复。然而,与无上下文语法和正则表达式不同, 这些运算符始终表现得很贪婪 ,消耗尽可能多的输入并且 永远不会回溯 > 即可。 [...]表达式(a* a)将始终失败,因为第一部分(a*)永远不会为第二部分留下任何匹配。

(强调我的。)

简而言之:虽然某些PEG运营商可以回溯试图采取另一条路线,但+运营商却不能。

相反,为了匹配嵌套的子表达式,您需要在分隔的子表达式(先检查)后跟非表达式字符之间创建一个替换。像(未经测试)的东西:

grammar TestGrammar
  rule open_close
    '{' contents '}'
  end
  rule contents
    open_close / non_brackets
  end
  rule non_brackets
    # …
  end
end