1

我正在为编译器设计课程编写一个编译器,我正在编写一个语法分析,我需要编写一个解析器。如何在编译器内对FIRST&FOLLOW集进行编码

我需要有FIRST和FOLLOW集来处理可能出现在源文本中的任何错误。我已经为我的语法中的所有非终端预先计算了FIRST和FOLLOW集,但是我无法确定我应该在哪里将它们实际编码到我的程序中。

我应该把它们放在一个映射中,其中的键是非终端的名称吗?

任何意见将是有益的

这篇文章看起来可能有点不清楚,如果需要,我可以澄清任何点。

回答

2

如果你想保留它们,你想把它们附加到它们所代表的非终结符。您可能还想要反转,例如,来自集合成员的映射返回到它们是FIRST或FOLLOW的非终止符。

然后,您错误恢复例程可以使用以前或更可能的“下一个”输入标记(这是导致您报告错误的那个标记)来决定可以插入到输入流中的内容。

我实际上没有存储这些。我使用一个GLR解析器,其解析表本质上是LALR解析表,并且简单地构建一个递归算法来遍历这些表,以查看哪些标记可能允许解析器继续。间接地,我利用FIRST和FOLLOW,因为那些被用来构造分析表。

如果您正在进行编译器设计课程,建议重点关注解析后问题。你可以花费大量的时间来试图“修补”源代码来应对错误,而你所学到的只是a)这很难,b)没有人会特别喜欢你提供的选择。你可以在修复语法上花费精力,直到你脸色发青,但我会等到有人让你去找工作。同时,对于编译器类,我会让编译器简单地说:“N行的语法错误”并中止。 不错,但足以让你继续更有趣的部分。

+0

在处理语法错误时,我还想停止遇到的第一个遇到的错误,因为显然用户需要在编译成功之前修复该错误;但是这个项目的一个要求是,我必须在向用户报告之前收集所有的语法错误。 – 2012-03-17 21:11:58

+0

你能解释更多关于反演吗?这基本上是一个从所有终端符号映射到一个非终端X的映射吗?也感谢您的回复,这非常有帮助。 – 2012-03-17 21:14:08

+1

@Hunter:“收集所有语法错误?”这有点含糊,因为一旦你修补了你的输入,解析器就可以继续了,你已经猜到了程序员的实际意图,猜测是不对的。通常,一旦解析器继续运行,它将遇到另一个(“级联”)语法错误......是用户所做的还是由错误恢复引起的错误?一个便宜的技巧:如果输入令牌不可接受,请报告语法错误,删除它并继续前进(您可能会抑制在同一地点发生的其他语法错误)。 ... – 2012-03-17 21:16:32