Haskell中的广义自下而上的解析器组合

时间:2014-06-05 02:57:17

标签: parsing haskell parsec parser-combinators attoparsec

我想知道为什么在Haskell中没有用于自下而上解析的通用解析器组合器,就像Parsec组合器一样,用于自顶向下解析。
(我可以在2004年找到一些研究工作,但是之后没有 https://haskell-functional-parsing.googlecode.com/files/Ljunglof-2002a.pdf http://www.di.ubi.pt/~jpf/Site/Publications_files/technicalReport.pdf

是否有任何具体原因未能实现?

4 个答案:

答案 0 :(得分:12)

这是因为参考透明度。正如没有任何功能可以区分

let x = 1:x
let x = 1:1:1:x
let x = 1:1:1:1:1:1:1:1:1:...  -- if this were writeable

没有函数可以区分作为有限图的语法和作为无限树的语法之间的区别。自下而上的解析算法需要能够将语法看作图形,以便枚举所有可能的解析状态。

自上而下的解析器将其输入看作无限树这一事实使它们更强大,因为树在计算上可能比任何图形更复杂;例如,

numSequence n = string (show n) *> option () (numSequence (n+1))

接受从n开始的任何有限的升序数字序列。这具有无限多种不同的解析状态。 (有可能以无上下文的方式表示这一点,但它会很棘手并且需要比解析库能够更好地理解代码,我认为)

自下而上的组合器库可以编写,虽然它有点难看,要求所有解析器都以“标记”方式

  • 相同的标签总是指同一个解析器,
  • 只有一组有限的标签

此时它开始看起来更像传统的语法规范而不是组合规范。但是,它仍然可以很好;你只需要标记递归制作,这将排除任何无限大的规则,如numSequence

答案 1 :(得分:4)

由于luqui的回答表明自下而上的解析器组合器库不太现实。如果有人访问此页面只是寻找haskell的自下而上解析器生成器,那么您正在寻找的是the Happy parser generator。对于haskell来说就像yacc

答案 2 :(得分:4)

正如luqui上面所说:Haskell对递归解析器定义的处理不允许定义自下而上的解析库。如果您以不同方式表示递归语法,则可以使用自下而上的解析库。对于自我推销道歉,使用这种方法的一个(研究)解析器库是grammar-combinators。它实现了一个称为统一Paull转换的语法转换,可以与自上而下的解析器算法结合使用,以获得原始语法的自下而上的解析器。

答案 3 :(得分:1)

@luqui本质上说,在某些情况下,共享是不可观察的。但是,通常情况并非如此:存在许多可观察的共享方法。例如。 http://www.ittc.ku.edu/~andygill/papers/reifyGraph.pdf提到了几种实现可观察的共享的方法,并提出了自己的新方法:

  

此循环结构可用于解释,但不能用于   进一步分析,漂亮印刷或常规处理。的   这里的挑战和本文的主题是如何允许树木   从Haskell提取的托管深度DSL,具有可观察到的后端,   或更一般而言,可观察的共享。这是一个容易理解的问题,   带有许多标准解决方案。

请注意,@ liqui的“丑陋”解决方案在本文中以 explicit标签的名称提及。该论文提出的解决方案仍然很“丑陋”,因为它使用了所谓的“稳定名称”,但是其他解决方案(例如http://www.cs.utexas.edu/~wcook/Drafts/2012/graphs.pdf(依赖PHOAS)也可能有效。