自上而下分析算法要点:

。由根向下构造语法树

。构造最左推导

。推导出的终结符是否与当前输入符匹配

5.1 确定的自顶向下分析思想

例1 :若有文法G1[S]

S →pA | qB

A →cAd |a

B → dB |bf

对于输入串:W=pccadd自顶向下推导过程:

S pA pcAd pccAddpccadd分析成功

该文法有两个特点:

  • l         每个产生式的右部都有终结符号开始。
  • l         如果两个产生式左部相同,那么他们右部有不同的终结符开始。

(1)First集

定义5.1   设G=(VT VN,P,S)是上下文无关文法,

FIRSTa)={a|a ab,a∈VTab∈V* }。

a ε则规定ε∈FRIST(a),称FIRST(a)为a的首符号集。

例2:

S →Aa | Ba    A →cb    B →bA | aBc     问符号串cba是否为该文法句子。

SAa               (S → Aa)

cba             (A → cb)

FRIST(Aa)={c}          FRIST(Ba)={b, a}

FRIST(Aa)∩Ba) =Φ

(2)Follow集

定义5.2  设G=(VT VN,P,S)是上下文无关文法

FOLLOW(A)={a|S  m A b且a ∈ FRIST(b),m∈V*, b∈V+  }

  若S  u A b,且b ε,则规定#∈FOLLOW(A)

例3:

S →dB | ε   B →dfa是否为该文法句子。

SAa               (S → Aa)

 dBa              (A → dB)

 dfa              (B → f)

FRIST(dB)A)={a ,e }

FRIST(dB)∩FOLLOW(A)=Φ

一个文法G能进行确定的自顶向下分析,当且仅当对于G的每一个非终结符A的任何两个不同产生式A®α½β,下面的条件成立:

FIRST(α)∩FIRST(β)=f,也就是α 和β推导不出以同一个终结符a为首的符号串;它们不应该都能推出空字e.

假若βε,那么,FIRST(α)∩FOLLOW(A)=f。 也就是,若βε则α所能推出的串的首符号不应在FOLLOW(A)中.

(3)SELECT集

定义5.3 设G=(VT,P,S)是上下文无关文法,对P中的任一 产生式 Aa α,VN ,V*。

若αε, 则SELECT(A→α)= FRIST(α)

若αε,则SELECT(A→α)=(α)-{ε})∪A)

如果对于G的每一个非终结符A的任何两个不同产生式A→ α|β,都有

A →α)⋂A→β)=Φ,其中α、β不能同时ε。

G进行确定的自顶向下分析。

例2中:S –> Aa | Ba            SELECT(S –> Aa) ∩S –> Ba )= Φ

A –>cb

B –> bA | aBc         SELECT(B –> bA) ∩B –> aBc)=Φ

所以能对文法G[S]进行确定的自顶向下分析。

例3中:S –> Aa | bB          SELECT(S –> Aa) ∩S –> bB )=Φ

A –>dB | ε               SELECT(A –>dB) ∩A –>e=Φ

B –> Ae | f             SELECT(B –> Ae) ∩B –> f )=Φ

所以能对文法G[S]进行确定的自顶向下分析。

(4)LL(1)的定义

定义5.4  一个上下文无关文法是1)文法的充分必要条件是:对于G的每一个非终结符A的任何两个不同产生式A→ α|β,满足SELECT(A →α) ∩A→β)=Φ,其中α、β不能同时ε

5.2  LL(1)文法的判别

一个文法G是LL(1)的,当且仅当对于G的每一个非终结符A的任何两个不同产生式Aα|β,下面的条件成立:  SELECT(A →α) ∩A→β)=Φ,其中α、β不能同时ε

步骤如下:

(1)求出能推出ε的非终结符

可通过求其First集,First集中含ε即可。

(2)计算FIRST集

1)若X∈VT,则FIRST(X)={X}。

2)若X∈VN,且有产生式X→a…,则把a加入到FIRST(X)中;若X→a也是一条产生式,则把ε也加到FIRST(X)中。

