【问题标题】:Treetop backtracking similar to regex?树顶回溯类似于正则表达式?
【发布时间】:2012-10-17 04:38:06
【问题描述】:

我读过的所有内容都表明 Treetop 会像正则表达式一样回溯,但我很难做到这一点。

假设我有以下语法:

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

这与字符串 {abc} 不匹配。我怀疑这是因为.+ 正在消耗从a 开始的所有内容。 IE。当我只希望它消耗 abc 时,它正在消耗 abc}

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

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

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

【问题讨论】:

    标签: ruby treetop peg


    【解决方案1】:

    Treetop 是Parsing Expression Grammar 解析器的实现。 PEG 的好处之一是它们结合了灵活性、速度和内存要求。但是,这种平衡行为有一些取舍。

    引自维基百科文章:

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

    (强调我的。)

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

    相反,为了匹配嵌套的子表达式,您希望在分隔的子表达式(首先检查)和非表达式字符之间创建一个交替。类似(未经测试):

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

    【讨论】:

    • 谢谢!您将如何使用 PEG 实现我所描述的目标?
    • @Jarrett 查看我的编辑。原谅可能严重破坏的语法;自从我上次使用 Treetop 以来已经有好几年了。请注意,维基百科条目专门讨论了这一点(在页面上搜索“Pascal-style nested comment syntax”)。
    • 太棒了!谢谢!匹配这个字符串怎么样:{ab}c}
    • 知道了。我决定只需要将 {ab}c} 中的第一个 } 而非最后一个 } 视为右括号。那么,字符串 c} 可以被视为普通的旧文本。不完全是我想要的,但这是一个合理的妥协。我不确定,但我开始认为这可能必然源于 PEG 的性质。
    猜你喜欢
    • 1970-01-01
    • 2012-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-23
    • 1970-01-01
    相关资源
    最近更新 更多