Algorithm LR、SLR和LALR解析器之间的区别是什么?

Algorithm LR、SLR和LALR解析器之间的区别是什么?,algorithm,parsing,compiler-construction,grammar,Algorithm,Parsing,Compiler Construction,Grammar,LR、SLR和LALR解析器之间的实际区别是什么?我知道SLR和LALR是LR解析器的类型,但就它们的解析表而言,实际的区别是什么 如何显示语法是LR、SLR还是LALR?对于LL语法,我们只需要证明解析表的任何单元格都不应该包含多个产生式规则。LALR、SLR和LR有类似的规则吗 例如,我们如何显示语法 S --> Aa | bAc | dc | bda A --> d 是LALR(1)而不是SLR(1) 编辑(ybungalobill):对于LALR和LR之间的区别,我没有得

LR、SLR和LALR解析器之间的实际区别是什么?我知道SLR和LALR是LR解析器的类型,但就它们的解析表而言,实际的区别是什么

如何显示语法是LR、SLR还是LALR?对于LL语法,我们只需要证明解析表的任何单元格都不应该包含多个产生式规则。LALR、SLR和LR有类似的规则吗

例如,我们如何显示语法

S --> Aa | bAc | dc | bda
A --> d
是LALR(1)而不是SLR(1)



编辑(ybungalobill):对于LALR和LR之间的区别,我没有得到令人满意的答案。因此,LALR的表较小,但它只能识别LR语法的子集。有人能详细说明一下LALR和LR的区别吗?LALR(1)和LR(1)足以回答问题。它们都使用1个令牌前瞻,并且都是表驱动的!它们有什么不同?

SLR、LALR和LR解析器都可以使用完全相同的表驱动机器来实现

从根本上说,解析算法收集下一个输入标记T,并参考当前状态S(以及相关的先行、转到和缩减表)以决定要执行的操作:

  • SHIFT:如果当前表表示在令牌T上进行SHIFT,则该对(S,T)被推送到解析堆栈上,状态根据GOTO表对当前令牌(例如GOTO(T))的说明进行更改,提取另一个输入令牌T’,并重复该过程
  • 减少:每个状态都有0、1或许多可能在该状态中发生的减少。如果解析器是LR或LALR,则将对照前瞻集检查令牌,以获取状态的所有有效缩减。如果令牌与语法规则G=R1 R2.的缩减的先行集匹配。。Rn,发生堆栈缩减和移位:调用G的语义动作,堆栈弹出n次(从Rn开始),将对(S,G)推到堆栈上,新状态S'设置为GOTO(G),循环使用相同的标记T重复。如果解析器是SLR解析器,对于该状态,最多有一个约简规则,因此可以盲目地执行约简操作,而无需搜索以查看哪个约简适用。对于SLR解析器来说,了解是否存在缩减是很有用的;这很容易判断每个州是否明确记录了与之相关的减少数量,而且实际上L(AL)R版本也需要该计数
  • 错误:如果移位和减少都不可能,则声明语法错误
那么,如果他们都使用相同的机器,那又有什么意义呢

单反的价值在于其实现的简单性;您不必扫描可能的预处理集,因为最多有一个预处理集,并且这是唯一可行的操作,前提是状态中没有换档退出。哪种简化适用于特定的状态,因此SLR解析机器不必搜索它。在实践中,L(AL)R解析器处理大量有用的语言,而且实现起来几乎没有额外的工作,因此除了作为学术练习之外,没有人实现SLR

LALR和LR之间的差异与表格生成器有关。LR解析器生成器跟踪特定状态的所有可能缩减及其精确的前瞻集;最终的状态是,每个缩减都与其左上下文中的精确前瞻集相关联。这往往会建立相当大的状态集。如果用于归约的GOTO表和lookhead集兼容且不冲突,LALR解析器生成器愿意组合状态;这会产生相当少的状态数,代价是无法识别LR可以识别的某些符号序列。因此,LR解析器可以解析比LALR解析器更大的语言集,但解析器表要大得多。在实践中,可以找到与目标语言足够接近的LALR语法,状态机的大小值得优化;LR解析器更好的地方是通过解析器外部的特别检查来处理的

所以:这三种机器都使用相同的机器。单反是“容易”的,因为你们可以忽略一点点机械,但它不值得麻烦。LR解析更广泛的语言集,但状态表往往相当大。这使得LALR成为实际的选择

话虽如此,但值得一提的是,它可以解析任何上下文无关的语言,使用更复杂的机器,但完全相同的表(包括LALR使用的较小版本)。这意味着GLR严格来说比LR、LALR和SLR更强大;如果你能编写一个标准的BNF语法,GLR将根据它进行解析。这种机制的不同之处在于,当GOTO表和or先行集之间存在冲突时,GLR愿意尝试多次解析。(GLR如何有效地做到这一点纯粹是天才[不是我的],但不适合这个职位)

这对我来说是一个非常有用的事实。我建立程序分析器和代码转换器和解析器是必要的,但“无趣”;有趣的工作是如何处理解析后的结果,因此重点放在解析后的工作上。使用GLR意味着我可以相对容易地构建工作语法,而不是通过破解语法进入LALR可用形式。当你试图处理非学术语言如C++或FORTRAN时,这一点很重要,你需要成千上万的规则来处理整个语言,你不想花时间去尝试语法规则来满足LALR(甚至LR)的限制。

作为一个著名的例子,C++被认为是非常难解析的。通过做LALR分析的人。使用GRR机器解析C++的方法非常简单,使用了后面提供的规则。

S → L = R | R
L → * R | id
R → L
S → L•= R
R → L•
S → b d•a / $
A → d• / c