3

我正在使用一些解析器和词法分析器生成工具(类似于 Lex 和 Bison,但用于 C#)来生成将字符串解析为抽象语法树的程序,以便以后进行评估。

我想做错误恢复(即在生成的抽象句子树中报告缺少标记等)。我有两种方法来构建生成的语法,我想知道哪种方法更好/更灵活/不会发生冲突(.y 和 .lex 文件是根据计算器的描述生成的)。

计算器描述允许用户指定终端/正则表达式及其对运算符和关联性的位置。所以像:

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

Terminal(通过添加's 和NonTerminal's的顺序指定优先级。"Add"是通过反射发现的方法的名称。基本上它告诉 NonTerminal 在抽象语法树中调用运算符的内容。)


方法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 中的空规则使事情变得更简单,代码方面,但我主要担心的是,当程序员创建计算器描述时,哪种方法会产生最少的语法问题如上所述。

4

1 回答 1

4

这个问题已经存在了一段时间,涵盖了该主题的初学者经常访问的主题。人们经常会发现,那些在本科阶段上过编译器课程的人都知道,这是那些没有简单或单一答案的问题之一。您可能已经注意到您有两个关于同一主题的问题,但都没有得到回答。其他人发布的另一个问题是通过指向解释为什么这很难的文献来回答的。

这是一个存在 50 多年的问题。如果随着时间的推移检查文献,从早期的会议论文、课程教科书、博士论文和(今天)SO,我们可以看到经常提到这是一个错误的问题这一事实!(或者更确切地说是解决问题的错误方法)。

只是从多年来的课程文本中抽取样本(从我的书架上随机选择):

Gries, D. (1970) 错误恢复和纠正 - 文献介绍,编译器构造,高级课程,由 Bauer, FL & Eickel, J., Springer Verlag, pp.627-638 编辑。
Gries, D. (1971)数字计算机的编译器构建,Wiley,pp.320-326。
Aho, AV, Ullman, JD (1977)编译器设计原理,Addison Wesley,pp.397-405。
Bornat, R. (1979)理解和编写编译器,Macmillan,pp.251-252。
Hanson, D. (1995) A retargetable C compiler: Design and Implementation , Addison-Wesley, pp.140-146。
Grune, D., Bal, HE, Jacobs, CJH & Langendoen, KG (2000)现代编译器设计,Wiley,第 175-184 页。
Aho, AV, Lam, MS, Sethi, R., Ullman, JD (2007)编译器:原理、技术和工具,Pearson, Addison-Wesley,pp.283-296。

所有这些都同意(超过 40 年),您的问题是关于错误地使用错误的工具或朝着错误的方向前进。我想我想说“你不能从这里到那里”。你应该从别的地方开始。

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

Charles, P. (1991) A Practical method for Constructing Efficient LALR(k) Parser with Automatic Error Recovery,纽约大学

希望将来再次访问此问题的人可以找到答案的占位符。


我从评论中注意到您正在使用源自 CPPG 的 MPPG。不是每个人都会使用这些工具,所以我提供了一些指向这些工具的链接:

Managed Babel Systems Essentials
Garden Points Parser Generator
Irony .NET 编译器构建工具包
编写您的第一个 Visual Studio 语言服务

于 2015-04-21T16:08:21.307 回答