编译原理-语法分析-自上而下分析

语法分析器的功能

语法分析器是编译过程的核心部分。任务是在词法分析识别出的单词符号串的基础上,分析并判定程序的语法结构是否符合语法规则。
image

自上而下分析面临的问题

  1. 左递归:p>pα|β:会使程序陷入死循环,导致不可实现
  2. 回溯:试探法就是穷举所有可能,一旦遇到不匹配就进行回溯,尝试下一种可能,这种方法只在理论上有意义,由于回溯穷举时间开销巨大所以不太具有实践意义。

LL(1)分析法

左递归的消除

直接左递归

直接左递归的形式:p>pα|β β不以p开头
这个推导:

p=>pα=>pαα=>...=>βα....α

从这个推到我们可以看出p推出的串是以β后面跟着若干个α组成的串
这样我没对这个串做等价变换:

p>βp

p>αp|ϵ

我们可以验证这个文法是不是和上面左递归形式的文法等价,我们对这个文法做推导看看会推导出哪些串

p=>βp=>βαp=>...=>βα...α

我们得到的串同样是以β开头后面接跟着若干个α的串
我们对上面的结论进行推广:
对于P的全部产生式是

P>Pα1|Pα2|...|Pαm|β1|β2|...|βn,αϵ,βP

我们直接进行右递归改造:

P>β1P|β2P...|betanP

P>α1P|α2P|...|αmP

例子:
E>E+T|T
T>TF|F
F>(E)|i
对于第一个式子有直接左递归我们进行消除,首先第一个式子最终的推导串是以T开头后面若干个{+T}我们进行等价变换:E>TE E>+TE|ϵ
对于第二个式子也是直接左递归的我们也需要进行消除,首先第二个式子最终推导出的串的形式下以F开头后面若干个*F,我们根据这个进行等价变换
T>FT
TFT|ϵ
最后一个式子没有直接左递归不用进行处理

非直接左递归

G(S)

S>Qc|c

Q>Rb|b

R>Sa|a

形式上这个文法并没有直接左递归,但是实际上这个文法是左递归的,进行如下推导就可以看出

S=>Qc=>Rbc=>Sabc

经过推导我们发现S实际上是左递归的
我们从上面的文法可以看出S是由Q定义的,Q是由R定义的,R是由S定义的,那么我们可以得到下图
image
S>Qc|c
Q>Rb|b
R>Sa|a
我们将Q中的R替换掉
image
S>Qc|c
Q>Sab|ab|b
R>Sa|a
再将S中的Q替换掉
image
S>Sabc|abc|bc|c
Q>Sab|ab|b
R>Sa|a

消除左递归的算法

1.把文法G的所有非终结符按任意一种顺序排列成P1P2,...,Pn按此顺序执行
2.
FORi:=1TOnDO
BEGIN
FORj:=1TOi1DO
Pi>PjγPi>δ1γ|δ2γ|...|δkγ(Pj>δ1|δ2|...|δkPj)

消除回溯、提左因子

FIRST

为了消除回溯,我们首先需要引入两个概念一个是FIRST集一个是FOLLW集
FIRST:
零G是一个不含左递归的文法,对G的所有非终结符的每一个候选α定义它的终结首符集FIRST(α)
image
那么当要求A匹配输入串时,A就能根据它所面临的第一个输入符号a,准确地指派某一个候选前去。这个候选就是那个首符集含aα

提左因子

很多文法都存在不满足所有候选式的终结首符集不两两相交的。我们采用提取公共左因子的办法
假设关于A的规则是:

Aδβ1|δβ2|...|δβn|γ1|γ2|...|γm,(,γδ)

那么可以把这些规则改写成

AδA|γ1|γ2|...|γm

Aβ1|β2|...|βn

经过上面反复提取左因子,我们一定可以将一个非终结符的所有候选式的FIRST集两两不相交

FOLLOW集

消除左递归后的文法

ETE

E+TE|ϵ

TFT

TFT|ϵ

F(E)|i

我们对i+i进行至上而下的语法分析

image
当我们进行到这个地方的时候我们发现TTFT|ϵ+ϵ,FTϵ
可以看到当候选式有ϵ时,会对我们的分析产生困难,如何消除这个困难呢?什么时候才能用ϵ去扩展呢?
这里我们就引入了FOLLOW
image

LL(1)的分析条件

LL(1)文法

image

  1. 文法不含左递归
  2. 对文法中每一个非终结符A的各个产生式的候选终结首符集两两不相交,

Aα1|α2|...|αn

FIRST(αi)FIRST(αj)=

  1. 对文法中的每个非终结符A,若它存在某个候选首符集包含 ϵ

FIRST(A)FOLLWO(A)

对于一个LL(1)文法,我们可以对输入串进行有效的无回溯的至上而下分析,假设我们要用非终结符Aα,A的所有产生式为:

Aα1|α2|...|αn

  1. aFIRST(αi)αi匹配

  2. a不属于任何一个候选首符集,则:

    1. ϵFIRST(αi)aFOLLOW(A)Aϵ
    2. 否则a的出现是一种语法错误

构造FIRST和FOLLOW集合

构造每个文法符号的FIRST集合

对每一文法符号 XVTVNFIRST(X)
连续使用下面几条规则,直到每个FIRST集合不再增大为止

  1. XVTFIRST(X)=X
  2. XVNXa...,aFIRST(X)XϵϵFIRST(X)
  3. XYYVN,FIRST(Y)ϵFIRST(X)
    image

构造FOLLOW集合

再回顾一遍FOLLOW集合的定义:

FOLLOW(A)={a|S...Aa...,aVT}

对于文法G的每个非终结符A构造FOLLOW(A),连续使用下面的规则,直至每个FOLLOW不再增大为止

  1. 对于文法的开始符号 S,#FOLLOW(S)
  2. AαBβFIRST(β)|ϵFOLLOW(B)
  3. AαBAαBββϵ则把 FOLLOW(A)FOLLOW(B)

递归下降分析程序

递归下降分析程序

image
image
image

G(E)

ETE

E+TE|ϵ

TFT

TFT|ϵ

F(E)|i

image
image

文法的另一种表示方法和转换图

image
image

文法
ET|E+T
TF|TF
Fi|(E)
用巴克斯范式可以表示为:
ET{+T}
TF{F}
Fi|(E)

我们还可以用语法图来表示,这种图的每一个子图是一个非终结符,子图和子图之间可以相互引用
image
根据语法图和上面的巴克斯范式我们可以写出递归下降程序
image

预测分析程序

预测分析程序的工作过程

image
image
预测分析的总控程序:
image

预测分析表的构造

image
image

posted @   cxy8  阅读(197)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示