【问题标题】:Can Haskell's Parsec library be used to implement a recursive descent parser with backup?Haskell 的 Parsec 库可以用于实现带备份的递归下降解析器吗?
【发布时间】:2011-01-29 19:36:44
【问题描述】:

我一直在考虑使用 Haskell 的 Parsec 解析库将 Java 的一个子集解析为递归下降解析器,以替代更传统的解析器生成器解决方案,例如 Happy。 Parsec 似乎很容易使用,解析速度对我来说绝对不是一个因素。不过,我想知道是否有可能使用 Parsec 实现“备份”,这是一种通过依次尝试每一个来找到要使用的正确产品的技术。举个简单的例子,考虑 JLS Java 语法的最开始:

Literal:
    IntegerLiteral  
    FloatingPointLiteral

我想要一种不必弄清楚我应该如何排序这两个规则才能使解析成功的方法。就目前而言,像这样的幼稚实现:

literal = do {
    x <- try (do { v <- integer; return (IntLiteral v)}) <|>
         (do { v <- float; return (FPLiteral v)});
    return(Literal x)
}

不会工作...像“15.2”这样的输入会导致整数解析器首先成功,然后整个事情都会被“.”阻塞。象征。当然,在这种情况下,很明显可以通过重新排序两个产品来解决问题。但是,在一般情况下,找到这样的事情将是一场噩梦,而且我很可能会错过一些案例。理想情况下,我想要一种方法让 Parsec 为我找出这样的东西。这是可能的,还是我只是想对图书馆做太多事情? Parsec 文档声称它可以“解析上下文相关的无限前瞻语法”,所以看起来我应该可以在这里做点什么。

【问题讨论】:

    标签: parsing haskell computer-science theory parsec


    【解决方案1】:

    您可以做到这一点的一种方法是使用try 组合器,它允许解析器使用输入并在不失败整个解析的情况下失败。

    另一个是使用Text.ParserCombinators.ReadP,它实现了一个对称选择运算符,其中证明了a +++ b = b +++ a,所以实际上哪个顺序并不重要。我比较偏爱ReadP,因为它很小但提供了构建真正强大的解析器所需的东西。

    【讨论】:

    • 请注意,经过一些经验后,我对ReadP 的吸引力降低了。它有一些有时很难找到的指数行为,并且不会很好地失败。 Parsec 更大更笨重,但我现在发现更好的软件。
    【解决方案2】:

    要么使用 Parsec 的 notFollowedBy 来确保 integer 消耗所有内容,直到某个标记分隔符(这种方法大部分时间都可以扩展到任意场景),或者查看探索所有可能的解析替代方案的解析器组合器。首先想到的是UU_Parsing library。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-01
      • 2015-08-07
      • 1970-01-01
      • 1970-01-01
      • 2018-03-25
      相关资源
      最近更新 更多