在LALR(1)的语法的错误恢复(Error recovery in an LALR(1) gram

2019-09-21 00:53发布

我使用了一些解析器和词法分析器生成工具(类似于Lex和野牛,但对于C#)生成解析字符串转换为抽象语法树以后可以评估的计划。

我想要做的错误恢复(即报告中产生的抽象句树,有缺失的令牌和这样)。 我想到了两种方法来构建生成的语法,我想知道哪种方法比较好/比较灵活/不会有冲突 (中不间断地和.lex文件是基于计算器的描述产生的)。

计算器描述允许用户指定终端/正则表达式的及其对运营商和关联性安置。 因此,像:

grammar.AddTerminal("Plus", "\\+").
    AddNonTerminal(new NonTerminal("Add", Associativity.LeftToRight).
        AddTerminal("Expression").
        AddTerminal("Plus").
        AddTerminal("Expression"));

(优先通过该命令指定Terminal的和NonTerminal的加入。 "Add"是通过反射发现了一个方法的名称,基本上它告诉非终结叫什么操作的抽象语法树。 )


方法1:(允许任何表达空规则)

S -> E
E -> E + T
E -> T
T -> T * P
T -> P
P -> (E)
P -> (E [error]
P -> a
P -> @ [error]

a是一个终端。 @是空的。


方法2:(只允许开始规则空规则)

S -> E
S -> @ [error]
E -> + [error]
E -> T + [error]
E -> + T [error]
E -> E + T
E -> T
T -> * [error]
T -> * P [error]
T -> P * [error]
T -> T * P
T -> P
P -> (E)
P -> (E [error]
P -> a

下面是显示使用每种方法不好输入最左推导的例子。


输入: (a +


方法1:

S
E
T
P
(E
(E + T
(T + T
(P + T
(a + T
(a + P
(a +

方法2:

S
E
T
P
(E
(T +
(P +
(a +

方法2时更难代码(考虑减/一元负操作不能只看减。 A -> A - B ,取出,首先A ,并在报告错误A -> - B ,因为这是有效的单目运算符)。我编码方法2今天早上才发现,我认为它有语法问题和空规则在方案1使事情变得更简单,代码明智的,但我主要关注的是哪种方法会产生的语法问题程序员量最少创建计算器描述如上所述。

Answer 1:

这个问题已经存在了一段时间,并覆盖了一个经常被在主题初学者走访了话题。 人们常常发现,那些谁在他们的本科学位做了编译器当然知道,这是有没有简单或单一的答案的问题之一。 您可能已经注意到您有关于同一主题的两个问题 ,均未得到了解答。 另一个问题是别人贴得到的回答是指向这解释了为什么这是很难的文献。

这是一个已经超过50年保持现存的问题。 如果一个检查,博士论文和(今天)文献随着时间的推移,从早期的会议论文,课程教材SO ,我们可以看到经常引用的事实,这是一个错误的问题 ! (或者说错误的解决问题的方法)。

刚刚从课程文本多年来(从我的书架随机选择)取一个样本:

格里斯,D。(1970)错误恢复和纠错-介绍文献,在编译器构造,高级课程由鲍尔,FL&Eickel,J.,施普林格出版社,pp.627-638编辑。
格里斯,D.(1971) 编译器构造为数字计算机 ,威利,pp.320-326。
编译器设计 ,艾迪生韦斯利,pp.397-405 阿霍,AV,乌尔曼,JD(1977年) 的原则
Bornat,R.(1979) 理解和写作编译器 ,麦克米伦,pp.251-252。
汉森,D.(1995年) 一个可移植的C编译器的设计与实现 ,Addison-Wesley出版社,pp.140-146。
Grune,D.,BAL,HE,雅各布CJH&Langendoen,KG(2000) 现代编译器设计 ,威利,pp.175-184。
阿霍,AV,林,MS,塞西,R.,乌尔曼,JD(2007) 编译原理,技术和工具 ,皮尔森,Addison-Wesley出版社,pp.283-296。

所有这些人赞成(超过40年的跨度),你的问题是关于使用了错误的工具,误服或在错误的方向前进的。 我想我想说“你不能从这儿”。 你应该从别的地方开始。

如果你想更深层次的东西,有一个整体的博士论文:

查尔斯,P.(1991) 为构建高效的LALR(K)与自动错误恢复 ,纽约大学解析器的实用方法

我们希望,对于那些谁在将来再次访问这个问题,有一个答案的占位符。


我从您正在使用MPPG意见,从CPPG衍生注意。 不是每个人都会用这些,所以我包括一对夫妇的这些工具的链接:

托管巴贝尔系统必备
花园积分器生成器
具有讽刺意味的.NET编译器构建工具包
编写第一个Visual Studio的语言服务



文章来源: Error recovery in an LALR(1) grammar