一般方法
对于输入序列,进行左推导,得到一个合法句子或者非法结构,是一种试探+回溯的方法,自上而下建立输入序列的分析树。
存在的问题
- 公共左因子,造成大量回溯。
- 左递归,造成死循环。
解决
- 消除直接左递归。
方法:首先,整理A产生式为如下形式:
A→ Aα1|Aα2|...|Aαm|β1|β2|...|βn
其中αi非空,βj均不以A开始。用下述产生式代替A产生式
A → β1 A' |β2 A' | ...|βn A'
A'→ α1 A' | α2 A' | ... | αm A' |ε
若αi为空,则形成一个有环的A产生式
- 消除左递归。
核心思想:将不是直接左递归的符号右部展开到其他产生式
关键步骤:合理排序非终结符:A1,A2,...,An;
用Aj→δ1|δ2|...|δk右部替换Ai→Ajγ中的Aj,得到Ai→δ1γ|δ2γ|...|δkγ;
消除Ai产生式中的直接左递归;
- 提取左因子(类似于有限自动机的确定化)
方法 重复过程,直到所有A产生式候选项中不再有公共前缀:
重排A产生式:A→αβ1|αβ2| ...�|αβn|γ;
并用 A→αA'|γ 和 A'→β1|β2| ...|βn取代原A产生式。
注意:既有左递归,又含左因子,先消除左递归(左递归可以看作左因子的一部分)。
递归下降分析法
限制:文法不能有左递归和公共左因子,必须先消除。
方法
- 构造文法状态图并化简
- 将转换图转化为EBNF表示。
- 从EBNF构造子程序。
具体操作
- 构造状态转换图并化简
- 为每个非终结符A建立对应的状态转换图,也就是初态到终态的路径。
- 化简原则
- 标记为A的边课等价为标记ε的边转向A转换图的初态;
- 可以合并:ε连接的两个状态(FA的确定化思想),标记相同的路径,不可区分的状态(DFA的最小化)
- 文法的拓展BNF(EBNF)表示
- {}:重复任意次数。
- []:可选择
- |:或关系
- ():用于改变优先级。
- 构造递归下降子程序
每一行是一个完整的执行语句。- 循环,包含{}的程序
语句:E → T { ( + | - ) T } procedure E is begin T; while lookahead∈(+|-) loop match(lookahead); T; end loop; end E;
- 多类匹配,包含或的程序。
语句:F → ( E ) | id | num procedure F is begin case lookahead is '(' : match('('); E; match(')'); id : match(id); num : match(num); others : error("syntax error2"); end case; end F;
预测分析法
核心:预测分析表+驱动器(模拟算法),预测分析表的构建。
LL,符号栈,输入记号流。
方法
- 如果已知当前栈顶是非终结符,下一输入终结符,预测分析表指示了下一步动作。
- 从初始状态到分析成功或者出错。一个状态(PPT中写作格局)是三元组(栈内容,剩余输入,改变格局的动作)。
改变格局的动作- 匹配终结符,则前往下一个。
- 展开非终结符,逆序放入符号栈。
- 成功:栈顶和剩余输入都是#。
- 出错:调用错误恢复例程。
- 驱动器算法(非递归的预测分析)
- 用预测分析器分析句子(及一个三元组(栈,剩余输入,动作)的顺序表示。
关键:构造预测分析表。
- 构造fIRST集合与FOLLOW集合,对于每个非终结符而言。
- 根据两个集合构造预测分析表。
文法符号序列α的FIRST集合为:
FIRST(α)={ a |α=*>a...,a∈T},若α=*>ε,则ε∈FIRST(α)
非终结符A的FOLLOW集合如下:
FOLLOW(A) = { a |S=*>...Aa...,a∈T}, 若A是某句型的最右符号,则#∈FOLLOW(A)。
通俗理解:FIRST(e)集合就是从e开始可导出的文法序列的开头终结符。Follow(e)集合就是从开始符号可导出的所有含e的文法序列中e之后的终结符。
求这两个集合的算法,需要来理解,first往后多步查看,follow复杂一点。
FIRST集合自下而上计算,FOLLOW集合自上而下计算。
方法 应用下述规则:
1. 加入#到FOLLOW(S),其中S是开始符号,#是输入结束标记
2. 若有产生式A→αBβ,则除ε外,FIRST(β)的全体加入到FOLLOW(B)。
3. 若有产生式A→αB或A→αBβ而ε∈FIRST(β),则FOLLOW(A)的全体加入到FOLLOW(B)。
对3的理解:因为 ε∈FIRST(β),B成为A产生式最右的文法符号,
所以对任何a∈FOLLOW(A),均有a∈FOLLOW(B),
反之不然,因为FIRST(β)不一定只有 ε。
构造预测分析表。
1. 对FIRST(α)的每个终结符a,加入α到M[A,a];
2. 若ε∈FIRST(α),则FOLLOW(A)每个终结符b(包括#),加入α到M[A,b];