概述
最右(Rightmost)
:指的是在推导中,总是选择扩展最右边的非终结符。这种推导方式产生的是最右推导
反向(Reverse)
: 这指的是在归约
过程中,做的事恰好是最右推导的逆过程
简单来说:LR分析器通过模拟最右推导的逆过程来进行语法分析
例子
使用一个非常简单的文法来描述"括号内包含一个标识符"的概念
S -> (S)
S -> id
目标: 分析输入字符串 ( id )
第1步:构造一个"最右推导"(Rightmost Derivation)
要理解LR 分析器在做什么,首先需要知道一个"正确"的句子是如何通过最右推导产生的
- 从开始符号S开始
- 查看当前字符串,并选择最右边的非终结符进行扩展
- 应用规则: S -> (S)
- 推导序列: S -> (S)
- 现在字符串 (S). 最右边的非终结符是 S
- 应用规则 S -> id
- 推导序列:S -> ( S ) -> ( id )
所以,最右推荐导序列是: S -> ( S ) -> ( id )
LR分析器的"反向"归约(Reverse Reduction)
LR 分析器的工作方式与推导完全相反。它从输入字符串开始,不断地将右侧符号(根据文法规则) 归约 为左侧的非终结符,直到最终归约为开始符号 S
它使用一个栈和一个状态机来跟踪当前的位置。下面模拟一个简化的LR分析过程,重点关注栈的内容的归约工作
输入流
: ( id )
步骤 | 栈内容 (底部 -> 顶部) | 输入流 | 动作解释 |
---|---|---|---|
1 | [ ] | ( id ) | 初始状态,栈为空。 |
2 | [ ( ] | id ) | 移入: 将 ( 从输入流移入栈顶 |
3 | [ (, id ] | ) | 移入: 将 id 移入栈顶 |
4 | [ (, S ] | ) | 归约: 栈顶的 id 匹配了规则 S -> id 的右侧。我们将 id 归约为 S。 (注意:这对应了最右推导的最后一步 ( S ) => ( id ) 的逆过程!) |
5 | [ (, S, ) ] | $ (结束符) | 移入: 将 ) 移入栈顶 |
6 | [ S ] | $ | 归约: 栈顶的 ( S ) 匹配了规则 S -> ( S ) 的右侧。我们将 ( S ) 归约为 S。 (注意:这对应了最右推导的第一步 S => ( S ) 的逆过程!) |
7 | 接受 | 栈顶是开始符号 S,输入流已结束,分析成功 |
关键对比与解释
现在我们把两个过程放在一起看
方向 | 过程 | 步骤序列 |
---|---|---|
正向 | 最右推导 (人类编写句子的思维) | S => ( S ) => ( id ) |
反向 | LR归约 (分析器理解句子的思维) | ( id ) <= ( S ) <= S |
"最右"体现在哪里?
在最右推导 S => ( S ) => ( id ) 中,第二步我们选择扩展的是第二个 S(它是当时最右边的非终结符)
在LR分析器中,我们最先归约的就是这个最后被扩展出来的部分 id
LR分析器总是能找到并归约那个"句柄",而这个"句柄"正是在最右推导中最后被生成的那个子串
"反向"体现在哪里?
LR分析器的归约步骤序列 ( id ) -> ( S ) -> S,恰好是最右推导序列 S -> ( S ) -> ( id ) 的逆序
结论
所以,"R代表反向(Reverse)和最右(Rightmost)" 这句话的含义是:
LR分析器通过构造一个自动机,来识别并逆向遍历输入串所对应的最右推导步骤,从而完成语法分析
- 最右: 定义了分析器所遵循的语法模型(最右推导规范)
- 反向: 定义了分析器的工作方式(从句子归约到开始符号)