我了解LR和LALR都是自下而上的语法分析算法,但它们之间有什么区别呢?
LR(0)、LALR(1)和LR(1)语法分析有什么差异?我该如何判断一个语法是否为LR(0)、LALR(1)或LR(1)?
我了解LR和LALR都是自下而上的语法分析算法,但它们之间有什么区别呢?
LR(0)、LALR(1)和LR(1)语法分析有什么差异?我该如何判断一个语法是否为LR(0)、LALR(1)或LR(1)?
从高层次来看,LR(0)、LALR(1)和LR(1)之间的区别如下:
LALR(1)解析器是LR(0)解析器的“升级”版本,它跟踪更精确的信息以消除语法歧义。 LR(1)解析器是一个明显更强大的解析器,比LALR(1)解析器跟踪更精确的信息。
LALR(1)解析器比LR(0)解析器大一个常数因子,而LR(1)解析器通常比LALR(1)解析器指数级大。
任何可以使用LR(0)解析器解析的语法都可以使用LALR(1)解析器解析,任何可以使用LALR(1)解析器解析的语法都可以使用LR(1)解析器解析。有些语法是LALR(1)但不是LR(0),有些是LR(1)但不是LALR(1)。
更正式地说,LR(k)解析器是一种自底向上的解析器,通过维护终结符号和非终结符号的堆栈工作。解析器由确定性有限自动机控制,该自动机根据解析器的当前状态和下一个k个输入符号来确定是否将新符号移入堆栈,或通过逆序应用一个产生式来规约堆栈中的顶部符号。
为了跟踪足够的信息以对移入和规约做出决策,LR(k)解析器使每个状态对应于一个“配置集”,该集合由以下信息注释的产生式集合组成:
一个好的 LALR(1) 解析器的解析算法有两个不同之处:(1) 它应该具有移位-规约操作,这将状态数减少约30%并使解析器更快,(2) 当检测到语法错误时,它必须执行一次或多次规约,这使得错误恢复更加复杂。
一个标准 LR(1) 解析器的解析算法 (1) 没有移位-规约操作,(2) 在检测到语法错误时不进行任何规约,这使得错误恢复更简单。
还有另一种情况,称为最小 LR(1),它使用与 LALR(1) 相同的解析算法和错误恢复算法。最小 LR(1) 解析器提供了 LR(1) 的功能,其大小几乎与 LALR(1) 一样小。LRSTAR Parser Generator 为 C++ 程序员创建最小 LR(1) 解析器。