习题第5章自顶向下语法分析方法
第5章-自顶向下语法分析方法
语法分析的主要工作: 是识别由词法分析给出的单词序列是否是给定的
正确句子(程序)。
பைடு நூலகம்语法分析常用的方法: 自顶向下的语法分析和自底向上的语法分析两大
类。
自顶向下分析思想
自顶向下的方法: 从文法的开始符号(设为〈程序〉)开始进行分析,
逐步推导的往下构造语法树,使其树叶正好构造出所给 定的源程序串(输入串)。
例5.1若有文法G[S]:
S → pA S → qB
A → cAd A→a
若有输入串w = pccadd.
考察自顶向下的推导过程。
解:推导过程为:
S pA pcAd pccAdd pccadd 其相应的语法树见右图:
S pA
cAd c Ad
a
这个文法的特点:
[1]每个产生式的右部都由终结符号开始。 [2]如果两个产生有相同的左部,那么它们的右部由不同的终 结符开始。
FOLLOW(A)的元素。
因此当文法中含有形如: A→α和 A→β的产生式时,其中 A∈VN ,α,β∈V*,当α和β不同时推导出空串时,设α * ε,β\ * ε, 则当FIRST(α) ∩(FIRST(β)∪FOLLOW(A))=φ时,对于非终结符 A的替代仍可唯一地确定候选。
定义5.3:
定义选择符集合SELECT如下: 对于给出上下文无关文法的产生式
自顶向下方法的关键: 是在推导过程中确定的选择候选式的问题。
自顶向下的主要思想: 从开始符出发导出句型并一个符号一个符号地与
给定输入串 (终结符串)进行匹配。如果全部匹配成功, 则表示开始符号可推导出给定的终结符串。因此判定 给定终结符号串是正确句子。
自顶向下的缺点:
软件工程 编译原理 第五章 自顶向下的语法分析方法
P→1P | 2P |… | mP |
(2)消除间接左递归
对于间接左递归的消除需先将间接左递归变为直接左 递归,然后再按a)消除直接左递归。
例:文法G为例: (1) A→aB (2) A→Bb (3) B→Ac (4) B→d 用产生式(1)、(2)的右部 代替产生式(3)中的非终 结符A得到左部为B的产 生式为: (1) B→aBc (2) BG的产生式为: (1) S→aSb (2) S→aS (3) S→ε 请提取文法中的左公因子
对产生式(1)、(2)提取左公因子后得: S→ aS(b|ε) S→ε 进一步变换为文法G′: S→aSA A→b A→ε S→ε
例2:若文法G的产生式为: (1) A→ad (2) A→Bc (3) B→aA (4) B→bB 请提取文法中的隐式左公因子。 对文法G2分别用(3)、(4)的右 部替换(2)中的B,可得: 提取产生式(1)、(2)的左 (1) A→ad 公共因子得: (2) A→aAc A→a(d|Ac) (3) A→bBc A→bBc (4) B→aA B→aA (5) B→bB B→bB
由上面所举例子可以说明以下问题:
① 不一定每个文法的左公共因子都能在有限的步骤内 替换成无左公共因子的文法,上面文法G4就是如此。 ② 一个文法提取了左公共因子后,只解决了相同左部 产生式右部的FIRST集不相交问题,当改写后的文法 不含空产生式,且无左递归时,则改写后的文法是 LL(1)文法,否则还需用LL(1)文法的判别方式进行判 断才能确定是否为LL(1)文法。
例:文法G(E):
E→TE E→+TE | T→FT T→*FT | F→(E) | i
每个非终结符有对应的子程序的定义, 首先在分析过程中,当需要从某个非终 结符出发进行展开(推导)时,就调用这 个非终结符对应的子程序。
《编译原理》课后习题答案第5章
《编译原理》课后习题答案第5章《编译原理》课后习题答案第5章.pdf《编译原理》课后习题答案第5章.pdf第5章自顶向下语法分析方法第1题对文法G[S] S→a|∧|(T) T→T,S|S(1) 给出(a,(a,a))和(((a,a),∧,(a)),a)的最左推导。
(2) 对文法G,进行改写,然后对每个非终结符写出不带回溯的递归子程序。
(3) 经改写后的文法是否是LL(1)的?给出它的预测分析表。
(4) 给出输入串(a,a)#的分析过程,并说明该串是否为G的句子。
答案:(1) 对(a,(a,a)的最左推导为:S(T) (T,S) (S,S) (a,S) (a,(T)) (a,(T,S)) (a,(S,S)) (a,(a,S)) (a,(a,a))对(((a,a),∧,(a)),a) 的最左推导为:S(T) (T,S) (S,S) ((T),S) ((T,S),S) ((T,S,S),S) ((S,S,S),S) (((T),S,S),S) (((T,S),S,S),S) (((S,S),S,S),S) (((a,S),S,S),S) (((a,a),S,S),S) (((a,a),∧,S),S) (((a,a),∧,(T)),S)(((a,a),∧,(S)),S)《编译原理》课后习题答案第5章.pdf《编译原理》课后习题答案第5章.pdf(((a,a),∧,(a)),S) (((a,a),∧,(a)),a)(2) 改写文法为:0) S→a 1) S→∧ 2) S→( T ) 3) T→S N 4) N→, S N 5) N→ε非终结符FIRST集FOLLOW集S {a,∧,(} {#,,,)} T {a,∧,(} {)} N {,,ε} {)}对左部为N的产生式可知:FIRST (→, S N)={,} FIRST (→ε)={ε} FOLLOW (N)={)}由于SELECT(N →, S N)∩SELECT(N →ε) ={,}∩ { )}= 所以文法是LL(1)的。
第11课 第5章_自顶向下语法分析方法_思想
FIRST(A)就是A开头的终结符, 直观的说就是A的开头字母 注意:First集合不仅仅针对非终 结符。 Nullable:可致空的
6
例子
S aA | d A bAS |
S aA abAS abS abd
?
7
Follow集
c | S A , 且c FIRST ( ), FOLLOW ( A) VT , V , A VN
3
确定分析的思想
S→pA|qB A→cAd|a B→dB|b 试分析串 pccadd
文法
S
pA pccadd
pcAd
pccAdd
4
例子
S→Ap,S →Bq, A →a,A →cA B →b,B →dB 分析串ccap有如下结论:
S
Ap
cAp
ccAp
ccap
5
开始符号集
FIRST ( A) c | A cB, c VT , A, B V
10
定理
一个CFG是LL(1)的充要条件是: 对每个非终结符A的不同产生式,满 足: Select A Select A
11
程序中错误的级别
lexical,譬如拼错了关键字 syntactic,譬如括号没有成对 semantic,譬如操作数与操作符不匹配 logical,譬如无限的递归调用
12
引用的统计数据
60%的程序在语法和语义上是正确的 存在错误的语句,有80%只有一个错误, 13%有两个 大部分错误都是极小的错误
13
第5章自顶向下语法分析方法
程序设计语言的语法结构是用上下文无 关文法描述的,因此,语法分析器的实 现原理就是按所给定的文法G,识别输入 符号串α是否为一个句子(即α∈L(G) 成立吗?),同时检查和处理语法错误。 语法分析的关键是句型识别问题。给定 一串单词(即文法的终结符),怎样知 道它是不是该文法产生的一个句子呢? 可以利用推导,或者利用语法树来进行 判断。一般来说,语法分析的过程就是 为一个句子建立语法树的过程。
(S,a)
(A,c)
S→aAB
aca#
3 acAB
4 acε B 5 aca
A→cA
A→ ε B→a
aca#
aca# aca#
(A,a)
(B,a) 推导成功
以上最左推导所建立输入串aca的语法树如图所 示。
S
a c A B A ε a
讨论
考查以上推导,在第3步到第4步的推导中, 即acABacB时,因为当前要替换的最左非终结 符为A,面临输入符为a,而关于A的产生式右部 的首终结符集都不包含a,但有ε,因此对于a 的匹配自然认为只能依赖于在可能的推导过程 中A的后面的符号,所以这时选用产生式A→ε 往下推导,而当前A后面的符号为B,B的产生式 右部的首终结符集包含了a,所以可匹配。由此 可以看出,当前输入符a与A后面的非终结符B匹 配。
文法的特点
文法G2有以下两个特点:
(1)每个产生式的右部都由终结符号开始;
(2)如果两个产生式有相同的左部,那么它们 的右部由不同的终结符开始。 对于这样的文法显然在推导过程中完全 可以根据当前要替换的非终结符和输入符 号决定选择哪个产生式往下推导,因此分 析过程是唯一确定的。
示例二
【例4.3】若有文法G3[S]为: S→Aa S→Bb A→c A→dA B→e B→fB
(完整版)编译原理第五章作业参考答案
SELECT(F PF/ )=FIRST(P)={(,a,b,^};
SELECT(F/ *F /)={*}; SELECT(F/ ε )=FOLLOW(F/)={(,a,b,^,+,),#};
SELECT(P (E))={(}
SELECT(P a)={a}
SELECT(P b)={b}
SELECT(P ^)={^} 可见,相同左部产生式的
if(CH== ’ aR’E)AD(CH);// 产生式 S a else if(CH== ’ ^ ’ ) READ(C产H)生;//式 S ^ else if(CH== ’产( ’生)式// S (T) {
READ(CH); P_T(); IF (CH= =’ ) ’TH)EN READ(CH) else ERROR } else ERR; } void P_T()// 非终结符 S 的子程序 { if(IsIn(CH,FIRST_SU)) //FIRST_SU 为 T SU 的右部的 FIRST 集合 { P_S(); P_U(); } } void P_U()// 非终结符 U 的子程序 { if(CH== ’ , ’产生)//式 U , SU
3.已知文法 G[S] :
S MH|a
H LSo| ε K dML|ε
L eHf
M K|bLM 判断 G是否是 LL( 1)文法,如果是,构造 LL( 1)分析表。 解: 首先求各非终结符的 FIRST 集合:
FIRST 集合有:
FIRST(E)=FIRST(T)=FIRST(F)=FIRST(P)={(,a,b,^}; FIRST(E / )={+, ε }
FIRST(T)=FIRST(F)=FIRST(P)={(,a,b,^}; FIRST(T / )=FIRST(T) ∪ { ε }={(,a,b,^, ε };
自顶向下语法分析方法
7
PL/0语言文法的EBNF表示
PL/0语言文法的EBNF表示 <程序>∷=<分程序>. <分程序>∷=[<常量说明部分>][<变量说明部分>][<过程说明部分>]<语句> <常量说明部分>∷=CONST<常量定义部分>{,<常量定义>}; <无符号整数>∷=<数字>{<数字>} <变量说明部分>∷=VAR<标识符>{,<标识符>}; <标识符>∷=<字母>{<字母>|<数字>} <过程说明部分>∷=<过程首部><分程序>{;<过程说明部分>}; <过程首部>∷=PROCEDURE <标识符>; <语句>∷=<赋值语句>|<条件语句>|<当型循环语句>|<过程调用语句>| <读语句>|<写语句>|<复合语句>|<空> <赋值语句>∷=<标识符>:=<表达式> <复合语句>∷=BEGIN <语句>{;<语句>} END <条件>∷=<表达式><关系运算符><表达式>|ODD<表达式>
例如对文法G3[S]: S→aAS|b A→bA| SELECT(S→aAS)={a} SELECT(S→b)={b} SELECT(A→bA)={b} SELECT(A→)={a,b}
第5章自顶向下语法分析方法
(A,b)
(B,a) (B,d) 推导成功
注意:#是输入结束符
以上最左推导所建立输入串acbad的语法树如图 所示。
S
a c b A B A B d
a
选择产生式是唯一的
在第 2 步推导时,当前要替换的非终结 符为 A ,面临的输入符为 c ,所以选择 A 的产生式来推导时,只能选产生式 A→cA,而不能选A→bB。同样,在第 5 步推导时,当前要替换的非终结符为 B , 面临的输入符为d,所以选择B的产生式 来推导时,只能选产生式B→d,而不能 选B→a。这样就保证上述每一步推导都 是确定的。
文法的特点
文法G2有以下两个特点:
(1)每个产生式的右部都由终结符号开始;
(2)如果两个产生式有相同的左部,那么它们 的右部由不同的终结符开始。 对于这样的文法显然在推导过程中完全 可以根据当前要替换的非终结符和输入符 号决定选择哪个产生式往下推导,因此分 析过程是唯一确定的。
示例二
【例4.3】若有文法G3[S]为: S→Aa S→Bb A→c A→dA B→e B→fB
不确定的语法分析方法――带回溯的自顶向下 分析法――实际上是一种穷举的试探方法,当 分析不成功时则推翻以前的分析退回到适当位 置再重新试探其余候选式可能的推导,这样需 要记录已选过的产生式,直到把所有可能的推 导序列都试完仍不成功才能确认输入串不是该 文法的句子而报错。由于在编译程序真正实现 时往往是边分析边插入语义动作,因而带回溯 的语法分析方法代价很高,效率很低,在实用 编译程序中几乎不用,因此对它实现的详细算 法不做介绍。
(S,a)
(A,c)
S→aAB
aca#
3 acAB
4 acε B 5 aca
第5章 自顶向下语法分析方法
构造集合FOLLOW的算法
(2)若B→A , /
,则把FIRST()-{}加入FOLLOW(A)中;
由C→AD可知, a,c∈FOLLOW(A)
(3)若B→A 或B→A,且
,
则把FOLLOW(B)加入FOLLOW(A) 中。
由S→bC,应把FOLLOW(S)加入∈FOLLOW(C) 由S→AB 且B ε,应把FOLLOW(S)加入FOLLOW(A)
FIRST(B) ={a,ε} FIRST(C)={a,b,c} FIRST(D)={a,c}
FOLLOW (A)={a,#,c}
FOLLOW (B) ={#} FOLLOW (C)={#} FOLLOW (D)={#}
【例5.9】 G[S] S→AB∣bC A→ ∣b B→ ∣aD C→AD∣b D→aS∣c
求SELECT
SELECT(S →AB)∩ SELECT(S →bC) ={b, a, #} ∩{b} ≠ф SELECT(A→)∩ SELECT(A →b) ={c, a, #} ∩{b} =ф SELECT(B→)∩ SELECT(B →aD) ={#} ∩{a} =ф SELECT(C →AD)∩ SELECT(C →b) ={b, a, c} ∩{b} ≠ф SELECT(D →aS)∩ SELECT(D→c) ={a} ∩{c} =ф
因为当试图用S或E的右部区匹配输入串时会发现,在没有读 入 任何输入符号的情况下,又要求用S或E的右部去进行新的匹配 【例5.3】 试建立输入串baa的最左推导 S→Sa S⇒Sa⇒Saa⇒baa S→b 【例5.4】 试建立输入串i+i+i的最左推导 E→E+T|T E⇒E+T⇒E+T+T⇒E+T+T+T⇒ T→T*F|F … F→(E)|i
(完整版)编译原理第五章作业参考答案
第五章自顶向下语法分析方法1.对文法G[S]S→a|∧|(T)T→T,S|S(1)给出(a,(a,a))和(((a,a),∧,(a)),a)的最左推导。
(2)对文法G,进行改写,然后对每个非终结符写出不带回溯的递归子程序。
(3)经改写后的文法是否是LL(1)的?给出它的预测分析表。
(4)给出输入串(a,a)#的分析过程,并说明该串是否为G的句子。
解:(1) (a,(a,a))的最左推导为S→(T)→(T,S)→(S,S)→(a,(T))→(a,(T,S))→(a,(S,a))→(a,(a,a))(((a,a),∧,(a)),a)的最左推导为S→(T)→(T,S)→(S,a)→((T),a)→((T,S),a)→((T,S,S),a)→((S,∧,(T)),a)→(((T),∧,(S)),a) →(((T,S),∧,(a)),a)→(((S,a),∧,(a)),a)→(((a,a),∧,(a)),a)(2)由于有T→T,S的产生式,所以消除该产生式的左递归,增中一个非终结符U有新的文法G/[S]:S→a|∧|(T)T→SUU→,SU|ε分析子程序的构造方法对满足条件的文法按如下方法构造相应的语法分析子程序。
(1) 对于每个非终结号U,编写一个相应的子程序P(U);(2) 对于规则U::=x1|x2|..|xn,有一个关于U的子程序P(U),P(U)按如下方法构造:IF CH IN FIRST(x1) THEN P(x1)ELSE IF CH IN FIRST(x2) THEN P(x2)ELSE ......IF CH IN FIRST(xn) THEN P(xn)ELSE ERROR其中,CH存放当前的输入符号,是一个全程变量;ERROR是一段处理出错信息的程序;P(xj)为相应的子程序。
(3) 对于符号串x=y1y2...yn;p(x)的含义为:BEGINP(y1);P(y2);...P(yn);END如果yi是非终结符,则P(yi)代表调用处理yi的子程序;如果yi是终结符,则P(yi)为形如下述语句的一段子程序IF CH=yi THEN READ(CH) ELSE ERROR即如果当前文法中的符号与输入符号匹配,则继续读入下一个待输入符号到CH中,否则表明出错。
第5自顶向下的语法分析方法
自顶向下分析法也就是从文法的开始符号出 发企图推导出与输入的单词串完全相匹配的 句子,若输入串是给定文法的句子,则必能 推出,反之必然出错。
句型分析的有关问题 ① 如何选择使用哪个产生式进行推导? 假定要被替换的最左非终结符号是V,且左部为V的规则有n条:
V→A1|A2|…|An,那么如何确定用哪个右部去替换V呢? ② 如何识别可归约的串? 在自下而上的分析方法中,在分析程序工作的每一步,都是从
LL(1) 文法的定义
定义5.4 一个上下文无关文法是LL(1)文 法的充分必要条件是:对每个非终结符A 的两个不同产生式,A→α, A→β,满足 SELECT(A→α)∩SELECT(A→β)=∅ 其中α,β不同时能 ε
LL(1)文法的含义:
第一个L 从左到右扫描输入串
第二个L 生成的是最左推导
该文法的特点是:
关于A的产生式的不同右部开始符号集合都含有a,因此要替 换非终结符A时,对当前输入符为a的情况,不能确定用产生式 A→ab 的右部还是用A→a的右部去替换。所以导致必须用带回溯 的自顶向下分析,
这是一个不确定的分析
文法含有左递归,可见一个文法含有左递归时不能用确定的自顶向 下分析
若有S …A,则规定#∈FOLLOW(A) 这里我们用'#'作为输入串的结束符,或称为句子括号,如:#输
入串#。
因此当文法中含有形如:
A→α
A→β 的产生式时,其中A∈VN,α,β∈V*,当α,β不同时推导出空时, 设α ε,β ε,则当FIRST(α)∩( FIRST(β)∪FOLLOW(A))= 时,对 于非终结符A的替换仍可唯一地确定候选。
当前串中寻找一个子串,看它是否能归约到文法的某个非终结符号, 该子串称为“可归约串”。
自顶向下语法分析方法
因此,该文法不是LL(1)文法,因而也就不 可以采用确定的自顶向下分析方法。
22
教学总结
语法分析是编译过程中不可缺少的重要阶段,其 主要功能是对词法分析生成的单词流进行分析,识别 各种语法成分。 语法分析方法有自顶向下和自底向 上两种,有自顶向下分析法又有确定和不确定两种。 一个上下文无关文法是LL(1)文法的充分必要条 件是对每个非终结符A的两个不同产生式: A,Aβ满足Select(A)∩Select(Aβ)=,其 中、β不同时 。 LL(1)文法可以采用自顶向下分析方法。
教学重点:
1.LL(1)文法的定义; 2.求first集合、follow集合与select集合
教学难点 :
求first集合、follow集合与select集合
教学课时:2 教学方法:多媒体教学 教学内容和步骤 :(如下) 3
第4章我们学习词法分析,介绍词法分析 的工具(主要讲正规文法)和方法(DFA和 NFA)。 本章介绍语法分析:在词法分析的基础上, 分析句子是否正确。
33
3. 计算Follow 集: 方法一:根据定义计算 算法如下: (1)设S为开始符号,则#follow(S); (2)若A→αBβ是一个产生式,则把FIRST(β )或 {}加至FOLLOW(B)中; (3)若A→αB是一个产生式,或A→αBβ是一个产 * 生式而β (即FIRST(β )),则把 FOLLOW(A)加至FOLLOW(B)中. 即:Follow(A)是所有句型中出现在紧接A之后 的终结符或“#”。
(#表示输入串的结束符,或句子括号)
13
也可以定义为:
* …Aa…, a∈V } Follow(A)={a|S T * …A,则#∈Follow(A)。 若S
#编译原理第五章自顶向下语法分析方法
第五章自顶向下语法分析方法课前索引【课前思考】为了了解自顶向下<自上而下)分析的一般过程和问题,请学员首先回顾在"文法和语言"一章中介绍的有关基本概念:◇句子、句型和语言的定义是什么?◇什么叫最左推导?◇什么叫最右推导和规范推导?◇什么叫确定的自顶向下语法分析?◇自顶向下语法分析是从文法的开始符号出发,反复使用各种产生式,寻找与输入符号匹配的推导。
◇确定的自顶向下语法分析中用的是哪种推导?◇在确定的自顶向下语法分析过程中,当以同一个非终结符为左部的产生式有多个不同右部时,如何选择用哪个产生式的右部替换当前的非终结符?◇确定的自顶向下语法分析对文法有何限制?【学习目标】确定的自顶向下分析方法虽对文法有一定的限制,但因为实现方法简单、直观,便于手工构造或自动生成语法分析器,因而仍是目前常用的方法之一。
要求学员通过本章的学习后达到以下要求:◇能够对一个给定的文法判断是否是LL(1>文法;◇能构造预测分析表;◇能用预测分析方法判断给定的输入符号串是否是该文法的句子;◇能对某些非LL(1>文法做等价变换:①消除左递归②提取左公共因子可能会变成LL(1>文法。
这样可扩大自顶向下分析方法的应用。
【学习指南】确定的自顶向下分析因为实现方法简单、直观、便于手工构造,因此,仍是目前常用的语法分析方法之一,尤其对小型编译器的实现较为适合。
对初学编译技术的学员也较容易入门。
确定的自顶向下分析要求文法是LL(1>的,所以,能否用确定的自顶向下分析方法构造语法分析器,首先必须对所给文法进行判断。
由此构造LL(1> 分析器的关键问题是对文法的LL(1>判别。
而判断LL(1>文法时用到文法符号串的开始符号集合<FIRST集)和非终结符的后跟符号集合<FOLLOW集)的计算。
本章的学习要求学员对给定的文法能熟练、准确地计算出产生式右部符号串的开始符号集合和每个非终结符的后跟符号集合,只有这两个集合的元素计算准确无误,才能对LL(1>文法的判断得出正确结论,从而正确构造LL(1>分析表。
第五章自顶向下语法分析方法
第五章⾃顶向下语法分析⽅法第五章⾃顶向下语法分析⽅法教学要求1.掌握:计算FIRST集、FOLLOW集、SELECT集,LL(1)⽂法的概念2.理解:不确定/确定的⾃顶向下分析法3.了解:该分析⽅法的基本思想5.1 确定的⾃顶向下分析思想确定的⾃顶向下分析⽅法,⾸先要解决从⽂法的开始符号出发,如何根据当前的输⼊符号唯⼀地确定选⽤哪个产⽣式替换相应⾮终结符往下推导,或构造⼀颗相应的语法树。
1:⾸符号集:设G=(VN,VT,P,S)是上下⽂⽆关⽂法 :FIRST(α)={a|α=>aβ,a∈VT, α, β∈V*} 若α=>ε则规定ε∈FRIST(α)2:后继符号集:FOLLOW(A)={a |S =>µAβ且 a∈FRIST(β),µ∈V*,β∈V+ }若S =>µAβ ,且β=>ε,则#∈FOLLOW(A)3:选择集合SELECT:给定上下⽂⽆关⽂法的产⽣式A→αA ∈VN, α∈V* ,若α≠>ε,则:SELECT(A→α)=FIRST(α)如果α=>ε,则:SELECT(A→α)=FIRST(α)-{ε}∪FOLLOW(A)4:LL(1)⽂法:⼀个上下⽂⽆关⽂法是LL(1)⽂法的充分必要条件是,对每个⾮终结符A的两个不同产⽣式,A→α或A→β满⾜SELECT(A→α)∩SELECT(A→β)= φ其中,α、β不能同时=>ε注意:第⼀个L表明⾃顶向下分析是从左到右扫描输⼊串,第⼆个L表明分析过程中将⽤最左推导,1表明只需向右看⼀个字符便可决定如何推导即选择哪个产⽣式。
5.2 LL(1)⽂法的判别判别⽂法是否是LL(1)⽂法,对任何⽂法计算需计算FIRST、FOLLOW和SELECT集合,进⽽判别⽂法是否为LL(1)⽂法。
举例说明判断LL(1)⽂法的步骤。
1.计算FIRST集1).若X∈V T,则FIRST(X)={X}2).若X∈VN,且有产⽣式X→a…,a是终结符,则把a加⼊到FIRST(X)中;若X→ε也是⼀条产⽣式,则把ε也加到FIRST(X)中. 3).若X→Y…是⼀个产⽣式且Y∈VN,则把FIRST(Y)中的所有⾮ε元素都加到FIRST(X)中;若X →Y1Y2…YK 是⼀个产⽣式,Y1,Y2,…,Y(i-1)都是⾮终结符,⽽且,对于任何j,1≤j ≤i-1, FIRST(Yj)都含有ε (即Y1..Y(i-1) =>* ε ),则把FIRST(Yj)中的所有⾮ε元素都加到FIRST(X)中;特别是,若所有的FIRST(Yj , j=1,2,…,K)均含有ε,则把ε加到FRIST(X)中.4)反复使⽤1)~3)直到每个符号的FIRST集不再增⼤为⽌FIRST集的求法有两种:⼀是根据定义,⼆是⽤关系图求得。
第五章 自顶向下语法分析方法
情况3
文法的特点是:文法中含有空产生式。 文法G3[S]: S → aA|d A → bAS|ε 识别串w=abd是否是G3[S]的句子
设 G=(VT,VN,S,P)是上下文无关 文 法,A∈VN,S是开始符号 * FOLLOW(A)={a|S μAβ,且 a∈VT,a∈FIRST(β),μ∈VT* ,β∈V+} * * 若S μAβ,且β ε, 则#∈FOLLOW(A)。 也可定义为: FOLLOW(A)={a|S …Aa…,a ∈VT} * * 若有S …A,则规定#∈FOLLOW(A) '#'作为输入串的结束符
例
文法G5[S]为:S→aAS|b A→bA|ε SELECT(S→aAS)={a} SELECT(S→b)={b} SELECT(A→bA)={b} SELECT(A→ε)={a,b} 所以 SELECT(S→aAS)∩SELECT(S→b)={a}∩{ b}= φ SELECT(A→bA)∩SELECT(A→ε)={b}∩{a ,b}≠ φ 不是LL(1)文法,因而也就不可能用确定的自顶 向下分析
FIRST ( ) ( FIRST ( x j { })) FIRST ( xi )
j 1
i 1
当所有FIRST(Xj)(1≤j≤n)都含有{ε}时,
FIRST ( )
FIRST ( x ){ }
j j 1
n
文法G7[S]为: S→AB S→bC B→ε B→aD D→aS D→c
A→ε A→b C→AD C→b
FIRST(S)={FIRST(A)\{ε}}∪{FIRST(B)\ {ε}} ∪{ε}∪{b}={b,a,ε} FIRST(A)={b}∪{ε}={ b,ε} FIRST(B)={ε}∪{a}={a,ε} FIRST(C)={FIRST(A)\{ε}}∪FIRST(D)∪ FIRST (b)={b,a,c} FIRST(D)={a}∪{c}={a,c} FIRST(S)={a,b,ε} FIRST(A)={b,ε} FIRST(B)={a,ε} FIRST(C)={a,b,c} FIRST(D)={a,c}
第5章 自顶向下语法分析方法3
③
结论 : 在推导过程中完全可以根据向前看符号 是属于哪个产生式右部的开始符号集合而决定选 择相应的产生式进行推导,因此,分析过程是完 全确定的。
FIRST定义:设 G = (VT ,VN , S , P) 是2型文法, * FIRST(α) = {a|α aβ,a∈ VT,α,β ∈ V*} * 若α ε,则规定ε∈FIRST(α) 直观定义理解: FIRST(α)={a|α *a … … ,a∈VT } FIRST(α)包含了α对应的串的所有可能的首终结 符号集(选择产生式的依据)
① 若XV,则FIRST(X)={X} ② 若XVN,且有产生式Xa…,则a∈FIRST(X);
若X也是一条产生式,则∈FIRST(X). ③ 若XY…是一个产生式且YVN,则把FIRST(Y)中的 所有非元素都加到FIRST(X)中; 若X Y1Y2…YK 是一个产生式,Y1,Y2,…,Y(k-1)都 是非终结符,而且,对于任何j,1≤j ≤k-1,FIRST(Yj)都 含有(即Y1..Y(k-1) * ),则把FIRST(Yj)中的所有 非元素与FIRST(Yk)都加到FIRST(X)中; 特别是,若所有的FIRST(Yj, j=1,2,…,K)均含有,则 把加到FIRST(X)中. (注意第3点)
③ A→αβ1|αβ2|…|αβn 变换为
语法分析的任务
语法分析是编译过程的核心部分。 2. 语法分析的作用:识别由词法分析输出的单词序列是否 符合该语言的文法(?)正确句子(程序)。 3. 分析方法 ① 自顶向下分析法(确定与不确定 ) 从推导的角度看,从识别符号出发,试图推导出与输入 符号串相同的符号串。一般来讲,推导是最左推导。 构造推导的关键问题: 在构造最左推导的过程中,面对当前读入的单词符号(向 前看符号)和当前被替换的非终结符两者,应该选择这个 非终结符的哪条候选式去替换它(推导)。 ② 自底向上分析法(算符优先、LR分析器)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
习题第5章自顶向下语法分析方法一课本练习部分(第99-101页)5.15.45.6(2)(3)(4)5.7(1)(3)(5)参考答案:5.1(1)S =>(T)=>(T,S) =>(S,S) =>(a,S) =>(a,(T)) =>(a,(T,S)) =>(a,(S,S)) => (a,(a,S)) => (a,(a,a))S => (T) => (T,S) => (S,S) => ((T),S) => ((T,S),S) => ((T,S,S),S) =>((S,S,S),S) => (((T),S,S),S) => (((T,S),S,S),S)=> (((S,S),S,S),S) => (((a,S),S,S),S) => (((a,a),S,S),S)=>(((a,a), ∧,S),S) =>(((a,a), ∧,(T)),S) =>(((a,a), ∧,(S)),S) => (((a,a), ∧,(a)),S) => (((a,a), ∧,(a)),a)(2)改写文法如下:S→a|∧|(T)T→ST’T’→,ST’|ε递归子程序为:S() {if(SYM==’a’)P(a);else if(SYM==’∧’)P(∧);else if(SYM==’( ’) {GetSym();P(T);match(’) ’);}else Error();}T() {P(S);P(T’);}T’() {if(SYM==",") {match(",");???P(S);P(T');}else if(SYM==(")")return;else error();}(3)FIRST(S)={a∧(} FOLLOW(S)={#,)}FIRST(T)={a∧(} FOLLOW(T)={)}FIRST(T')={,} FOLLOW(T')={)}SELECT(S→a)={a}SELECT(S→∧)={∧}SELECT(S→(T))={(}SELECT(T→ST')={ a∧(}SELECT(T'→,ST')={,}SELECT(T'→ε}={)}由于相同左部的SELECT集的交集为空,所以所改写的文法是LL(1)的。
写出该文法的预测分析表:或者4.证明:FT(S)={a,b};FT(C)={a,b};FT(A)={a,b};FT(B)={a,b};FW(S)={#};FW(C)={$,a,b};FW(A)={$,a,b};FW(B)={$,a,b};ST(C->Ba)={b};ST(C->aB)={a};ST(A->a)={a};ST(A->aC)={a};ST(A->Abb)={b};ST(B->b)={b};ST(B->bC)={b};ST(B->aBB)={a};由于:ST(A->a)={a}∩ST(A->aC)={a}≠¢ST(B->b)={b}∩ST(B->bC)={b}≠¢所以为非LL(1) 文法。
若通过提取公共左因子来改写文法为:S->C$C->bA|aBA->aD|bAAB->bD|aBBD->C|ε由于左部为D的规则式的选择集相交:ST(D->C)={a,b};ST(D->ε)={a,b,$};故也不是LL(1)文法。
5.6(2)B有相同左因子,所以该文法不是LL(1)的。
先将A的规则代入S的规则: S→BaB|B提左因子B,得 S→B(aB|ε)引入非终结符E及其规则得: S→BEE→aB|ε再将D的规则代入B的规则: B→db|b|d|ε提左因子d得: B→d(b|ε)|b|ε引入非终结符F及其规则得: B→dF|b|εF→b|ε故文法变换为: S→BEB→dF|b|εE→aB|εF→b|ε由于 SELECT(B→ε)={a,#}SELECT(E→ε)={#}SELECT(F→ε)={a,#}故B,E和F的各自规则两两不相交,变换后的文法是LL(1)文法。
递归下降子程序此略。
注意:若直接提取左因子D: B→D(b|ε)并改写为 B→DHH→b|ε则文法改写为:S→ABA→Ba|εB→DEE→b|εD→d|ε但因为SELECT(A→Ba)⋂ SELECT(A→ε)≠¢故此,仅直接提取左因子,文法仍不是LL(1)的。
(3)SELECT集为:ST(S->aAaB)={a}ST(S->bAbB)={b}ST(A->S)=first(S)={a b}ST(A->db)={d}ST(B->bB)={b}ST(B->a)={a}因相同左部产生式的SELECT集不相交,所以为LL(1)文法。
递归下降子程序为:S(){if(SYM==a){GetSym();P(A);match(a);P(B);}else if(SYM==b){GetSym();P(A);match(b);P(b);} }A(){if(SYM==d){GetSym();match(b);}else P(S);}B(){if(SYM==b){GetSym();P(B);}else if(SYM==a) GetSym();}(4)因为文法具有左递归,所以不是LL(1)的。
改写该文法:S→i|(E)E→SE'E'→+SE'|-SE'|ε计算SELECT集:SELECT(S→i)={i}SELECT(S→(E))={(}SELECT(E→SE')={i(}SELECT(E'→+SE')={+}SELECT(E'→-SE')={-}SELECT(E'→ε)={)}由此可以看出此文法是LL(1)的。
构造相应的递归下降识别器:P(S) {if(SYM==i)match(i);else if(SYM=="(") {match("(");P(E);match(")");}}P(E) {P(S);P(E');}P(E') {if(SYM=="+") {match(+);P(S);P(E');} else if(SYM=="-") {match(-);P(S);P(E');}else if(SYM==")")returnelse error();}7.消除了左递归,提取了左公因子并不一定是LL(1)的。
(1)改写文法得:A→baB|εB→baBbb|bb|a消除公共左因子得:A→baB|εB→bB'|aB'→aBbb|b求其First集和Follow集:计算SELECT(A→baB)={b}SELECT(A→ε}={#}SELECT(B→bB'}={b}SELECT(B→a}={a}SELECT(B'→aBbb}={a}SELECT(B'→b}={b}由此可见所改写的文法是LL(1)的。
(3)改写文法得:S→Aa|bA→babA'A'->aabA'|ε求以上状态的First集和Follow集:SELECT(S→Aa)={b}SELECT(S→b)={b}由此可见,此文法不是LL(1)的。
(5)可以看出A有公共左因子。
消去得:S→Ab|aaA→aA'A'→A|ε此时,已经消除了左递归,并且没有了公共左因子。
但是 SELECT(S→Ab)={a}SELECT(S→aa)={a}显然文法不是LL(1)的。
二补充部分B5.1 设有文法G:A→(A)A|ε(1)求非终结符A的FIRST集和FOLLOW集;(2)说明G是LL(1)文法;(3)写出相应的递归下降子程序。
B5.1(1)FIRST(A)={ ( } FOLLOW(A)={ #,) }(2)因为 SELECT(A→(A)A)={ ( }SELECT(A→ε)={ #,) }规则的SELECT集互不相交,故文法是LL(1)文法。
(3)文法A→(A)A|ε的递归下降子程序:A() {if(SYM==‘(‘) { GetSym(); A(); match(‘)’); A(); }else if(SYM!=’#’ && SYM!=’)’) ERROR();?????}B5.2 对于简化的C声明文法G:declaration→type var-listtype→ int | floatvar-list→identifier , var-list | identifier其中,非终结符(斜体)集为{declaration,type ,var-list ,identifier(其规则省略) },终结符集为{ int, float,,(逗号) }(1)提取规则的公共左因子;(2)为所得文法的非终结符求FIRST集和FOLLOW集;(3)说明所得文法是LL(1)文法;(4)为所得文法构造预测分析表(LL(1)分析矩阵);(5)写出输入串 int x,y,z的分析过程。
B5.2对于文法declaration→type var-listtype→ int | floatvar-list→identifier , var-list | identifier(1)提取公共左因子:var-list→identifier(, var-list | ε)(2)FIRST(declaration) = {int, float}FIRST(type) = {int, float}FIRST(var-list) = { identifier }FOLLOW(declaration) = { # }FOLLOW(type) = FIRST(var-list) = { identifier }FOLLOW(var-list) = FOLLOW(declaration) = { # }(3)只有type不止一个候选式:int | float,且Select集不相交,故文法是LL(1)的。
(4)文法简记为:D → TVT → i | f (i和f分别为int和float的简记符)V → IX (I为identifier的简记符)X → ,V | ε(5B5.3 对于文法G:A→aAa|ε(1)说明该文法不是LL(1)文法;(2)假设某人构造A的递归子程序为void A(){if(SYM == a){GetSym();A();if (SYM == a) GetSym();else ERRPR();}else if (SYM != #) ERROR;}说明该子程序不能正确运行。