3)若X→Y…是一个产生式且Y∈VN,则把FIRST(Y)中的所有非ε元素都加到FIRST(X)中;若X→Y1,Y2,…,Yi-1都是非终结符,而且,对于任何j,1≤j ≤i-1,Yj)都含有ε (即Y1。。Yi-1 * ε ),则把FIRST(Yj)中的所有非e元素都加到FIRST(X)中;特别是,若所有的FIRST(Yj ,2,…,K)均含有ε,则把ε加如FRIST(X)。

(3)计算FOLLOW集

1)对于文法的开始符号S,置#于FOLLOW(S)中;

2)若A→αBβ是一个产生式,则把FIRST(β)-{ ε}加至FOLLOW(B)中;

3)若A→αB是一个产生式,或A®αBβ是一个产生式而βε(即eÎFIRST(β)),则把FOLLOW(A)加至FOLLOW(B)中?(S …Aa… … αBβa…)。

(4)计算SELECT集

对上下文无关文法G=(VT,P,S)中的任一产生式A→α(VN , α∈V* ),计算SELECT集:

当α*ε时,SELECT(A→α)= FRIST(α)。

当α*ε时,SELECT(A→α)=(-{ε})∪A)。

例4:G[ E]:   

(1)2)3)e

(4)5)6)e

(7)E)8) i

第一步:各非终结符的FIRST集合为:

FIRST(E)={(,i};FIRST(E′)={+,ε};FIRST(T)={(,i}

FIRST(T′)={*,ε};FIRST(F)={(,i}

第二步FOLLOW集合为:

E)={),#};E′)={),#};FOLLOW(T)={+,),#}

T′)={+,),#};FOLLOW(F)={*,+,),#}

第三步:求各非终结符的SELECT集:

E’ →+TE’ | e

E’ →= FIRST(+TE’)={+}

SELECT (E’ →e)=FOLLOW(E′)={),#}

T’ →e

T’ →= FIRST(*FT’)={*}

T’ → e= FOLLOW(T′)={+,),#}

F→ (E)  | i    

F→(E) )= FIRST((E))={(}

F→ (E)= FIRST(a)={i}

因为文法中每个非终结符的所有产生式的SELECT集两两不相交,所以G[E]是LL(1)的

5.3 某些非LL(1)文法到LL(1)文法的等价变换

5.3.1提左公因子

 αβ|αγ 变换为:A→αB

例5:S →aS    S → ε

改写为: S →b|ε)ε

在改写:S →aSA        A→b|ε     S→ε

有时,左公共因子是隐式的。

例6:A →Bc      B →bB

改写为:A →aAc|bBc       B →bB

改为:A →aA’|bBc     A’ →aA     B →bB

5.3.2 消除直接左递归

α 或A→B β 且α,含有左递归的文法不能进行自顶向下分析。

一般情况:A→Aα1|Aα2|…Aαm| β1 |β2… | βk

变形为:A®A(α1|α2|…αm)1 |β2… | βk )

改写为:A→(β1 |β2… | βk )A’   A’ →(α1α2|…αm)A’| ε

例7:Qc|c     Q →Rb|b    R→Sa|a

非终结符次序S,Q,R

Qca|ca|a    R →Rbca|bca|ca|a

改写为:S →Qc|c     Q →Rb|b     R →(bca|ca|a )R’     R’ →bcaR’|e

 

 

 

5.4 不确定的自顶向下分析

(1)对于文法G中的某一个非终结符A,存在A的两个不同产生式A→ α|β,并且

         FIRST(α)∩FIRST(β)≠Φ

确定不了用哪个产生式推导。

举例如下:带回溯的自上而下分析

S→ b | bB

推导串:a  a a b b。

正确过程:

S(1)  AB             S –> AB

(2)  aAB            A –> aA

(3)  aaAB           A –> aA

(4) aaaAB           A  –> aA

(5) aaa ε B         A –> ε

(6) aaab            B –> b

错误推导:

S(1) A。。。> AB

