在计算机科学中,LALR分析器是一种规范LR分析方法(英语:Canonical_LR_parser)的简化形式。它可以对上下无关文法进行语法分析。LALR即“Look-Ahead LR”。其中,Look-Ahead为“向前看”,L代表对输入进行从左到右的检查,R代表反向构造出最右推导序列。LALR分析器可以根据一种程序设计语言的正式语法的产生式(英语:Production_(computer_science))而对一段文本程序输入进行语法分析,从而在语法层面上判断输入程序是否合法。实际应用中的LALR分析器并不是由人手工写成的,而是由类似于yacc和GNU Bison之类的LALR语法分析器生成工具(英语:LALR_parser_generator)构成。由机器自动生成的代码相比较于程序员手工的代码,拥有更好的运行效率而且减少了程序员的工作量。
1965年,Donald Knuth发明了LR分析器。LR分析器可以在线性时间里分析一个确定的上下文无关文法的输入。但是,最右推导技术所需的分析表需要一个巨大的内存空间,所以在那个内存空间紧缺的年代,LR分析技术被认为是不可行的。为了解决这个缺点,在1969年,Frank DeRemer提出了两种LR分析方法的简化版,即LALR分析器和SLR分析器(英语:Simple_LR_parser)。这两种方法所需的内存空间较LR分析法减少了许多。即使在后来的1977年,LR分析器的空间优化方式被提出,但是其空间效率依然比不过LALR这种简化版本。1979年,Frank DeRemer和Tom Pennello宣布了对于LALR分析器的新的优化方法,这再一次提高了LALR分析器的空间使用效率 。
通常来说,LALR分析器是指LALR(1)分析器。其中(1)代表了向前看一个字符,分析器可以根据这前面的一个字符确定分析时使用的产生式。相类似的,还有向前看两个字符的LALR(2)分析器、甚至向前看k个字符的LALR()分析器,但是实际使用中很少使用这类分析器。LALR分析方法基于LR(0)分析法演化而来,因此对于一个LALR()分析法可以看成LA()LR(0)分析法。实际上考虑到LR分析法,有两种参数存在的LA()LR()分析法族。对于所有的和的组合,都可以由LR(+)分析法导出。但是这种观点没有任何的实际意义。相比较与其他的LR分析器,LALR分析器在一次简单的对输入流进行从左到右扫描时,可以更直接的根据向前看的那个字符确定一个从下至上的分析方法。这些是归功于LALR分析器不需要回溯。作为一个定位于向前看的语法分析器,LALR(1)即为最常用的形式。
由于LALR分析器采用了最右推导而不是采用最左推导,因此,理解LALR分析器的工作方法变得十分困难。而这导致了手动构造一个LALR分析器是一个消耗巨大而且费时的工作。而且当出现语法错误时,LALR分析器可能并不会马上报错,而是执行几次归约动作。无论如何,任意的LR()分析器中,由于要在出错时枚举每一个可能的字符, 让错误恢复这项工作变得十分繁琐。由于这个原因,在一些时候递归下降分析器比LALR分析器更实用。由于其较低的语法分析功能,一个递归下降分析器需要更多的手写代码。但是为一个递归下降分析器编写代码并不像LALR分析器那样的困难,这是因为递归下降分析器使用了最左推导。一个值得注意的例子就是Gnu Compiler Collection中的C和C++语言的语法分析器。其中语法分析器起始是LALR分析器,但是之后却被改写成递归下降分析器。
严格的来说,LALR(1)分析器的功能比LR(1)分析器要弱一些;但是却比SLR(1)分析器强。由LALR引入的对LR的简化在于存在相同核心的项集;但是在LR分析法中,下个字符是未知的。而这种简化导致了LALR的分析功能的下降:不知道下个字符导致了语法分析器不知道选择哪个产生式,从而产生了归约/归约冲突。而SLR(1)分析法采用了更多的合并,导致了相较于LALR(1)更多的额外冲突。下述是一个标准的LR(1)文法,但是并不能由LALR(1)分析器进行分析。
S -> a E c -> a F d -> b F c -> b E dE -> eF -> e