第四章:语法分析 1
4.1 自顶向下分析概述
4.1.1 自顶向下的分析(Top-Down Parsing)
- 从分析树的顶部向底部方向构造分析树
- 可以看成是文法的开始符合 推出词串 的过程
例如文法:
输入
分析树:
推导过程:
每一步推导中,都需要做两个选择:
- 替换当前句型中的哪个非终结符
- 用该非终结符的哪个候选式进行替换
4.1.2 最左推导(Left-most Derivation)
在最左推导中,总是选择每个句型的最左非终结符进行替换。
如上面的例子,推导过程:
与最左推导相对的过程是最右归约,最右归约是最左推导的逆过程。
如果 ,则称 是当前文法的 最左句型(Left-Sentential Form)。
4.1.3 最右推导(Right-Most Derivation)
在最右推导中,总是选择每个句型的最右非终结符进行替换。
同样地,最左归约是最右推导的逆过程。
注意:在自底向上的分析中,总是采用最左归约的方式,因此把最左归约称为规范归约,而最右推导相应地称为规范推导。
最左推导和最右推导的唯一性:最左推导和最右推导总是唯一的。
自顶向下的语法分析采用最左推导方式:
- 总是选择每个句型的最左非终结符进行替换
- 根据输入流中的下一个终结符,选择最左非终结符的一个候选式
输入
- 文法开始,使用
(1)
得到 - 使用
(3)
替换 ,得到 - 使用
(5)
替换 ,得到 - 使用
(4)
替换 ,得到 - 使用
(2)
替换 ,得到 - 使用
(3)
替换 ,得到 - 使用
(5)
替换 ,得到 - 使用
(4)
替换 ,得到 - 使用
(5)
替换 ,得到 - 使用
(4)
替换 ,得到 - 使用
(2)
替换 ,得到
即得到 。
4.1.4 递归下降分析(Recursive-Descent Parsing)
- 由一组过程组成,每个过程对应一个非终结符
- 从文法开始符号 对应的过程开始,其中递归调用文法中其它非终结符对应的过程。如果 对应的过程体恰好扫描了整个输入串,则成功完成语法分析
注意
此算法可能需要回溯(Backtracking),导致效率较低。需要回溯的算法是不确定的。
算法如下:
【算法】
4.1.5 预测分析(Predictive Parsing)
预测分析是递归下降分析技术的一个特例,通过在输入中向前看固定个数(通常是一个)符号来选择正确的 产生式。
可以对某些文法构造出向前看 个输入符号的预测分析器,该类文法有时也称为 文法类。
预测分析不需要回溯,是一种确定的自顶向下分析方法。
4.2 文法转换
4.2.1 递归的产生
给定文法
输入 ,选择候选式时不确定是哪一个,将产生回溯。
同一个非终结符的多个侯选式存在共同前缀,将导致回溯现象。
另外一个例子:
输入 ,由于侯选式没有与 对于的侯选式,首先尝试 ,然后继续尝试第一个式子,产生单程递归。
含义 的产生式的文法称为是 直接左递归(Immediate Left Recursive)的。
如果一个文法中有一个非终结符 使得对某个串 存在一个推导 那么这个文法就是 左递归 的。
经过两步或两步以上推导产生的左递归称为是 间接左递归 的。
左递归文法会使递归下降分析器陷入无限循环。
4.2.2 消除直接左递归
那么上面的产生式可以替换为正则表达式 。
那么
事实上,这种消除过程就是把左递归转换成了右递归。
例如
第一个式子中,消除左递归后
4.2.3 消除直接左递归的一般形式
可以得出
消除左递归是要付出代价的 —— 引进了一些非终结符和 产生式。
4.2.4 消除间接左递归
推导
可以使用代入的方法消除 ,然后消除直接左递归。
4.2.5 消除左递归算法
输入不含循环推导(如 )和 产生式的文法 ,输出等价的无左递归文法。
【算法】
4.2.6 提取左公因子(Left Factoring)
通过改写产生式来推迟决定,等读入了足够多的输入,获得足够信息后再做出正确的选择。
【输入】文法 ,输出等价的提取了左公因子的文法
【算法】
对于每个非终结符 ,找出它的两个或多个选项之间的最长公共前缀 。如果 ,即存在一个 非平凡的(Nontrivial)公共前缀,那么将所有 产生式
替换为
其中, 表示所有不以 开头的产生式体。
是一个新的非终结符。不断应用这个转换,直到每个非终结符的任意两个产生式体都没有公共前缀为止。
4.3 文法
4.3.1 预测分析法的工作过程
从文法开始符号出发,在每一步推导过程中根据当前句型的最左非终结符 和当前输入符号 ,选择正确的 产生式。为保证分析的确定性,选出的候选式必须是唯一的。
4.3.2 S_文法
S_文法(简单的确定性文法,Korenjak & Hopcroft,1966):
- 每个产生式的右部都以终结符开始
- 同一非终结符的各个候选式的首终结符都不同
根据定义,S_文法不含 产生式。
例如文法:
输入 ,推导
如果输入 ,推导
这个例子无法推导出,那么什么时候使用 产生式?
如果当前某非终结符 与当前输入符 不匹配时,若存在 ,可以通过检查 是否可以出现在 的后面,来决定是否使用产生式 (若文法中无 ,则应报错)。
4.3.3 非终结符的后继符号集
非终结符 的后继符号集是可能在某个句型中紧跟在 后边的终结符 的集合,记为 :
如果 是某个句型的的最右符号,则将结束符 '$'
添加到 中。
例如:
那么 。
4.3.4 产生式的可选集
产生式 的可选集是指可以选用该产生式进行推导时对应的输入符号的集合,记为
4.3.5 q_文法
- 每个产生式的右部或为 ,或以终结符开始
- 具有相同左部的产生式有 不相交的可选集
那么,q_文法不含右部以非终结符打头的产生式。
4.3.6 串首终结符集
串首终结符:串首第一个符号,并且是终结符,简称 首终结符。
给定一个文法符号串 , 的串首终结符集 被定义为可以从 推导出的所有串首终结符构成的集合。
如果 ,那么 也在 中:
- 对于
- 对于 ,那么
产生式 的可选集 :
- 如果 ,那么
- 如果 ,那么
4.3.7 文法
文法 是 的,当且仅当 的任意两个具有相同左部的产生式 满足下面的条件:
- 如果 和 均不能推导出 ,则
- 和 至多有一个能推导出
- 如果 ,则
- 如果 ,则
那么,同一非终结符的各个产生式的可选集互不相交。
4.3.8 为 文法构造预测分析器
的含义:
- 第一个
L
表示从左向右扫描输入 - 第二个
L
表示产生最左推导 1
表示在每一步中只需要向前看一个输入符号来决定语法分析动作