(2) aA。。。> aA

(3) aaA。。。> aA

(4) aaaA。。。> aA

(5) aaa ε B     A –> ε

(6) aaa b B    B –> bB

(7) aaabb        B –> b

因为:FIRST(B –> b)∩FIRST(B –> bB)={b}

(2)对于文法G中的某一个非终结符A,存在A的两个不同产生式A→ α|β,并且

   假若βε,那么,FIRST(α)∩FOLLOW(A)≠Φ

(3)文法G中含有左递归


5.5  确定的自顶向下分析方法

确定的自顶向下分析方法:

  • l         特征——根据下一个输入符号为当前要处理的非终结符选择产生式。
  • l         要求——文法是LL(1)。

ü    L:从左到右扫描输入串

ü    L :生成的是最左推导

ü    lookahead)

5.5.1 递归子程序法

递归下降子程序: 对应文法中每个非终结符编写一个过程。

例:递归子程序实现 --表达式的语法分析

〈表达式〉∷=[+|-]〈项〉{(+|-)〈项〉}

〈项〉∷=〈因子〉{(*|/)〈因子〉}

〈因子〉∷=ident|number|(〈表达式〉)

〈表达式〉∷=[+|-]〈项〉{(+|-)〈项〉}

5.5.2 预测分析方法

预测分析方法是自顶向下分析的一种方法,一个预测分析器是由三个部分组成。

  • l         预测分析程序(总控程序)
  • l         先进后出栈(stack)
  • l         预测分析表

下推栈的初始状态包含两个符号:‘#S’,其中‘#’为栈底,‘S’为文法开始符号。整个分析过程在语法分析程序控制下进行。在语法分析中用到的文法产生式的表,称为语法表。

(1)基本模型

基本模型如下:

预测分析程序是无回溯的自顶向下分析程序。

(2)工作过程

其工作过程如下:

图中符号说明如下:

  • l         “#”句子括号即输入串的括号
  • l         “S”文法的开始符号
  • l         “X”存放当前栈顶符号的工作单元
  • l         "a"存放当前输入符号a的工作单元

(3)预测分析法步骤

通过举例讲解预测分析法具体步骤如下:

例:G[ E]:    (1)E →2)3)E’ → e

4)T →FT’      (5)T’ →6)T’e

7)F →(E)8) a

第一步:构造预测分析表

设每个终结符或“#”用a表示:

1)对文法G的每个产生式A®a执行:

若ÎSELECT(A®a) ,则把A®a加至M[A,a]中。

2)把所有无定义的M[A,a]标上“出错标志”。

可以证明,一个文法G的预测分析表不含多重入口,当且仅当该文法是LL(1)的。

SELECT(E→= FIRST(TE’)FT’)a}

SELECT(E’ →+TE’)= FIRST(+TE’)={+}

SELECT (E’ →ε)=FOLLOW(E′)={),#}

SELECT(T→ FT’)= FIRST(FT’)a}

SELECT(T’ →= FIRST(*FT’)={*}

SELECT(T’ →ε)= FOLLOW(T′)={+,),#}

SELECT(F→ (E) )= FIRST( (E))={(}= FIRST(a)={a}

因为文法中每个非终结符的所有产生式的SELECT集两两不相交,所以G[E]是LL(1)的。

其预测分析表如下:

第二步:分析输入串#a+a#

栈内容b ]

1  #E      E             a                 +a#            E→ TE’

2  #E’T    T             a                 +a#            T→ FT’

3  #E’T’F  F             a                  +a#            F→ a

4  #E’T’a  a             a                  +a#

5  # E’T’   T’            +                   a#            T’ →ε

6  #E’      E’            +                   a#            E’ → +TE’

7  #E’T+   +             +                   a#

8  # E’T   T             a                     #            T→ FT’

9  #E’T’F  F             a                     #            F→ a

10 #E’T’a   a              a                    #

11 #E’T’    T’            #                                  T’ → e

12 #E’      E’            #                                  E ’ → e

13 #        #              #