Parsing LL(1)解析器中第一和后续集合的用途?

Parsing LL(1)解析器中第一和后续集合的用途?,parsing,context-free-grammar,ll,Parsing,Context Free Grammar,Ll,有人能给我解释一下在LL(1)语法中应该如何使用FIRST和FOLLOW吗?我知道它们是用于语法表构造的,但我不明白它们是如何工作的。在LL(1)解析器中,解析器的工作方式是维护一个工作区,该工作区最初是在开始符号的后面加上字符串结束标记(通常表示为$)。在每个步骤中,它都执行以下操作之一: 如果工作区的第一个符号是一个终端,它将与下一个输入标记相匹配(如果不匹配,则报告错误) 如果工作区的第一个符号是非终结符,则它会预测用什么产品替换该非终结符 预测步骤是第一步和后续步骤。解析器需要能够完

有人能给我解释一下在LL(1)语法中应该如何使用FIRST和FOLLOW吗?我知道它们是用于语法表构造的,但我不明白它们是如何工作的。

在LL(1)解析器中,解析器的工作方式是维护一个工作区,该工作区最初是在开始符号的后面加上字符串结束标记(通常表示为$)。在每个步骤中,它都执行以下操作之一:

  • 如果工作区的第一个符号是一个终端,它将与下一个输入标记相匹配(如果不匹配,则报告错误)
  • 如果工作区的第一个符号是非终结符,则它会预测用什么产品替换该非终结符
预测步骤是第一步和后续步骤。解析器需要能够完全基于当前的非终结符和输入的下一个标记来猜测使用哪个产品。问题是如何做到这一点

让我们假设当前的非终结符是A,输入的下一个标记是t。如果你知道A的作品,你会选择哪一个?有一个简单的例子需要考虑:如果有一个表单a的生成→ tω,其中ω是任意字符串,那么您应该选择该产品,因为您作为输入查看的t将匹配产品前面的t

也有一些复杂的情况需要考虑。假设你有一个形式a的产品→ Bω,其中B是非终结符,ω是某个字符串。在什么情况下,你会想猜这个产品?好的,如果你知道下一个终端符号是t,你不会想猜测这个结果,除非你知道B可以扩展成一个以终端t开头的字符串(还有另一种情况,我们稍后将讨论)。这就是第一盘的位置。在没有ε乘积的语法中,某些非终结符X的set FIRST(X)是可能出现在从X派生的某个字符串开头的所有终结符的集合→ Bω,你可以看到非终结符t,你可以猜测,当t∈第一(B);也就是说,B可以派生一些以t开头的字符串。如果B没有派生出以t开头的任何东西,那么就没有理由选择它,如果B确实派生出以t开头的东西,你会想做出这个选择,这样你最终可以将t与它匹配

引入ε乘积后,事情变得有点棘手。现在,让我们假设你有一个形式a的产物→ BCω,其中B和C是非终结符,ω是字符串。我们还假设输入的下一个标记是t。如果t∈首先(B),然后我们选择这个产品,如上所述。但是,如果t∉ 第一(B)?如果语法中有ε产生式,如果B可以导出ε和t&in,我们可能仍然希望选择这个产生式;第一(C)。为什么会这样?如果发生这种情况,这意味着我们可以通过生成BCω来匹配t,然后从B生成ε,留下Cω来匹配t。这是一个我们可能必须“查看”非终结符的上下文。幸运的是,这是由第一批人处理的。如果非终结符X可以产生ε,那么ε∈第一(X)。因此,我们可以使用第一组来检查是否需要通过查看ε∈第一(X)

到目前为止,我们还没有讨论跟随集。他们从哪里来?假设我们处理的是非终结符A,我们看到了终结符t,但是A的所有产品都不能实际使用t。那我们怎么办?事实证明,我们还是有办法吃掉t。记住,LL(1)解析器通过维护一个包含字符串的工作区来工作。有可能我们正在研究的t根本不应该与当前的非终结符A匹配,相反,我们应该有一个productε,然后让工作区中稍后的一些非终结符与t匹配。这就是FOLLOW set的用武之地。非终结符X的跟随集,表示为跟随(X),是在某些派生中可以紧跟在X之后出现的所有端子符号的集合。在为A选择哪一个产品时,我们添加了一个最终规则-如果终端符号t在A的后续集合中,我们选择最终将产生ε的产品。这样,A将“消失”,我们可以将t与出现在A非终结符后面的某个字符进行匹配

这不是对LL(1)解析的完整介绍,但我希望它能帮助您了解为什么我们需要FIRST和FOLLOW集合。有关更多信息,请阅读一本关于解析的书(我推荐解析技术:Grune和Jacobs的实用指南),或者学习一门关于编译器的课程。作为一个无耻的插件,我在2012-2013年夏天教了一门编译器课程


希望这有帮助

谢谢,解释得很好,很有帮助!祝你一切顺利!我想补充一点,能得到斯坦福大学教授的回答是我的荣幸在你们大学听课程太好了…@templatetypedef:You's slides很好也很有趣。不仅仅是这些(CS143),还有CS103。我想知道哪个更重要:优先还是跟随?我浏览了维基百科,它说它(先跟冲突)是否存在类似左递归的情况?除了上述情况(左递归)之外,还有其他情况发生吗?为什么跟随集不包含“epsilon”。这背后有什么原因吗?或者这只是一个规则吗?@templatetypedef:很抱歉评论第一次跟随冲突,因为您已经回答了。您的幻灯片非常好而且有趣,不仅仅是这些幻灯片(CS143)但是CS103也是。你能告诉我为什么FOLLOW集合不包含epsilon吗?@justin,我想这就是它的定义。FOLLOW(A)是在任何派生中合法出现在A之后的所有字符的集合,因为空字符串不是字符