640 likes | 822 Views
编译原理第五章. 自顶向下语法分析方法. 语法分析的作用: 识别由词法分析给出的单词符号序列是 否是给定文法的正确句子(程序) 目前语法分析常用的方法 有 自顶向下分析和自底向上分析 。 而自底向上分析又可分为算符优先分析和 LR 分析。 自顶向下分析也称面向目标的分析方法,也就是从文法的 开始符号出发,企图推导出与输入的单词串完全相匹配的 句子,若输入串是给定文法的句子,则必能推出,反之, 必然出错。 自顶向下分析又可分为确定的和不确定的两种。. 5.1 确定的自顶向下分析思想. 确定的自顶向下分析方法,首先要解决从文法的开始符号
E N D
编译原理第五章 自顶向下语法分析方法
语法分析的作用:识别由词法分析给出的单词符号序列是语法分析的作用:识别由词法分析给出的单词符号序列是 否是给定文法的正确句子(程序) 目前语法分析常用的方法有自顶向下分析和自底向上分析。 而自底向上分析又可分为算符优先分析和LR分析。 自顶向下分析也称面向目标的分析方法,也就是从文法的 开始符号出发,企图推导出与输入的单词串完全相匹配的 句子,若输入串是给定文法的句子,则必能推出,反之, 必然出错。 自顶向下分析又可分为确定的和不确定的两种。
5.1 确定的自顶向下分析思想 确定的自顶向下分析方法,首先要解决从文法的开始符号 出发,如何根据当前的输入符号(单词符号)唯一地确定 选用哪个产生式替换相应非终结符往下推导,或构造一棵 相应的语法树。
例5.1 若有文法G1[S] SpA|qB AcAd|a BdB|b 对于输入 串W=pccadd,自顶向下的推导过程为: S=>pA =>pcAd =>pccAdd =>pccadd,相应的语法树如下: S S S S p A p A p A A p d d c A d c A c A d d c A c A a
文法的特点: (1)每个产生式的右部都由终结符号开始。 (2)如果两个产生式有相同的左部,那么它们 的右部由不同的终结符开始。
例5.2 若有文法G2[S]为: SAp SBq Aa AcA Bb BdB 对于输入串W=ccap,其推导过程为: S=>Ap =>cAp =>ccAp =>ccap 对应的语法树为: S S S S A p A p A p A p c A c A c A c A c A a
例5.2文法的特点: (1)产生式右部不全是由终结符开始。 (2)如果两个产生式有相同的左部,它们的右部 是由不同的终结符或非终结符开始。 (3)文法中无空产生式。
定义5.1 设文法G是上下文无关文法 FIRST(α)={a| α=*> aβ,a∈VT*,α,β ∈V*} 若α=*>ε,则规定ε ∈FIRST( α) 对于文法G2 有 文法G2[S]为: SAp SBq Aa AcA Bb BdB FIRST(Ap)={a,c} FIRST(Bq)={b,d}
例5.3 若有文法G[S] SaA Sd AbAS Aε 若输入串w=abd 其推导过程为: S=>aA =>abAS =>abS =>abd S S S S a A a A a A a A A S b A S A S b b ε d ε
当某一非终结符的产生式中含有空产生式时,它的非空当某一非终结符的产生式中含有空产生式时,它的非空 产生式的右部首符号集两两不相交,并与在推导过程中紧 跟该非终结符右边可能出现的终结符集也不相交,则仍可 构造确定的自顶向下分析。
定义5.2 设文法G是上下文无关文法,A∈VN,S是开始符号 FOLLOW(A)={a|S=*>μAβ,且a∈VT,a ∈FIRST(β), μ ∈VT*, β ∈V+} 若S=*> μAβ,且β=*>ε则# ∈FOLLOW(A)。 若有S=*> …A,则规定# ∈FOLLOW(A)
定义 5.3 给定上下文无关文法产生式Aα,A∈VN, α ∈V*,若α≠*>ε,则 SELECT( Aα)=FIRST( α) 如果α=*>ε,则 SELECT( Aα)=(FIRST( α)-{ε})∪FOLLOW(A)
定义5.4 一个上下文无关文法是LL(1)文法的充要条件是: 对于每个非终结符A的两个不同产生式Aα,Aβ,满足: SELECT( Aα)∩ SELECT( A β)=Ø 其中α、β不同时能=*>ε LL(1)文法的含义:第一个L表明自顶向下分析是从左到右 扫描字符串,第二个L表明分析过程中将用最左推导,1表 明只需向右看一个符号,便可决定如何推导,即选择哪个产 生式(规则)进行推导。
例5.3 的文法G[S] SaA Sd AbAS Aε 有: SELECT( SaA)={a} SELECT(Sd)={d} SELECT(AbAS)={b} SELECT(Aε)={a,d,#} 所以: SELECT( SaA)∩ SELECT(Sd)=Ø SELECT(AbAS) ∩SELECT(Aε)={a,d,#} =Ø 因此它是一个LL(1)文法。
例5.4 设文法G[S]为: SaAS Sb AbA Aε 则: SELECT( SaAS)={a} SELECT(Sb) ={b} SELECT(AbA)={b} SELECT(Aε)={a,b} 所以: SELECT( SaAS) ∩SELECT(Sb)=Ø SELECT(AbA) ∩ SELECT(Aε) ≠Ø 因此,它不是LL(1)文法.
5.2 LL(1)文法的判断 • 通过求FIRST、FOLLOW、SELECT集合进行判断。
例5.5 若文法G[S]为: SAB SbC Aε Ab B ε BaD CAD Cb DaS Dc
1、求出能导出ε的非终结符 (1)将数组X[ ]中对应每一非终结符的标记置初值为“未定” (2)扫描文中的产生式 (a)删除所有右部含有终结符的产生式,若这使得以 某一非终结符为左部的所有产生式都被删除,则将数组中对 应该非终结符的标记值改为“否”,说明该非终结符不能推出ε。 (b)若某一非终结符的某一产生式右部为ε,则将数组 中对终结符的标志置为“是”,并从文法中删除该非终结符的所 有产生式。 (3)扫描产生式右部的每一符号 (a)若所扫描到的非终结符号在数组中对应的标志是 “是”,则删去该非终结符,若这使产生式右部为空,则对产 生式左部的非终结符在数组中对应的标志改为“是”,并删除该 非终结符为左部的所有产生式。
(b)若所扫描到的非终结符号在数组中对应的标志是(b)若所扫描到的非终结符号在数组中对应的标志是 “否”,则删除该产生式,若这使产生式左部非终结符的有关产 生式都被删除,则把数组中该非终结符对应的标志改为“否”。 (4)重复(3),直到扫描完一遍文法的产生式,数组中 非终结符对应的特征再没有改变为止。
2、计算FIRST集 (1)根据定义计算 定义: 定义5.1 设文法G是上下文无关文法 FIRST(α)={a| α=*> β,a∈VT*,α,β ∈V*} 若α=*>ε,则规定ε ∈FIRST( α)
对于每一文法符号X∈V,计算FIRST(X) • 若X ∈VT,则FIRST(X)={X} • 若X ∈VN,且有产生式Xa...,a ∈ VT则a ∈ FIRST(X) • 若X ∈VN ,Xε,则ε ∈ FIRST(X) • 若X ∈VN ,Y1,Y2...Yi都∈VN,而有产生式 • XY1Y2...Yn。当Y1,Y2...Yi-1都=*>ε时,(其中1≤i≤n), • 则FIRST(Y1)-{ε},... FIRST(Yi-1)-{ε}, FIRST(Yi)都 • 包含在FIRST(X)中。 • (e) 当(d)中所有Y1 ε,则 • FIRST(X)=FIRST(Y1)∪ FIRST(Y2)... ∪ FIRST(Yn) ∪ {ε} • 反复使用(b)~(e),直到每个符号的FIRST集合不再增大为止。
对于符号串求FIRST集合 若符号串α∈V*, α=X1X2...Xn 当X1不能=*>ε,则置FIRST( α)=FIRST(X1) 若对任何j (1≤j≤i-1,2 ≤i ≤n), ε ∈FIRST(Xj) 则FIRST( α)=∪(FIRST(Xj)-{ε }) ∪FIRST(Xj)
例5.5 若文法G[S]为: SAB SbC Aε Ab B ε BaD CAD Cb DaS Dc FIRST(S)={FIRST(A)- {ε }} ∪ {FIRST(B)- {ε }} ∪ {ε } ∪{b} ={b,a, ε } FIRST(A)= {ε } ∪{b}= {b, ε } FIRST(B)= {ε } ∪{a}= {a, ε } FIRST(C)={FIRST(A)- {ε } } ∪ FIRST(D) ∪FIRST(b)={b,a,c} FIRST(D)={a} ∪{c}={a,c} 每个产生式的右部符号串开始符号集合为: FIRST(AB)={a,b, ε} FIRST(bC)={b} FIRST(ε)={ε} FIRST(b)={b} FIRST(aD)=a
FIRST(AD)={a,b,c} FIRST(b)={b} FIRST(aS)={a} FIRST(c)={c}
(2)由关系图法求文法符号的FIRST集 • 每个文法符号对应图中一个结点,对应终结符的结点时, • 用符号本身标记,对应非终结符的结点用FIRST(A)标记。 • (b)如果文法中有产生式AαXβ,且α=*>ε,则对应A的结点到 • 对应X的结点连一条弧线。 • (c) 凡是从FIRST(A)结点有路径可达的终结符结点所标记 • 的终结符都为FIRST(A)的成员。 • (d) 由判别步骤1确定ε是否为某终结符FIRST集的成员,若是, • 则将ε加入该非终结符的FIRST集。
例5.5 若文法G[S]为: SAB SbC Aε Ab B ε BaD CAD Cb DaS Dc FIRST(C) b FIRST(A) FIRST(S) FIRST(B) FIRST(D) a c
由关系图可以算出 FIRST(S)={b,a,ε} FIRST(A)={b ,ε} FIRST(B)={a, ε} FIRST(C)={a,b,c} FIRST(D)={a,c}
3、计算FOLLOW集 • (1)根据定义计算 • 对文法中每一A∈VN计算FOLLOW(A) • 设S为文法中开始符号,把{#}加入FOLLOW(S)中 • 若AαBβ是一个产生式,则把FIRST( β)的非空元素 • 加入FOLLOW(B)中。如果β=*>ε,则把FOLLOW(A) • 也加入FOLLOW(B)中。 • (c) 反复使用(b),直到每个非终结符的FOLLOW集不再 • 增大为止。
例5.5 若文法G[S]为: SAB SbC Aε Ab B ε BaD CAD Cb DaS Dc FOLLOW(S)={#} ∪FOLLOW(D) FOLLOW(A)=(FIRST(B)-{ε}) ∪FOLLOW(S) ∪FIRST(D) FOLLOW(B)=FOLLOW(S) FOLLOW(C)=FOLLOW(S) FOLLOW(D)=FOLLOW(B) ∪FOLLOW(C)
(2)用关系图法求非终结符的FOLLOW集 • 文法G中的每个符号和“#”对应图中的一个结点,对应终结 • 符和“#”的结符号本身标记。对应非终结符的结点则用 • FOLLOW(A)或FIRST(A)标记。 • (b) 从开始符号S的FOLLOW(S)结到“#”号的结点连一条弧线。 • (c) 如果文法中有产生式AαBβX,且β=*>ε,则从FOLLOW(B) • 结点到FIRST(X)结点连一条弧,当X∈VT时,则与X相连。 • (d) 如果文法有产生式A αBβ,且β=*>ε,则从FOLLOW(B) • 结点到FOLLOW(A)结点连一条弧线。 • (e) 对每一FIRST(A)结点,如果有产生式A αXβ,且α=*>ε, • 则从FIRST(A)到FIRST(X)连一条弧线。 • (f) 凡是从FOLLOW(A)结点有路径可达的终结符或“#”号的 • 结点,其所标记的终结符或“#”号即为FOLLOW(A)的成员。
# FOLLOW(B) FOLLOW(S) FOLLOW(D) FOLLOW(A) FIRST(B) FOLLOW(C) FIRST(D) c a
计算结果: FOLLOW(S)={#} FOLLOW(A)={a,c,#} FOLLOW(B)={#} FOLLOW(C)={#} FOLLOW(D)={#}
4、计算SELECT集 (按定义计算) SELECT(SAB)=FIRST(AB)- {ε }∪FOLLOW(S)={b,a,#} SELECT(SbC)=FIRST(bC)={b} SELECT(Aε)=FIRST(ε) - {ε }∪FOLLOW(A)={a,c,#} SELECT(Ab)=FIRST(b)={b} SELECT(B ε)= FIRST(ε) - {ε }∪FOLLOW(B)={#} SELECT(BaD)=FIRST(aD)={a} SELECT(CAD)=FIRST(AD)={a,b,c} SELECT(Cb)=FIRST(b)={b} SELECT(DaS)=FIRST(aS)={a} SELECT(Dc)=FIRST(c)={c}
从而有: SELECT(SAB) ∩SELECT(SbC) ≠Ø SELECT(Aε) ∩SELECT(Ab) =Ø SELECT(B ε) ∩SELECT(BaD) =Ø SELECT(CAD) ∩SELECT(Cb) ≠Ø SELECT(DaS) ∩SELECT(Dc) =Ø 所以该文法不是LL(1)文法。
5.3 某些非LL(1)文法到LL(1)文法的等价变化 若文法中含有直接或间接左递归,或含有左公共因子, 则该文法肯定不是LL(1)文法。 等价变换过程实际上就是设法消除文法中的左递归,提取 左公共因子。
1、提取左公共因子 对于文法中含有形如:Aαβ|αγ的产生式,会使得FIRST集 相交,即有SELECT( Aαβ)∩ SELECT( Aα γ)≠Ø 则将Aαβ|αγ变为: A α (β|γ) 即有:A α A’ A’ β|γ 写成一般形式: Aαβ1| αβ2...| αβn 变为A α(β1| β2...| βn) 即有: A αA’ A’ β1| β2...| βn
例5.6 若文法G1的产生式为: (1)SaSb (2)SaS (3)Sε 对(1)(2)式: SaS(b| ε) 变为: SaSA Ab A ε S ε
例5.7 对文法G2的产生式: (1) Aad (2)ABc (3)BaA (4)BbB 产生式(2)右部以非终结符开始,可能导致公共因子。 用(3)(4)替换(2)得到: (1)Aad (2)AaAc (3)AbBc (4)BaA (5)BbB
提取(1)(2)左公因子 Aa(d|Ac) 引进A‘ AaA’ A’d|Ac 最后: AaA’ AbBc A’d A’Ac BaA BbB
例5.8 若有文法G3的产生式 • SaSd • SAc • AaS • Ab • 用(3)(4)替换(2) • (1)SaSd • (2)SaSc • (3)Sbc • (4)AaS • (5)Ab
引入A‘ (1)SaSA’ (2)Sbc (3)A’d|c (4)AaS (5)Ab
例5.9 若文法G4的产生式为: (1)SAp|Bq (2)AaAp|d (3)BaBq|e 用(2)(3)替换(1)得到 (1)SaApp|aBqq (2)Sdp|eq (3)AaAP|d (4)BaBq|e 对(1)提取左公因子得到: Sa(App|Bqq) 引入S‘最后: (1)SaS’ (2)Sdp|eq (3)S’App|Bqq (4)AaAp|d (5)BaBq|e
结论: (1)不一定每个文法的左公因子都能在有限的步骤内替换 成无左公因子的文法。 (2)一个文法提取了左公因子后,只解决了相同左部产生式 右部的FIRST集不相交问题,当改写后的文法不含空产生式, 且无左递归时,则改写后的文法是LL(1)文法,否则还需 用LL(1)文法的判断方式进行判断,才能确定是否为 LL(1)文法。
2、消除左递归 对于三个产生式: AAβ AB β BAα 会有A=+>A...,它称为文法中含有左递归,或间接左递归。
例5.10 文法G5 SSa Sb 其语法分析树如右: S S a S a ... S a
例5.11 文法G6: (1)AaB (2)ABb (3)BAc (4)Bd 对于输入串adbcbcbc# 其语法分析树为: A a B A c B b d
如果选用(3)式推导,则不能终止 A a B A c B b A c ...
消除左递归方法: (a)消除直接左递归,把直接左递归改写为右递归 对于SSa Sb 可改写为: SbS’ S’aS’|ε 一般情况下: 对于AAα1| Aα2|... Aαn|β1 |β2 |...βn 改写为: A β1 A‘| β2 A’|... βnA‘ A’ α1 A’| α2A’|... |αnA’|ε
(b)消除间接左递归 先将间接左递归变为直接左递归,再进行删除。 例子:文法G6 (1)AaB (2)ABb (3)BAc (4)Bd 用(1)(2)代入(3)得到 (1)BaBc (2)BBbc (3)Bd 消除左递归后得到: B(aBc|d)B’ B’bcB’|ε 再把原产生式代入,得到: (1)AaB (2)ABb (3)B(aBc|d)B’ (4)B’bcB’|ε
(c)消除文法中一切左递归的算法 (1)把文法的所有非终结符按某一顺序排序; 如A1,A2…An (2)从A1开始消除左部为A1的产生式的直接左递归,然后把左 部为A1的所有规则的右部逐个替换左部为A2右部以A1开始的 产生式中的A1,并消除左部为A2的产生式中的直接左递归。 (3)去掉无用产生式。