我一直在考虑使用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文档声称它可以“解析上下文相关的,无限的超前语法”,因此好像我应该可以在这里做些什么。

最佳答案

可以使用Parsec的notFollowedBy来确保integer消耗了所有内容,直到某个 token 分隔符为止(此方法在大多数情况下将扩展到任意方案),或者查看解析器组合器,探索所有可能的解析替代方案。首先想到的是UU_Parsing库。

07-26 08:54
查看更多