回溯的消除

回溯的消除

在自上而下分析过程中,由于回溯需要推翻前面的分析,包括已做的一大堆语义工作,重新去进行试探,这样大大降低了语法分析器的工作效率,因此,需要消除回溯。

从 4.2.1 节中我们已经发现引起回溯的原因是,在文法中某个非终结符 A 有多个候选式,遇到用 A 去匹配当前输入符号 a 时,无法确定选用唯一的一个候选式,而只能逐一进行试探,从而引起回溯,这具体表现为下面两种情况。第一种情况是相同左部的规则,其右部左端第一个符号相同而引起回溯。例 4.1 即是这种情况。第二种情况是相同左部的规则,其中某一右部能推出 ε 串,例如,文法 G :A → Bx , B → x | ε 。其非终结符 B 有两个右部,第二个右部能推导出 ε 串且两个右部左端第一个符号不相同,但在分析符号串 W = x 时出现回溯。试探分析过程如图 4.2 所示。

在这里插入图片描述
面临输入符号 x 时,用文法开始符号 A 的规则(仅一条规则)向下构造语法树,见图 4.2 (a ),其左子结点为非终结符 B ,它有两个选择,先试用 B → x 向下构造语法树,见图 4.2 ( b ),输入串 x与 B 的子结点 x 匹配,输入串指针右移,输入串已结束,但语法树中 A 的右子结点 x 未得到匹配,分析失败。回溯使输入串指针退回到 x ,对 B 选用规则 B → ε ,见图 4.2 (c ),输入符号 x 得到正确匹配,分析成功。显然,选用规则 B → ε 相当于与 B 的后继符号 x 进行匹配,这里由于 B 的后继符号 x 与 B 的第一个选择的右部左端的第一个符号 x 相同,所以面临输入符号 x 时出现回溯。

综上所述,在自上而下分析过程中,为了避免回溯,对描述语言的文法有一定的要求,即要求描述语言的文法是 LL ( 1 )文法。为了建立 LL ( 1 )文法的判断条件,需引进 3 个相关集:FIRST 集、 FOLLOW 集和 SELECT 集

(1 )设 α 是文法 G 的任一符号串,定义文法符号串 α 的首符号集合

`FIRST ( α ) = { a | α ⇒* a … 且 a∈ V T }`

若 α ⇒* ε,则规定 ε ∈FIRST ( α )。换句话说, FIRST ( α )是从 α 可推导出的所有首终结符或可能的 ε 。

(2 )设文法 G 的开始符号为 S ,对于 G 的任何非终结符 A ,定义非终结符 A 的后继符号的集合

FOLLOW ( A ) = { a | S ⇒*… Aa … 且 a ∈ V T }

若有 S ⇒*… A ,则规定 $ ∈FOLLOW (A )。换句话说 FOLLOW ( A )是 G 的所有句型中紧接在 A 之后出现的终结符或 $ 。
这里用 $ 作为输入串的结束符,例如, $ 输入串 $ 。

(3 )定义规则的选择集合 SELECT 。设 A → α 是文法 G 的任一条规则,其中 A ∈ V N ,α ∈ ( V N ∪ V T )* ,定义

SELECT ( A → α ) =FIRST ( α )		 若 α ⇒ /* ε
SELECT ( A → α ) =FIRST ( α ) \ { ε } ∪FOLLOW ( A )若 α ⇒* ε

现在,可以给出 LL ( 1 )文法的判断条件。
一个上下文无关文法 G 是 LL ( 1 )文法,当且仅当对 G 中每个非终结符 A 的任何两个不同的规则 A → α | β ,满足 SELECT ( A → α ) ∩SELECT ( A → β ) = Ø其中 α ,β 中至多只有一个能推出 ε 串。这里,LL ( 1 )中的第一个 L 表明自上而下的分析是从左到右扫描输入串,第二个 L 表明分析过程中使用最左推导,1 表示分析时每一步只需向前看一个符号即可决定所选用的规则,而且这种选择是准确无误的

回顾前面例 4.1 中的文法

S → aAb
A → de | d

不难看出

SELECT ( A → de ) =FIRST ( de ) = { d }
SELECT ( A → d ) =FIRST ( d ) = { d }

所以SELECT ( A → de ) ∩SELECT ( A → d ) ≠ Ø
由 LL ( 1 )文法定义可知,例 4.1 文法不是 LL ( 1 )文法,因此对输入串进行自上而下分析会发生回溯。

【例 4.6 】设有文法 G [ A ]:

A → aB | d
B → bBA | ε

SELECT ( A → aB ) =FIRST ( aB ) = { a }
SELECT ( A → d ) =FIRST ( d ) = { d }
SELECT ( B → bBA ) =FIRST ( bBA ) = { b }
SELECT ( B → ε ) =FOLLOW ( B ) = { a , d , $ }

所以

SELECT ( A → aB ) ∩SELECT ( A → d ) = Ø
SELECT ( B → bBA ) ∩SELECT ( B → ε ) = Ø

由定义可知,G [ A ]是 LL ( 1 )文法,对任何输入串 W 可进行无回溯的分析。

【例 4.7 】设有文法 G [ S ]:

S → aAB
A → bB | dA | ε
B → a | e

SELECT ( S → aAB ) =FIRST ( aAB ) = { a }
SELECT ( A → bB ) =FIRST ( bB ) = { b }
SELECT ( A → dA ) =FIRST ( dA ) = { d }
SELECT ( A → ε ) =FOLLOW ( A ) = { a , e }
SELECT ( B → a ) =FIRST ( a ) = { a }
SELECT ( B → e ) =FIRST ( e ) = { e }

所以

SELECT ( A → bB ) ∩SELECT ( A → dA ) = Ø
SELECT ( A → bB ) ∩SELECT ( A → ε ) = Ø
SELECT ( A → dA ) ∩SELECT ( A → ε ) = Ø
SELECT ( B → a ) ∩SELECT ( B → e ) = Ø

由定义可知,文法 G [ S ]是 LL ( 1 )文法,对任何的输入串可进行确定的自上而下分析。

综合上面的讨论可知,对 LL ( 1 )文法,若当前非终结符 A 面临输入符号 a 时,可根据 a 属于哪一个 SELECT 集,唯一地选择一条相应规则去准确地匹配输入符号 a 。也就是说,当描述语言的文法是 LL ( 1 )文法时,可对其进行确定的自上而下的分析。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值