最强大的解析器是什么?


28

作为附带项目,我正在使用Python编写语言。我从使用称为Ply的flex / bison克隆开始,但是在那种语法风格所能表达的功能方面,我处于优势地位,并且由于与阻抗不匹配,我对破解我的语言不感兴趣。工具。因此,我不反对自己编写。

那么,最强大的解析器类型是什么?欢迎引用论文(以及更多介绍性文章)。

(我知道“功能强大”的定义不明确,但让我们稍微放松一点,看看答案在哪里)


1
不赞成投票:没有研究水平。
沃伦·舒迪

3
@沃伦:我问之前已经检查了常见问题-这似乎不是必需的。
Paul Biggar

1
实际上有两种常见问题解答,一种针对一般站点,另一种针对CStheory。CS理论指出,可以通过阅读Wikipedia回答的问题是题外话。请参阅“什么样的问题太基础了?” 在meta.cstheory.stackexchange.com/questions/225/…中
沃伦·舒迪

1
@沃伦:那是我读的常见问题。我已经阅读了维基百科,但是我觉得这需要实际的见识。
Paul Biggar

1
您是指生产中的解析器还是理论上的解析器,即涵盖CFG以外的语法类型的解析器?
拉斐尔

Answers:


33

文法通常被定义为一个上下文无关文法 -一个确切的定义是维基百科的页面上给出的,但是,当它在PLY,这是基于确实它的工作原理相同的野牛,其又基于YACC

在这里说PLY使用LALR解析器。从本质上讲,这是一个LR解析器,在该解析器中会压缩查找表,这可能会引入解析冲突,从而降低LR语法的某些表现力(即LR解析器可以解析的上下文无关语法)。如果您想了解解析器这个特定分支和其他解析器的局限性,请在此处概述各种解析技术(LL,LR和其他)。

要回答您的问题:即使语言模棱两可,也存在能够解析任何无上下文语言的解析算法(即,有多种方法可以解释输入):

第一个这样的算法是CYK算法,不幸具有一个运行时间,其中Ñ是输入字符串的长度和| G | 是语法的大小,因此对于解析语言而言是不切实际的。O(n3|G|)n|G|

第二种算法是Earley算法。该算法还能够解析任何上下文无关的语法。尽管该算法需要时间来解析一种模棱两可的语言,但它只需要O n 2时间来解析一种模棱两可的语言。另外,对于大多数LR语法,它显然可以在线性时间内工作,并且在左递归语法中,效果特别好。O(n3)O(n2)

在这里,您可以找到一篇论文,讨论Earley算法的实际实现(改编)。他们得出结论:“鉴于Earley解析与LALR(1)解析((大致是PLY所做的)相比)的一般性,并且考虑到即使是PEP((Earley算法的实现)),最坏的时间也不会引起注意。用户,这是一个极好的结果”。

解析器的最后一种类型是GLR解析器。这是LR解析的通用版本,能够解析任何上下文无关的语言。

GLR的成熟实现是ASF + SDF。Bison也可以生成GLR解析器,尽管其实现与“标准” GLR算法略有不同。所述Elkhound算法是一个GLR / LALR混合算法。它尽可能使用LALR,并在需要时使用GLR,以便既快速又能够解析任何语法。

除了上下文无关的语法外,还有上下文敏感的语法,但是这些语法通常很难解析,并且不会增加太多的表现力:您可以使用它们做更多的事情,但是对于大多数应用程序,多余的用途并不重要,除非您要解析一种自然的语言。

作为最后一步,存在不受限制的语法。在这一点上,语法是图灵完备的,因此无法给出解析特定语言所花费的时间,这对于大多数解析应用程序是不希望的。几乎不需要额外的电源。如果您确实想使用所有功能,则可以使用语言机器

最后,实现您自己的解析器生成器并不是一件容易的事,尤其是要使其更快。我个人刚刚完成了自己的flex版本(lexer生成器)的制作,尽管这似乎是在相对简单的算法问题中进行的练习,但是正确起来变得相当复杂,尤其是当我尝试支持Unicode时。考虑使用现有的实现而不是编写自己的实现。


1
优秀的答案!关于PEG如何适应的任何想法?
Paul Biggar

2
PEG与CFG有“不同”:有些CFG不是PEG,反之亦然。我在这里指给您:stackoverflow.com/questions/1857022/…
Alex 10 Brink 2010年


1
实际上,大多数常见的解析器生成器(yacc,Antlr,bison)都允许通过谓词或任意代码检查非CF概念,以检查是否可以分别应用一条规则。决定优先顺序。这可以用于实现静态语义,主要是因为基本语法在本质上保持上下文无关。
拉斐尔

1
递归语言正是图灵机始终停止可决定的语言。因此,任何上下文相关的语言也是递归的,但是由于上下文相关的语言可以在指数时间内确定,因此存在一些上下文无关的递归语言。不受限制的语法甚至更强大:停止问题可以由不受限制的语法来描述,但不是递归语言。
亚历克斯十布林克

15

今年在ICFP 2010上的一篇论文,Total Parser Combinators,描述了一个可证明的终止解析器组合器库,并且还确定了在保证解析器能够终止的情况下,“解析器组合器尽可能具有表现力”。不幸的是,我不记得作者为“尽可能表现力”的含义所作的解释,但它显然与您关于“权力”的问题有关。


1
我有一辆不会污染的汽车,实际上它也不会动...所以问题是:此库解析了哪种语言?当然,这并不意味着这项工作并不有趣。
babou 2013年

2

如果您想超越上下文无关的语法来解析编程语言,但仍可以在多项式时间内进行解析,则可以采用解析表达式语法布尔语法 -后者也具有LL和LR风格(请参见此处)。在形式语言理论中,还研究了功能强大但线性时间可识别的Church-Rosser语言,但是我不知道有没有为这些语言实现的解析器生成器。

在自然语言处理中,品味不同,例如,处理歧义(也:固有歧义)和自由词序起着非常重要的作用。在这里,关键字对上下文敏感,并且会自动启动,可能会帮助您开始阅读。


1
考虑到问题的提出方式,以及对CF过于严格的抱怨,您的答案显然是最好的。事实如此……
babou

0

解析器生成器工具:

ANTLR非常好。另外,您可以看一下JavaCC


我不是最科学的计算机(尽管我的学位是什么意思;),所以在这里我的话语可能会轻描淡写。我同意Sazzad-ANTLR是非常强大的工具。它非常完整,解析器生成器(如果我没记错的话,LL(k))还没有发现任何问题。在另一方面,我还没有实现的一个比较复杂的语法编译器...
约尔根Sigvardsson

5
我认为您错过了问题的重点,也许是整个网站。它是关于解析理论,而不是关于实现和工具。
Paul Biggar 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.