语法分析是编译过程的核心部分,它的主要作用是根据单词找出符合语法规则的句子。
自上而下分析的主旨是,对任何一个输入串,试图用一切可能的办法,从文法的开始符号(根节点)出发,根据文法自上而下地为输入串建立一棵语法树,即为输入串寻找一个最左推导。本质上是一种试探过程,是反复使用不同产生式谋求匹配输入串的过程。

自上而下分析面临的问题:

  1.文法的左递归问题,会使分析过程陷入无限循环。

  2.若匹配不成功,需要回溯。需要把已经做过的一大堆工作(各种表格工作、语义分析等)推倒重来,既费时又费力。

  3.虚假匹配的问题。由于虚假现象,我们需要更复杂的回溯技术,一般来说,要消除虚假匹配是很困难的。

  4.当最终报告分析不成功时,难于知道输入串中出错的确切位置。

  5.由于带回溯,实际上才用了一种穷尽一切可能的试探法,因此,效率很低,代价极高。该方法只有理论意义,在实践上价值不大。

一般的自上而下方法存在回溯,会产生左递归(P=>Pα),且回溯具有不确定性,可能产生虚假匹配,不能准确地确定输入串中出错的位置,效率低。不带回溯的自上而下分析算法LL(1)可以消除这些问题。
   不带回溯的文法不能含左递归
 消除左递归:(1消除直接左递归:把产生式P→Pα1|Pα2|…|Pαm|β1|β2|…|βn(βi不以P开头,αi不为ε)改写成:P→β1P'|β2P'|…|βnP’,P'→α1P'| α2P'|…|αmP'| ε
         (2)间接左递归:把间接左递归改为直接左递归,将文法中产生式:Pi→Pjγ|β1|β2|…|βn, Pj→δ1|δ2|δ3|…|δk改写成:Pi →δ1γ|δ2γ|δ3γ|…|δkγ|β1|β2|…|βn;消除直接左递归,化简改写后的文法,去除那些从开始符号出发却无法到达的非终结符的产生规则。
消除回溯:
要使文法没有回溯要满足:(1)用候选式去匹配字符串时,若该候选式匹配成功,那么该匹配不是虚假匹配
                                             (2)若该候选式无法匹配,则其他任何候选式也无法完成。消除回溯的过程中需要用到终结首符集FIRST集(非终结符α产生式右部的第一个终结符,若α能推出ε,则ε∈FIRST(α)),如果非终结符A的任意两个候选式两两不相交,即FIRST(αi)∩FIRST(αj)=Φ,则A可以为输入符号a,选择候选式α(FIRST集含a的候选式,即  a ∈FIRST(α))完成匹配。当候选式的First集不满足两两不相交时,通过提取公共左因子改造文法。为避免ε∈FIRST(α)时自动匹配引起语法错误,定义FOLLOW(A)集(非终结符A后的第一个终结符或“#”,特别地,如果开始符S能推出…A,则#∈FOLLOW(A)。
    

1.不带回溯的自上而下分析的文法条件(LL(1)文法)

         (1)文法不含左递归

         (2)对于文法中每一个非终结符A的各个产生式的候选式的FIRST集两两不相交。即,若

                            A→α1|α2|…|αn

                   则     FIRST(αi)∩FIRST(αj)=Φ (i≠j)

         (3)对于文法中的每个非终结符A,若它的某个候选首符集包含ε,则

                            FIRST(A)∩FOLLOW(A)=Φ

         如果一个文法G满足以上条件,则称该文法G为LL(1)文法(第1个L代表从左到右扫描输入串,第2个L代表最左推导,1表示分析时每一步只看1个符号)

  当一个文法满足LL(1)条件时,我们就可以构造一个不带回溯的自上而下分析程序,这个分析程序由一组(可能的)递归程序组成,每个过程对应文法的一个非终结符。这样一个分析程序称为递归下降分析器。

  具体做法:

  对文法的每一个非终结符都编一个分析程序,当根据文法和当时的输入符号预测到要用某个非终结符去匹配输入串时,就调用该非终结符的分析程序。

  LL-自左向右扫描、自左向右的分析和匹配输入串。分析过程表现为最左推导的性质。该过程由分析表、总控程序、符号栈三部分组成。由于最左推导,进栈过程是逆序的。

2.预测分析表的构造——FIRST(X)

(1)若X终结符,则FIRST(X)={X};

(2)若X为非终结符,且有X->a …的产生式,则把a加入到FIRST(X)中;

(3)若X->Y…是一个产生式,且Y为非终结符,则把FIRST (Y)-ε加入到FIRST(X)中;

(4)若X->Y1Y2Y3….YK,是产生式,Y1Y2Y3….Yi-1是非终结符,而且ε属于FIRST (Yj)(1<=j<=i-1),则把FIRST (Yj)-ε加入到FIRST(X)中;如果ε属于所有的FIRST (Yj),则ε加入到FIRST(X)中。

 3.预测分析表的构造——FOLLOW(X)

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

(2)若A->αBβ, 则把FIRST (β)-ε加入到FOLLOW(B)中;

(3)若A->αB 是一个产生式,或 A->αBβ是一个产生式,而β-> ε,则把FOLLOW(A)加入到FOLLOW(B)中。

4.

构造分析表的算法:  

对文法G的每个产生式, A->α,进行下面的处理

  1. 对每个终结符a,如果a属于FIRST(α),则把该产生式写入到M[A,a]

若ε属于FIRST(α),则对任何b属于FOLLOW(A), 把该产生式加入到M[A,b]

所有无定义的M[A,a]标上出错标志

习题:

编译原理第四章-语法分析(自上而下)

编译原理第四章-语法分析(自上而下)

总结:这一章内容难度有点大,求FIRST集和FOLLOW集是重点,做题目的时候很容易出错,因此需要很仔细。通过对本章的学习,对于预测分析法的语法分析程序和递归子程序的区别与联系有了一定认知了解,还有一部分内容没有弄懂,还需课下多看多理解。

相关文章: