第四章 自顶向下语法分析方法

4.1语法分析器的功能:

       语法分析是整个编译过程的核心部分,它完成的任务是:按照文法从源程序单词串(符号串)中识别各类语法成分,判断所给出的单词串是否是给定文法的正确句子,并为语义分析和代码生成做准备。


4.2 不确定的自顶向下分析

一、算法思想

       对于任一输入符号串,试用一切可能的办法从树根结点出发根据文法自上向下的为输入串建立一棵语法树



三、对应最左推导

       以上为输入符号串建立语法树的过程,实际上也是一个建立最左推导序列的过程,显然有:SÞcAdÞcad之所以使用最左推导,是因为我们对输入串是从左到右扫描的,只有使用最左推导,才能按扫描顺序去匹配输入串。

四、存在问题

1.左递归问题:自顶向下分析方法,在匹配过程中,假若用到非终结符号U去匹配输入串,而U为左递归的(例如:U®U…),那么为了用它的右部匹配输入串,又要用到非终结符号U,循环往复,没有终止。若文法存在间接递归,也有相同问题发生。

2.回溯问题:对某个非终结符,当有多条规则时,需采用逐个选择的方法,若不能匹配需要回溯,代价高,效率低。

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

一、算法思想

       对于任一输入符号串,从文法的识别符号出发,根据当前的输入符号,唯一的确定一个产生式,用产生式的右部的符号串替代相应的非终结符往下推导,或构造一棵语法树。若能推导出输入串或构造语法树成功则输入串是句子,否则不是。

二、举例
(1)文法G[S]:
S->pA |qB
A->cAd|a
输入串w=pccadd

文法特点:  (1)每个产生式的右部都由终结符号开始;(2)两个产生式若左部相同,则其右部以不同的终结符号开始(3)无空产生式U->e


(2)文法G[S]:
S->Ap |Bq
A->cA | a
B->dB | b
输入串w=ccap

文法特点:  (1)每个产生式的右部并非都由终结符号开始;(2)两个产生式若左部相同,则其右部以不同的终结符号或非终结符号开始,且首符号集不相交(3)无空产生式U->e


(3)文法G[S]:
S->aA | d
A->bAS |e
输入串w=abd

文法特点:  (1)有空产生式U->e(2)两个产生式若左部相同,则其对应的首符号集不相交并且与其后继符号集也不相交;


例题(1)(2)(3)的共同特点:

1)没有左递归
2)在每一步推导中,都可以根

据输入串的当前符号唯一的确

定一个产生式去匹配。

4.3.2 几个重要集合

一、首符号集

设有文法G=(VT,VN, S, P)是上下文无关文法,则符号串x的首符号集合定义为:


例如:有如下文法G[E]
E->E+T| T
T
->T*F| F
F
->(E) | i        则有:
                    
First(E+T)={(, i}
                    
First(T)={(, i}
                    
First(i*i)={i}

二、后继符号集


三、FIRST集及FOLLOW集的构造

1.构造文法符号XFIRST集:

(1) X∈V T ,则 FIRST(X)={X};

(2)X∈VN,且有X->a…, a 加入FIRST(X)

                      若有X->εε加入FIRST(X)

(3)若有X->Y…,Y∈VN ,FIRST(Y)中非ε元素

          全部加入FIRST(X)

    若有X->Y1Y2Y3…YK,Yi∈VN ,ε∈FIRST(Yj)

                    FIRST(Yi)中非ε元素加入FIRST(X)

     ε∈FIRST(Xj),1≤j≤kε加入FIRST(X)

 2.构造符号串αFIRST: (α=X1X2XN)

(1)首先FIRST(α)= FIRST(X1)\{ε};

(2) ε∈FIRST(Xj),FIRST(Xi)\{ε}加入FIRST(α);

(3) ε∈FIRST(Xj),ε加入FIRST(α);

例:设有文法G[E]:

ETE’         E’→+TE’|ε          T→FT’        T→*FT’|ε             F→(E)|i

非终结符号的First集:
First(E)={(,i}
First(E
)={+,ε}
First(T)={(,i}
First(T
)={*,ε}
First(F)={(,i}  
First(E'T')={+,*,ε}

3.构造非终结符XFOLLOW

(1)对文法开始符号S, #加入FOLLOW(S);

(2)若有A->αBβ,FIRST(β)\{ε}加入FOLLOW(B);

(3)若有A->αB, A->αBβε∈ FIRST(β),则 

          FOLLOW(A)加入FOLLOW(B);



LL(1)文法:

    如果一个文法满足以下条件:

1、文法不含左递归。

2、对文法中每一个非终结符A的各个产生式的候选首

符集两两不相交。

3、对文法中每一个非终结符A,若存在某个候选首

符集包含e,则

            First(A)^ Follow(A)=F(空)

      LL(1)中第一个L表明自左(Left)向右扫描输入串,第二个

L表明分析过程采用最左(Left)推导,括号中的1表明只需向右

看一个符号便可决定选择哪个产生式进行推导。

4.3.1非LL(1)文法转换为LL(1)文法

       对某个语言来说其文法不一定是LL(1)文法,而非LL(1)文法将无法采用确定的自顶向下分析方法进行分析,但我们可以通过对文法进行等价变换,在有些情况下使其成为LL(1)文法。

一、提取左公共因子


1.方法:若有产生式U->xy|xw|…|xz,则提取左公共因子并用EBNF表示为: U->x(y|w|…|z)

再引入另一个非终结符号V,将产生式变为:
U->xV
V->y|w
|…|z

若在y,w,…,z中仍然有左公共因子,可以再次提取。注意,若有:U->xy|x,则提取后:U->x(y|e)

2.举例

设有产生式:Sif B  then  S1  else  S2  |if  B then  S1

其中,S表示两种类型的条件语句。

提取公因子,改成:S→if  B  then  S1 ( else S2  | e)

引入非终结符号R
                           
S→if B then S1 R

                            R→else  S2 

文法中,if, then, else<(属于)VT

3.说明

文法提取左公共因子后,只能使相同左部的产生式右部的First集不相交。

文法提取左公共因子后,若文法中无空产生式,且无左递归,则改写后的文法为LL(1)文法。

有些文法,不能在有限步骤内改写为无左公共因子的文法。

二、消除左递归

左递归文法的分析程序可能进入死循环,可以证明,左递归文法不可能是LL(1)文法。

1.消除直接左递归:若有产生式U->x|y|…|z|Uv, U<VN, x,y,z,v<V*则改写并用EBNF表示为:



2.消除间接左递归:先将间接左递归变为直接左递归,再按消除直接左递归的方法进行。


举例:有文法G[S]:

S→Qc|c

Q→Rb|b

R→Sa|a

该文法无直接左递归,但,S=>Qc=>Rbc=>Sabc,故有间接左递归,所以文法G[S]为左递归文法。

(1)对非终结符号排序:R, Q, S

注意:对非终结符号的排序是任意的(但要保证开始符号不变),不同的排序最后所得文法得形式可能不同,但它们是等价的。

4.4 确定的自顶向下分析方法举例

一、递归子程序法

      递归子程序法是比较简单直观易于构造的一种语法分析方法,其方法思想是对源程序中每个语法成分编制一个处理子程序,即对 每个非终结符号编制一个递归过程,每个子程序的功能是识别由该非终结符号推出的串 。它要求文法满足 LL(1) 文法,以便当某个非终结符号有多条产生式时,可以根据当前的输入符号唯一地确定选择某个产生式进行匹配。

文法G[E]  :      

              ETE’          

              E’→+TE’|ε         

              T→FT’

              T→*FT’|ε

              F→(E)|i


Progrom E;
  Begin
    T
    While sym=“+” do
    Begin advance;  T end
  End
Progrom T;
  Begin
     F
     While sym=“*” do
     Begin  advance;  F end
End
Progrom F;
If sym= “i” then advance
      else If sym= “(” then        
           Begin advance;   E
                     If sym= “)” then advance
                     else error           
           End
     else error

4.5 预测分析程序——LL(1)分析器:

      预测分析程序也是一种自顶向下分析程序,预测分析要求文法是LL(1)文法,它由分析栈、分析表和分析程序三部分组成,其中分析表的构成与文法有关。下面举例说明分析器的构造过程:

设有文法G[E]:
E→E+T|T
T→T*F|F
F→(E)|i

1.判断是否LL(1)文法

(1)消除左递归:
ETE’          

E'→+TE’|ε         

T→FT’

T'→*FT’|ε

F→(E)|i

(2)找出能推出ε的非终结符号:
    
E, T

(3)非终结符号每一候选式First
First(TE')={(,i}  First(+TE')={+} First(ε)={ε} First(FT')={(,i}
First(*FT
)={*} First(ε)={ε} First((E))={(} First(i)={i}

(4)(含ε产生式非终结符号Follow
Follow(E)={),#}
Follow(E')={),#}
Follow(T)={+,),#}
Follow(T')={+,),#}
Follow(F)={*,+,),#}

 文法是LL(1)文法。

2.构造预测分析表

定义:预测分析表与文法有关,它说明当某个非终结符号U向下推导时,面临输入符号a时,所应选用的产生式。

(2)表示:预测分析表可用一矩阵M表示,矩阵的行表示非终结符号,矩阵的列表示输入符号或#,矩阵的元素M[U,a]表示对非终结符号U ,当面临输入符号a时,它向下推导所应采取的产生式。

(3)构造方法:

,对于上例中的文法G[E],预测分析表为:

当元素内无产生式时,表明用非终结符号U向下推导时,遇到了不该出现的输入符号。所以元素内容可以存放转向出错处理的错误信息.

举例:分析输入串i+i是否为文法G[E](上例)的句子。

首先为输入串i+i加上括号,即被分析的串变为#i+i#,分析过程如下:


4.1考虑下面文法G1S-〉a | ∧ | T
                              
T-〉TS | S
1
)消去G1的左递归

消除左递归:S-〉a| ∧ | T

    T-〉ST

    T-〉S T

a、由(1)知,改写后的文法不含左递归;

b、下面分别对各非终结符的候选求FIRST集:

    FTRST(a)={a}               FIRST(∧)={∧}

    FIRST((T))={(  }        

    FIRST(ST)={}        FIRST(ε)={ε}

   对非终结符S有:FTRST(a)∩FIRST(∧)∩FIRST((T))=Φ

   对非终结符T有:FIRST(ST) ∩ FIRST(ε)=Φ

cFIRSTS={a,∧,(}          FOLLOWS={#,,)}

     FIRSTT={a,∧(}        FOLLOWT={ )}

     FIRSTT={,ε}          FOLLOWT={ )}

  故: FIRSTT)∩FOLLOWT

   综合以上的分析,经改写后的文法是LL1)文法

其预测分析表为:


有文法:E->TE

              E->ATE

              T->FT

              T->MFT

              F->E|i

              A->+ | -

              M->* | /

1)、求FirstFollow集,判断是否是LL1)文法?

2)、若是构造LL1)分析表?

3)、简述LL1)分析器的工作原理。

解:1)、文法中各非终结符的First集和Follow


2)、LL1)分析表


