LR分析法也是一种“移进—归约”的自底向上语法分析方法,其本质是规范归约,具有以下特点:
(1)应用面广:能够用LR分析程序识别绝大多数的程序设计语言的语法结构;
(2)实现效率高:虽构造方法复杂,但是实现(执行)效率高。
(3)查错准确:LR分析器能够及时发现语法错误并准确指出错误位置。
LR(k)分析方法中L是指自左(Left)向右扫描输入单词串,R指分析过程是最右(Right)推导的逆过程(规范归约),k是指在决定当前分析动作时需向前察看的输入符号个数。
LR(0): 构造简单,适用文法少。是SLR(1)、LR(K)
的基础。
SLR(1): 是针对LR(0)的一些问题进行改进,简单的
LR(1)方法。
LR(K): 分析能力强,构造复杂。
一、LR分析器的逻辑结构:
1.整体结构:
(1)在总控程序的控制下,从左到右扫描输入串,根据分析栈和输入符号的情况,查分析表确定分析动作;
(2) 分析表是LR分析器的核心,根据文法构造,它包括动作表(Action)和状态转换表(Goto)两部分,总控程序根据分析表确定分析动作;
(3) 分析栈包括文法符号栈X[i]和相应的状态栈S[i]两部分,LR分析器通过判断栈顶元素和当前输入符号查分析表确定下步分析动作。
规范归约的关键是寻找句柄,LR法是根据已“移进”、“归约”的符号串及即将读入的符号串进行分析,以确定是否有句柄可归约。
状态:是对迄今为止的整个分析过程的记录以及对
即将扫描的输入串的展望(预测)。
例:S0状态(开始态)表示当前栈中仅有“#”,且即
将输入的符号为句首符号。
SN状态(接受态)表示当前栈中已归约为开始
符号,且即将输入的符号应为“#”。
状态是根据分析表得到的,分析表是由文法构造的。
2.分析表的组成:
二、LR分析过程:
1. 将初始状态S0和输入串的左边界(#)分别进栈;
2. 根据栈顶状态Si和当前输入符号a查动作表进行如下工作:
A β进行归约,若| β |=n,说明符号栈栈顶的n个符号为句柄,所以符号栈栈顶n个符号出栈,A进符号栈 ;同时,状态栈顶的n个元素也出栈,此时状态栈顶为Sk,则查Goto [Sk,A]得到新的状态Sl进状态栈;
三.LR(0)分析表的构造
事实上:LR分析过程中,任意时刻均应保证栈中符号串是规范句型的活前缀,即:栈中绝无句柄之后的任何符号。若输入串为一合法的“句子”,则栈中符号与剩余输入串就构成一个规范句型。
因此识别、产生规范句型的活前缀就是LR分析器的工作过程。为此,我们需要构造可识别文法所有活前缀的有限自动机。
为构造识别文法所有活前缀的有限自动机,现定义构成有限自动机中状态的“项目”
(二) 项目
1.定义:对于文法G,其产生式右部添加一个特殊的符号“.”,就构成文法的一个LR(0)项目,简称项目。
(三)构造识别活前缀的NFA
根据项目的定义,我们可给出文法中所有产生式的项目,而每个项目都为识别活前缀的NFA的一个状态。即文法有多少个项目,它所对应识别活前缀的NFA就有多少个状态。
1.NFA的构造方法
(1)状态集:由每个项目所对应的状态组成的集合;
(2)输入字符集合:由文法符号组成,包括:
终结符、非终结符和e;
(3)初态:对于文法G[S]的拓广文法G[S’],有项目S’® . S ,由于S’ 仅在第一个产生式的左部出现,所以规定它为初态;
(4)终态:每个状态均为NFA的终态(活前缀的识别态)。