我是Haskell和Parsec的新手。在阅读Chapter 16 Using Parsec of Real World Haskell之后,我脑子里出现了一个问题:Parsec为什么以及何时比Yacc / Bison / Antlr等其他解析器生成器更好?
我的理解是Parsec创建了一个很好的编写解析器的DSL,而Haskell使它非常容易和富有表现力。但解析是一种标准/流行的技术,值得使用自己的语言,输出到多种目标语言。那么我们何时应该使用Parsec而不是从Bison / Antlr生成Haskell代码?
这个问题可能会超越技术,进入行业实践领域。从头开始编写解析器时,与Bison / Antlr或类似的东西相比,拾取Haskell / Parsec有什么好处?
顺便说一句:我的问题与this one非常相似,但在那里没有得到令人满意的回答。答案 0 :(得分:55)
您列出的工具之间的主要区别之一是ANTLR,Bison和他们的朋友是解析器生成器,而Parsec是解析器组合器库。
解析器生成器读入语法描述并吐出解析器。通常不可能将现有语法组合成新语法,并且当然不可能将两个现有生成的解析器组合成新的解析器。
解析器组合器OTOH不执行任何操作,但将现有解析器组合到新解析器中。通常,解析器组合器库附带了几个简单的内置解析器,可以解析空字符串或单个字符,它附带一组组合器,它们接受一个或多个解析器并返回一个新的解析器,例如,解析原始解析器的序列(例如,您可以组合d
解析器和o
解析器以形成do
解析器),原始解析器的交替(例如{{{ 1}}解析器和0
解析器到1
解析器)或多次解析原始解析(重复)。
这意味着您可以为Java提供现有的解析器和HTML的现有解析器,并将它们组合成JSP的解析器。
大多数解析器生成器不支持此功能,或仅以有限的方式支持它。解析器组合器 OTOH 仅支持支持此功能。
答案 1 :(得分:9)
您可能希望在问题中看到此问题以及链接的问题。
Which Haskell parsing technology is most pleasant to use, and why?
在Haskell中,竞争是在Parsec(和其他解析器组合器)和解析器生成器Happy之间进行的。如果我已经使用LR语法,我会选择Happy - 解析器组合器以LL形式学习语法,从LR到LL的转换需要付出一些努力,组合器解析器通常会慢得多。如果我没有语法,我将使用Parsec,它比Happy更灵活(强大),在Haskell中工作比用Happy和Alex生成代码更有趣。如果你使用Happy来解析你几乎总是需要使用Alex来进行解析。
对于行业惯例,决定使用Haskell来获取Parsec会很奇怪。对于解析,当前大多数语言将至少具有解析器生成器,并且可能更灵活,如Parsec端口或PEG系统。
艾拉·巴克斯特对这个相关问题的回答是关于一个解析器只是为了编写一个翻译而让你只是喜马拉雅山的立足点,但是成为翻译者的一部分只是其中一个用途对于解析器,所以仍然有许多域,其中像ANTLR,Happy和Parsec这样的极简主义系统是令人满意的。
答案 2 :(得分:6)
继斯蒂芬的回答之后,我认为如果你想坚持使用解析器组合,Parsec最常见的替代方法之一是attoparsec。主要的区别在于,attoparsec写的更多偏向于速度,并相应地进行权衡。例如,如果解析失败,Parsec会进行一些记账以尝试返回有用的错误消息,而attoparsec在相同程度上没有这样做。另外,我认为attoparsec专门用于一个输入流/令牌类型,而Parsec从输入类型中抽象出来,以便它可以解析String,ByteString,Text等类型的流而没有问题。