3)、对i+i*i进行预测分析的过程表




















  • 17
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,我可以帮您解答这个问题。生成代码可以通过编写LL(1)语法分析器来完成,特别是要保证能够处理出错的情况。LL(1)语法分析器是一种自顶向下的分析器,它可以将输入语句解析成词法单元序列,并进行语法分析。在此过程中,如果出现语法错误,分析器应该能够抛出错误信息并提示用户进行修正。希望这能帮助您解决问题。 ### 回答2: 自顶向下语法分析是一种从文法的开始符号开始,通过对输入符号串的左推导过程来建立语法树。LL(1)语法分析器是一种具有预测分析表的自顶向下分析方法,能够通过LL(1)文法规则来分析表达式,实现语法分析的同时,也能处理出错的情况。 实现LL(1)语法分析的基本步骤如下: 1. 构建LL(1)预测分析表:根据给定的文法,按照逐步处理非终结符号的规则构建预测分析表,表中的每个非终结符对应每个终结符的预测产生式。 2. 初始化分析栈和输入缓冲区:将文法的开始符号压入分析栈,并将输入符号串的第一个字符放入输入缓冲区。 3. 进行语法分析:通过预测分析表,进行匹配和推导的过程,逐步将输入符号串进行左推导,直到所有输入符号都被处理完毕或出错。 a. 如果分析栈的栈顶为非终结符号,且与输入缓冲区的首字符相同,则进行匹配,并将栈顶符号弹出,将相应的预测产生式逆序压入分析栈中。 b. 如果分析栈的栈顶为终结符号,且与输入缓冲区的首字符相同,则进行匹配,并将栈顶符号和输入缓冲区的首字符同时弹出。 c. 如果分析栈的栈顶符号与输入缓冲区的首字符都不匹配,则说明出现了错误。可以选择错误恢复策略,如跳过输入符号继续分析或弹出栈顶符号忽略错误。 4. 判断结束状态:如果分析栈为空且输入缓冲区为空,说明成功完成了语法分析;如果分析栈为空但输入缓冲区不为空,说明语法分析失败。 通过以上步骤,我们可以使用LL(1)语法分析方法完成表达式的分析,并能够处理出错的情况。注意,LL(1)文法有一定的限制,例如无左递归,且产生式需要消除左公因子等。 ### 回答3: 自顶向下语法分析是一种从文法的开始符号开始,通过逐步向下扩展、匹配输入符号串的过程来构建语法树的方法。在LL(1)语法分析中,LL表示从左到右扫描输入符号串,同时使用最左推导法则,1表示在任何给定的输入符号后,唯一能够选择的产生式。 表达式的分析可以按照以下步骤进行: 1. 首先,确定文法的产生式集合。对于表达式的文法,可以考虑产生式包括表达式的各种运算符和终结符。例如:表达式 → 表达式 + 项 | 表达式 - 项 | 项,项 → 项 * 因子 | 项 / 因子 | 因子,因子 → 数字 | (表达式)。 2. 构建LL(1)分析表。根据文法的产生式,可以得到每一个非终结符对应的终结符集合,并建立分析表。例如,对于非终结符表达式,如果下一个输入符号是+,就选择表达式 → 表达式 + 项这个产生式;如果下一个输入符号是-,就选择表达式 → 表达式 - 项这个产生式。同理,对于非终结符项和因子也可以建立相应的分析表。 3. 进行语法分析。从开始符号开始,根据当前输入符号和栈顶的非终结符,查找分析表,选择相应的产生式。如果无法找到对应的产生式,则说明存在语法错误。在匹配完整个输入符号串之后,如果分析栈为空,说明语法分析成功;否则,语法分析失败。 4. 处理错误情况。当在分析过程中遇到不能完成匹配的情况时,可以进行错误恢复措施。一种常见的错误恢复方法是跳过当前输入符号,继续进行分析。 总之,通过以上步骤,使用LL(1)语法分析器可以完成表达式的分析,并且能够处理出错的情况。中文回顾了自顶向下语法分析的流程,并解释了如何使用LL(1)分析方法实现对表达式的语法分析,特别说明了如何处理错误情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值