语法分析——自顶向下分析方法

前文概述:

前阵子弄完词法分析后,这一周开始语法分析的课程。

语法分析:在计算机科学和语言学中,语法分析(英语:syntactic analysis,也叫 parsing)是根据某种给定的形式文法对由单词序列(如英语单词序列)构成的输入文本进行分析并确定其语法结构的一种过程。
(摘自维基百科)

其实学习语法分析,并不是一上来就看其算法应该怎么做,而是需要一些概念进行铺垫。

语法分析方式:

语法分析方式分为两种,一种是自顶向下分析,一种是自底向上分析。这篇博文要讲的是自顶向下分析。

自顶向下分析法:

概念1:推导方式

在推导过程中,有最左推导和最右推导。
最左推导:每次选择最左非终结符进行替换。
最右推导:每次选择最右非终结符进行替换。

而自顶向下选择的是最左推导。

概念2:回溯

回溯现象:同一个非终结符的多个候选式存在共同前缀,将导致回溯现象。
比如:A —> aBd | aCd。那么这个将会产生回溯,因为假如选了aBd这个之后,程序发现不对,那么就得重新回来,选择aCd这个,这样子是不好的,效率很低。

既然这样的话,如何消除回溯现象呢?

A —> aBd | aCd

还是以这个为例,我们可以改造成下面这个:

A —> aD
D —> Bd | Cd

也就是通过改写产生式来推迟决定,等读入了足够多的输入,获得足够信息后再做出正确的决定。

概念3:LL(k)文法:
预测分析:

预测分析是递归下降分析技术的一个特例,通过在输入中向前看固定个数(通常为1)符号来选择正确的产生式。

LL(k)文法:

可以对某些文法构造出向前看k个输入符号的预测分析。

文法转换:

并不是所有的文法都适用于自顶向下的分析,我们有时候需要对文法进行改造,使之适合。

概念4:左递归

如果一个文法中有一个非终结符A使得对某个字符串a存在一个推导:A —> *Aa,那么这个文法就是左递归的。
如:

A —> Aa
E —> E + T | E - T

左递归分为两种:

直接左递归:

如:

A —> Aa | b
E —> E + T | E - T

A和E都可以直接推出A和E。

那么如何消除左递归呢?
如A —> Aa | b
则其r = ba*。
令 A —> bC, C —> aC | e。(这里e代表空字符串)。

间接左递归:

如:

S —> Aa | b
A —> Ac | Sd | e (这里e代表空字符串,下同)

上面那个可以推出:
S —> Aa —> Sda,即经过两步及两步以上推出了左递归。
那么如何消除呢?
还是以上面为例:
将S的定义代入A的产生式得:
A —> Ac | Aad | bd | e
消除A的直接左递归:
A —> bd | C
C —> cC | adC | e

LL(1)文法:

在了解LL(1)文法之前,我们需要来了解一下以下几个概念:

FIRST(X)集:

可以从X推导出的所有串首终结符构成的集合,如果式空串e,也要加入。
如:A —> bd | C C —> cC | adC | e
那么FIRST(A) = {b, c, a, e}。
这个应该不是很难理解?那就过了。

FOLLOW(A)集:

可能在某个句型中紧跟在A后面的终结符a的集合。如果A是某个句型的最右符号,则将结束符“#"添加到FOLLOW(A)中。
如何求解:
①设S为文法中开始符号,把{#}加入FOLLOW(S)中(这里“#” 为句子括号)。
②若A→αBβ是一个产生式,则把FIRST(β)的非空元素加入FOLLOW(B)中。如果β能够推导出ε则把FOLLOW(A)也加入FOLLOW(B)中。
③反复使用②直到每个非终结符的FOLLOW集不再增大为止。

例子可以看一下这篇文章

SELECT(A —> b):产生式的可选集

产生式 A —> b的可选集是指可以选用该产生式进行推导时对应的输入符号的集合,记为SELECT(A —> b)。
例如:
SELECT(A —> aB) = {a}.
SELECT(A —> e) = FOLLOW(A).

LL(1) 文法:

当同个非终结符推出的SELECT集不相交时,则是LL(1)文法。
如SELECT(A —> aB) = {a}. SELECT(A —> e) = FOLLOW(A).演示a和FOLLOW不相交的话,那么A —> aB,A —> e构成的文法就是LL(1)文法。

LL(1) 文法分析方法:
递归的预测分析法:

在递归下降分析中,编写没有给非终结符对应的过程时,根据预测分析表进行产生式的选择。

非递归的预测分析法:

不需要为每一个非终结符编写递归下降过程,而是根据预测分析表构造一个自动机,也叫驱动的预测分析。

一般写语法分析器代码就是依照上面其中一中方法来。

总结:

上面讲的其实是一个大概,其中的细节并没有深挖,推荐这个教程,老师讲的很不错。看了几遍应该就可以了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值