语法分析总结(上)-自上而下分析

一、知识点总结

    语法分析分为两部分:自上而下的推导,和自下而上的规约。第四章讲述的是自上而下的推导,主要内容包括文法的改造,LL分析和LR分析。要搞清楚语法分析,首先需要明白什么是语法分析,怎么进行语法分析,分析的结果是什么等等,接下来我们逐一介绍。
      语法分析是编译过程的核心部分,它的任务是在词法分析识别出单词符号串的基础上,分析并判定程序的语法结构是否符合语法规范。它的基本思想是为输入串寻找一个最左推导,是一个反复使用不同产生式谋求匹配输入串的过程。
它的构造方法是:让每个非终结符号对应一个递归子程序。每个子程序可以作为一个布尔过程(返回“真”或“假”):
 (1)一旦发现该非终结符的某个候选式与输入串相匹配,就用这个候选式去扩展语法树,并返回“真”值;
 (2)该候选式和输入串不匹配,则保持原来的语法树和IP值不变(IP回溯),并返回“假”值
但是这种分析方式面临着一下几个问题:
1>文法的左递归问题
    若有如下形式:p-->pa则为左递归,文法的左递归会使推导无限循环下去,从而无法解决问题。
2>回溯的不确定性问题
    匹配不成功,需要回溯。需要把已经做过的一大堆工作(各种表格工作、语义分析等)推倒重来,既费时又费力
3>虚假匹配的问题
    设有文法(1) S → xAy(2) A →* | **,分析输入串x**y。S-->xAy,正常情况下非终结符A可以生成**从而完成匹配,但是,如果系统自动匹配,会选择A-->*,从而导致匹配失败。这就是虚假匹配问题。
4>不能准确地确定输入串中出错的位置
5>效率低
        那接下来引入LL(1)分析法解决问题,首先最重要的消除左递归。消除左递归包括消除直接左递归和消除间接左递归
1>消除直接左递归的方法:
设有产生式
  P→Pα1|Pα2|…|Pαm|β1|β2|…|βn,
 其中每个βi不以P开头,每个αi不为ε
 消除P的直接左递归性就是把这些规则改写成:
  P→β1P’|β2P’|…|βnP’
  P’→α1P’| α2P’|…|αmP’| ε
例如:T-->T*F|F 可改为 T-->FT’,T’-->*FT’|ε
2>消除间接左递归的方法:

文法:  
   S→Qc|c
   Q →Rb|b
   R →Sa|a
 把R带入到Q中有关的候选式: 
      Q →Sab|ab|b 
 现在Q同样不含直接左递归,把它带入S的有关候选式:
      S →Sabc|abc|bc|c

    (1) 消除文法的左递归分为:           
 1>将间接左递归改造为直接左递归
     将文法中所有如下形式的产生式:
            Pi →Pjγ|β1|β2|…|βn
                  Pj→δ1|δ2|δ3|…|δk
      改写成:
     Pi →δ1γ|δ2γ|δ3γ|…|δkγ|β1|β2|…|βn
2>消除直接左递归
    P→Pα1|Pα2|...|Pαm|β1| β2|...| βn
    消除P的左递归
    P→ β1P'| β2P'|...| βnP'
    P'→ α1 P'| α2 P'|...|αm P'| ε
3>化简改写后的文法,即去除那些从开始符号出发却永远无法到达的非终结符的产生规则。
  最终得到无左递归的文法。

      (2)消除回溯

消除回溯的关键在于定义First集:令文法G是不含左递归的文法,对G的非终结符的候选α,定义它的开始符号(终结首符)集合:

    特别地,如果α   ε,则ε∈FIRST(α);
如果非终结符A的任意两个候选式αi和αj的开始符号集满足FIRST(αi)∩FIRST(αj)=Φ,则A可以根据所面临的第一个输入符号,准确地指派一个候选式α去执行任务,α是那个FIRST集含a的候选式,即  a ∈FIRST(α)。 
 许多文法都存在非终结符的首符集两两相交的情况,这种情况下,可通过提取公共左因子的方法对文法进行改造,即
假设A的产生式为
  A→δβ1|δβ2|…|δβn|γ1| γ2|…|γm
其中每个γ不以δ开头
那么把这些产生式改写为:
  A→δA’ |γ1| γ2|…|γm
  A’→β1|β2|…|βn
反复提取左因子(包括对新引进的非终结符,例如A’)

当一个文法不含左递归,并且满足每个非终结符的所有候选首符集两两不相交的条件,如果空字符属于某个非终结符的候选符号集,那么问题就比较复杂,此时需要引入follow集,

对文法G的任何非终结符A,定义它的后继符号集合:

特别地,如果S-->…A,则#∈FOLLOW(A)
FOLLOW(A)集合是所有句型中出现在紧接A之后的终结符号或#所组成的集合
当非终结符A面临输入符号a,且a不属于A的任意候选式的FIRST集但A的某个候选式的FIRST集包含ε时,只有当a∈FOLLOW(A),才可能允许A自动匹配

接下来引入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-自左向右扫描、自左向右的分析和匹配输入串。
  分析过程表现为最左推导的性质。

LL分析程序构造及分析过程包括:分析表 ,执行程序 (总控程序) ,符号栈 (分析栈)

执行程序主要实现如下操作:
1.把#和文法起始符号E推进栈,并读入输入串的第一个符a,重复下述过程直到正常结束或出错.
2.测定栈顶符号X和当前输入符号a,执行如下操作:
(1)若X=a=#,分析成功,停止。E匹配输入串成功.
(2)若X=a≠#,把X推出栈,再读入下一个符号。
(3)若X∈Vn,查分析表M
a) M[X,a]=   X→UVW
        则将X弹出栈,将UVW压入
     注:U在栈顶 (最左推导)
   b) M[X, a] = error   转出错处理
   c) M[X, a] = X-〉ε     ---a为X的后继符号
       则将X弹出栈 (不读下一符号)
           继续分析。
预测分析表的构造:

first表的构造:

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

follow表的构造:

对于文法的开始符,置#于FOLLOW(S)中
若A->αBβ, 则把FIRST (β)-ε加入到FOLLOW(B)中,
若A->αB 是一个产生式,或 A->αBβ是一个产生式,而β-> ε,则把FOLLOW(A)加入到FOLLOW(B)中

预测分析表的构造

对文法G的每个产生式, A->α,进行下面的处理
对每个终结符a,如果a属于FIRST(α),则把该产生式写入到M[A,a]
若ε属于FIRST(α),则对任何b属于FOLLOW(A), 把该产生式加入到M[A,b]
所有无定义的M[A,a]标上出错标志

LL(1)分析中的错误:预测分析过程中错误的识别
当栈顶的终结符与当前的输入符不匹配
非终结符A处于栈顶,面临的输入符号为a, 但分析表中M[A,a]为空
错误恢复的方法:
跳过输入串中的一些符号,直到遇到同步符号。遇到同步符号时,将符号栈顶的非终结符出栈
将FOLLOW(A)设为同步符号
将FIRST(A)加入到同步符号
如果非终结符产生空串,可以自动匹配,以推迟检测到错误的时间。
如果栈顶是终结符,当出错时,直接将栈顶出栈

二、习题总结

   第一张是第一遍做的,写follow集的时候总是出错,原因是对follow集的定义不熟悉,预测分析表也不太会,还有就是LL(1)型文法的判断,第二张图片是后来又做了一遍。第一遍做完以后又看了遍课本,还是要上课好好听的,不然看课本也是看不明白的。血的教训啊!


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值