450 likes | 685 Views
第 5 章 自顶向下语法分析方法. 5.1 确定的自顶向下分析思想. 语法分析分为:自底向上语法分析 自顶向下语法分析 自顶向下方法 :从文法的初始符出发导出句型。. S. B. A. c. a. b. A. a. 例: G(S): S→ABc A→aB|a B→Ab|b 判别 aabc 是否为文法 G 的句子. S ABc AAbc Aabc aabc. 首符集、后继符集及选择符集 定义 5.1
E N D
第5章 自顶向下语法分析方法
5.1 确定的自顶向下分析思想 语法分析分为:自底向上语法分析 自顶向下语法分析 自顶向下方法:从文法的初始符出发导出句型。
S B A c a b A a 例:G(S): S→ABc A→aB|a B→Ab|b 判别 aabc 是否为文法G的句子 SABc AAbc Aabc aabc
首符集、后继符集及选择符集 定义5.1 first(α)={t|α t…,t∈VT} follow(A)={t|Z …Att∈VT} select(A→)= first(α),当α不可空 first(α)∪follow(A),否则 其中α∈(VN∪VT)*,A∈VN, first(ε)={ },α可空表示α ε。 * * *
例子: 求first(X)其中X→aBc first(X)={a} 求follow(B)其中X→aBc follow(B)={c} 求select(A→aBc)其中X→aBc select(A→aBc)= first(X)={a}
求first(X)的算法:(X∈VN∪VT) • 若X∈VT,则first(X)={X}。 • 若X∈VN,且有产生式X→t…,则把t加入到first(X)中;若X→也是产生式,则把也加入到first(X)中。其中t∈VT。
若有产生式X→Y……,(Y∈VN),则把first(Y)~{ε}中的元素全部加到first(X)中;若X→Y1Y2…Yn是一产生式,同时 Y1,…,Yi-1是非终极符,且对一切j=1,2,…,i-1,都有first (Yj),则把first(Yi)~{ε}的元素全部加到first(X)中;特别是对一切j=1,2,…,n,都有first(Yj)时,要把加first(X)中。
例1:X→ABC A→a B→b C→c 解:ABCaBC,abC,abc,AbC, Abc,aBc,ABc…… first(X)=first(ABC) ={a}
例2:X→ABC A→a| B→b C→c 解:ABCaBC,abC,abc,AbC,Abc, aBc,ABc,bC,bc,BC,Bc…… first(X)=first(ABC)={a,b}
例3:X→ABC A→a| B→b| C→c 解:ABCaBC,abC,abc,AbC,Abc,aBc, ABc,bC,bc,BC,Bc,c,C…… first(X)=first(ABC) ={a,b,c}
例4:X→ABC A→a| B→b| C→c| 解:ABCaBC,abC,abc,AbC,Abc,aBc, ABc,bC,bc,BC,Bc,c,C,ε…… first(X)=first(ABC) ={a,b,c,ε}
例5:X→ABc A→a|b| B→c|d D→d 解:first(X)=first(ABc) =first(A)∪first(B) ={a,b}∪{c,d} ={a,b,c,d}
求first()的算法:(α=X1X2…Xn) • 若n=0,即=ε,则令first()={ε} • 否则,对1≤i≤n,求first(Xi)。 • 若n≥2,且对一切j=1,2,…,i-1都有ε∈first(Xj),则令first(Xi)~{ε} first(),其中2≤i≤n。若对一切j=1,2,…,n都有ε∈first (Xj),则令ε∈first(α)。
例子:X→ABCA→a| B→b| C→c| 解:first(ABC) =first(A)~{ε}∪first(B)~{ε}∪first(C) ={a,b,c,ε}
求follow(B)的算法:(B∈VN) • 对文法初始符S,令#∈follow(S) • 若A→xBy是一个产生式,则令first(y)~ε follow(B) • 若A→xB是一个产生式,或A→xBy是一个产生式且有ε∈first(y),则令follow(A) follow(B)
例1 G[X]:X→AB A→a|aAa B→b 则:follow(X)={#} 因为A→aAa所以{a} follow(A) follow(A)=first(B)∪{a} ={b}∪{a}={b,a} follow(B)=follow(X)={#}
例2 G[X]:X→ABC A→a|aAa B→b C→c|ε 则:first(C)={c, ε} follow(B)=first(C)~{ε}∪ follow(X) ={c}U{#}={c, #}
- • 若ε∈first(α),则令Select (A→α)=first(α)。 求select(A→α)的算法 • 求first(α)。 • 否则求follow(A)并令Select(A→α) =first(α)∪follow(A)。
例子:G[Z]: Z→aA A→b first(Z)={a} first(A)={b} follow(Z)={#} follow(A)= follow(Z)={#} select(Z→aA)={a} select(A→b)={b}
例子:G[Z]: Z→AB A→a|ε B→b|ε first(AB)={a,b,ε} Follow(Z)={#} select(Z→AB) =first(AB)~{ε}∪follow(Z) ={a,b}∪{#} ={a,b,#}
例子:考虑文法,分别求 first,follow,select集 G[E]:E→TE' E'→+TE'|ε T→FT' T'→*FT'|ε F→i|(E) first(E)=first(T)=first(F)={i,( } first(E‘)={+,ε} first(T')={*,ε}
follow(E)={),#} follow(E')= follow(E)={),#} follow(T)=first(E')∪follow(E) ={+, }∪{ ),#} ={+,),#} follow(T')=follow(T)={+,),#} follow(F)= first(T')∪follow(T) ={*,}∪{ +,),#} ={*,+,),#}
select(E→TE')=first(T)={i,(} select(E'→+TE')={+} select(E‘→ε)=follow(E’)={),#} select(T→FT')=first(F)={),#} select(T'→*FT')={*} select(T'→ε)=follow(T') ={+,),#} select(F→i)={i} select(F→(E))={(}
5.4 不确定的自顶向下分析思想 自顶向下语法的弊端 自顶向下的语法分析方法具有一些弊端: ① 产生回溯问题:在语法树上不知选择那条分支。 ② 会造成无限循环。
S c B A a b A B a 求:select(A→aB)={a} select(A→a)={a} select(A→aB)∩select(A→a)={a} 结论:产生回溯问题
S A B b B S B S b A B G[S]:S→AB A→bB|Aa B→Sb|a Select(A→bB)∩select(A→Aa)={b} 结论:会造成无限循环
总结: 当有两个产生式 A→xi A→xj 并且有 Select(xi)∩ Select(xj)≠Ф 必然会产生回溯问题或会造成无限循环。
5.5 确定的自顶向下分析方法 5.5.1 递归下降法 例:G(E): E→eBaA A→a|bAcB B→dEd|aC C→e|dc 该文法不含左递归和回溯。 编写自顶向下分析程序,其情况如下:
= = 入口 P(E) E→eBaA Ch=e? read error P(B) Ch=a? error P(A) 出口
= = = P(A) 入口 A→a|bAcB Ch=a? Ch=b? read error read P(A) Ch=c? P(B) 出口 error read
5.5.2 预测分析方法(LL(1)方法) • 引入LL(1)文法: 使用递归子程序方法有限制,即对任一非终极符B进行如下操作: • 不含左递归 (否则,会出现重复调用) • select(B,βi)∩select(B,βj)=Ф (i≠j) (否则,不知选哪个分支)
定义3.12LL(1)文法:如果对任一非终极符B都有 select(B,βi)∩select(B,βj)=Ф,(i≠j)。 LL(1)的含义: 第1个L表明自顶向下分析是从左到右扫描字符串,第2个L表明分析过程中将用最左推导,1表明只需向右看一个符号便可决定如何推导即选择那个产生式进行推导。
有四种动作: 替换:当X1∈VN时,选相应侯选式β去替换X1。 匹配:当X1∈VT时,与Y1匹配,如成功则去掉X1和Y1,否则报错 接受:当格局为(空,空)时,分析成功 报错:不为(空,空)时。
设有文法:G[A]:A→aBc B→d|bB 判别符号串是否文法的句子。 格局的变化过程如下: (A, abbdc)==>(cBa, abbdc) ==>(cB, bbdc) ==> (cBb,bbdc) ==>(cB,bdc) ==>(cBb,bdc) ==>(cB, dc) ==>(cd, dc) ==>(c, c)
格局的控制过程由以下条件确定: 栈顶元素(符号栈或分析栈或语法栈) 输入流第一个符号(终极符,#) 格局的控制过程由LL矩阵来表示: LL[Xi,Yj]=ACTij 其中:Xi∈(VN∪VT∪{#} Yj∈(VT∪{#}) ACTij表示动作序列
被分析的串ω写成ω#,并首先往分析栈中放进符号#,为了描述ACTij,引入下面三个过程:被分析的串ω写成ω#,并首先往分析栈中放进符号#,为了描述ACTij,引入下面三个过程: NEXT:删除输入流的第一个字符 PROCESS:不删除输入流的第一个字符 REPL(β):用β的逆串代替栈顶元素 ~ 预测分析方法是自顶向下分析的另一种方法,一个预测分析器是由三部分组成: 预测分析程序 先进后出栈 预测分析表
Ⅱ.对每一个B∈VN a.若有B∈aω(a∈VT),则令 LL[B,a]=(REPL(ω),NEXT) b.若有B→Aω(A∈VN),则令 LL[B,ai]=(REPL(Aω),PROCESS) ~ ~ LL矩阵的构造算法: 对每一B→ω,求select(B→ω) Ⅰ.对每一个a∈VT,a不现于侯选式的首位,令LL[a,a]=(REPL(ε),NEXT)
其中select(B→Aω)={a1,a2,…an} Ⅲ.对#令:LL[#,#]=ok Ⅳ.对其他情形令:LL[X,a]=ERR(k) 处理P,N,R操作: ① 当遇到小写字母时进行N操作,删除小写字母。 ② 当遇到大写字母时进行P操作,保留源大写字母。 ③ 将符号串进行逆序转换。
例子:G(E): E→E+E E→E*E E→(E)|i 1.构造LL矩阵 2.符号串i+i*i的LL分析过程
解:首先此文法有二义性应该去除。 G(E): E→E+T|T T→T*E|F F→(E)|i 其次此文法有左递归应该去除。 G(E): E→TE’ E’→+TE’| T→FT’ T’→*FT’| F→(E)|i
各产生式的SELECT集合为: select(E→TE')=first(T)={i,(} select(E'→+TE')={+} select(E'→ε)=follow(E')={),#} select(T→FT')=first(F)={),#} select(T'→*FT')={*} select(T'→ε)=follow(T')={+,),#} select(F→i)={i} select(F→(E))={(}
表达式文法的预测分析表 i + * ( ) # E E→TE’ E→TE’ E’ E’→ E’→ E’→+TE’ T T→FT’ T→FT’ T’ T’→ T’→ T’→*FT’ T’→ F F→(E) F→i
i + * ( ) # E E’T,P E’T,P E’ E’T,N ε,P ε,P T T’F,P T’F,P T’ ε,P T’F,N ε,P ε,P F ε,N )E,N ) ε,P # OK 表达式文法的LL矩阵
T E’ # F T’ # E ) # T # F # E # 分析过程: E→TE’ T→+FT’ F→(E)
分析栈S 输入流T 矩阵元素 #E i+i*i# LL[E,i]=(E'T,P) #E'T i+i*i# LL[T,i]=(T'F,P) #E'T'F i+i*i# LL[F,i]=(ε,N) #E'T' +i*i# LL[T',+]=(ε,P) #E' +i*i# LL[E',+]=(E'T,N) #E'T i*i# LL[T,i]=(T'F,P) #E'T'F i*i# LL[F,i]=(ε,N) #E'T' *i# LL[T',*]=(T'F,N) #E'T'F i# LL[F,i]=(ε,N) #E'T' # LL[T',#]=(ε,P) #E' # LL[E',#]=(ε,P) # # LL[#,#]=Ok