(完整版)编译原理第五章作业参考答案
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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,^, ε };
BEGIN
P(y1);
P(y2);
...
P(yn);
END
如果 yi 是非终结符,则 P(yi) 代表调用处理 yi 的子程序;
如果 yi 是终结符,则 P(yi) 为形如下述语句的一段子程序
IF CH=yi THEN READ(CH) ELSE ERROR
即如果当前文法中的符号与输入符号匹配,则继续读入下一个待输入符号到 否则表明出错。
FIRST(S)={a, ∧ , ( }
FIRST(T)=FIRST(S)={a, ∧ , ( } FIRST(U)={ , , ε }
各非终结符的 FOLLOW集合如下:
FOLLOW(S)={#} ∪ FIRST(U) ∪ FOLLOW(T) ∪ FOLLOW(U)={#, , ,)}
FOLLOW(T)={)}
CH中,
(4) 如果文法中有空规则 U::=EPSILON, 则算法中的语句
IF CH IN FIRST(xn) THEN P(xn)
编译原理习题解答
页 2/2
ELSE ERROR
改写为:
IF CH IN FIRST(xn) THEN P(xn)
ELSE IF CH IN FOLLOW(U) THEN RETURN
FOLLOW(T)=FIRST(E/ ) ∪ FOLLOW(E)={+,),#};// 不包含ε
/
FOLLOW(T)=FOLLOW(T)=FIRST(E
/
)
∪
FOLLOW(E)={+,),#};
FOLLOW(F)=FIRST(T/ ) ∪ FOLLOW(T)={(,a,b,^,+,),#};//
不包含ε
3
#)T
a,a)# T SU
4
#)US
a,a)# S a
5
#)Ua
a,a)# a 匹配
6
#)U
,a)# U , SU
7
#)US,
,a)# , 匹配
8
#)US
a)# S a
9
#)Ua
a)# a 匹配
10
#)U
)# U ε
11
#)
)# ) 匹配
12
#
# 接受
2. 对下面的文法 G:
E TE/
/
E +E| ε
SELECT(E TE/ )=FIRST(T)={(,a,b,^};
SELECT(E/ +E)={+};
/
SELECT(E
ε
/
)=FOLLOW(E)={),#}
SELECT(T FT/ )=FIRST(F)={(,a,b,^};
/
SELECT(T T)=FIRST(T)={(,a,b,^};
SELECT(T/ ε )=FOLLOW(T/)={+,),#};
((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]:
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) 的含义为:
SELECT集的交集均为空,所以文法
G[E] 是 LL(1) 文法。
(3) 构造它的预测分析表。
文法 G[E] 的预测分析表如下:
+
*
(
)
a
b
^
#
E
TE/
TE/
TE/
TE/
/
E
+E
ε
ε
/
/
/
/
T
FT
FT
FT
FT
T/
ε
T
ε
T
T
T
ε
F
PF/
PF/
PF/
PF/
F/
ε
*F /
ε
ε
ε
ε
ε
ε
P
(E)
a
b
^
(4) 构造它的递归下降分析程序。
{ if(IsIn(CH,FIRST_T)) //FIRST_T {
为产生式 T/ T 的右部的 FIRST 集合,产生式 T/ T
P_T();
} else// 产生式 T/ ε
{ if(IsIn(CH,FOLLOW_TP)) //FOLLOW_TP 为 T/ 的 FOLLOW集合
return ;
else ERR;
return ;
else ERR;
}
}
void P_T()// 非终结符 T 的子程序
{ if(IsIn(CH,FIRST_FTP)) //FIRST_ FTP
为 T FT/ 的右部的 FIRST 集合,产生式 T FT/
{
P_F();
P_TP();
}
else ERR;
}
/
void P_TP()// 非终结符 T 的子程序
}
}
void P_F()// 非终结符 F 的子程序
{ if(IsIn(CH,FIRST_PFP)) //FIRST_PFP
为 F PF/ 的右部的 FIRST 集合,产生式 F PF/
{
P_P();
P_FP();
}
else ERR;
} void P_FP()// 非终结符 F/的子程序
{
if( CH==’* ’ ) //
{ READ(CH); P_S(); P_U();
} else// 产生式 U ε {
if(IsIn(CH,FOLLOW_U)) //FOLLOW_U return ;
else ERR; } } (3) 判断文法 G/ [S] 是否为 LL(1) 文法。
为 U 的 FOLLOW 集合
各非终结符的 FIRST 集合如下:
READ(CH); P_E(); if(CH== ’) ’) READCH(C H); else
ERR; } else if(CH== ’a’) READ(CH); else if(CH== ’b’) READ(CH); else if(CH== ’^’) READ(CH); else ERR; }
S a| ∧ |(T)
T SU
U , SU|ε
分析子程序的构造方法 对满足条件的文法按如下方法构造相应的语法分析子程序。
(1) 对于每个非终结号 U,编写一个相应的子程序 P(U) ;
(2) 对于规则 U::=x1|x2|..|xn,
有一个关于 U 的子程序 P(U),P(U) 按如下方法构造:
IF CH IN FIRST(x1) THEN P(x1)
可见,相同左部产生式的 SELECT集的交集均为空,所以文法
文法
/
G [S]
的预测分析表如下:
a
∧
(
S
a
∧
(T)
T
SU
SU
SU
U
G/ [S] 是 LL(1) 文法。
)
,
ε
, SU
(5) 给出输入串 (a,a)# 的分析过程
步骤 分析栈
剩余输入串 所用产生式
1
#S
(a,a)# S (T)
2
#)T(
(a,a)# ( 匹配
对每个非终结符写出不带回溯的递归子程序如下:
char CH;// 存放当前的输入符号
void P_E()// 非终结符 E 的子程序 {
if(IsIn(CH,FIRST_TEP)) //FIRST_TEP
为 E TE/ 的右部的 FIRST 集合,产生式 E TE/
{
P_T();
P_EP();
}
编译原理习题解答
编译原理习题解答
页 1/1
第五章 自顶向下语法分析方法
1.对文法 G[S]
S a| ∧ |(T)
T T,S|S
(1) 给出 (a,(a,a)) 和 (((a,a), ∧ ,(a)),a) 的最左推导。
(2) 对文法 G,进行改写,然后对每个非终结符写出不带回溯的递归子程序。
(3) 经改写后的文法是否是 LL(1) 的?给出它的预测分析表。
/
T FT T/ T| ε F PF/
F/
/
*F
|
ε
P (E)|a|b|^
(1) 计算这个文法的每个非终结符的 FIRST 集和 FOLLOW集。
(2) 证明这个方法是 LL(1) 的。
(3) 构造它的预测分析表。
(4) 构造它的递归下降分析程序。
解:
( 1)计算这个文法的每个非终结符的
FIRST 集和 FOLLOW集。
页 5/5
else ERR;
} void P_EP()// 非终结符 E/的子程序
{ if( CH==’+’ ) // 产生式 E/ +E
{
READ(CH);
P_E();
}
/
else// 产生式 E ε
{ if(IsIn(CH,FOLLOW_EP)) //FOLLOW_EP 为 E/ 的 FOLLOW集合
FOLLOW(U)=FOLLOW(T)={)}
每个产生式的 SELECT集合如下:
编译原理习题解答
SELECT(S a)={a}
SELECT(S ∧ )={ ∧ } SELECT(S (T))={(}
SELECT(T SU)=FIRST(S)={a, ∧ , ( } SELECT(U , SU)={ , } SELECT(U ε )=FOLLOW(U)={)}
FOLLOW(F/ )=FOLLOW(F)=FIRST(T / ) ∪ FOLLOW(T)={(,a,b,^,+,),#};
FOLLOW(P)=FIRST(F/ ) ∪ FOLLOW(F)={*,(,a,b,^,+,),#};//
不包含ε
(2) 证明这个方法是 LL(1) 的。
各产生式的 SELECT集合有:
产生式 F/
/
*F
{
READ(CH);
P_FP();
}
/
else// 产生式 F ε {
if(IsIn(CH,FOLLOW_FP)) //FOLLOW_FP
为 F/ 的 FOLLOW集合
return ;
else ERR;
}
编译原理习题解答
} void P_P()// 非终结符 P 的子程序 {
if(CH== ’( ‘) {
(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)
ERROR
(5) 要分析一个 OrgStr, 应在该串的后面加上一个串括号 '#', 并从子程序 P(S)(S 为文法的开始符号 ) 开始,
如果中途没有产生错误,并且最后
CH='#', 则说明 OrgStr 串合法,否则该串不合法。
对每个非终结符写出不带回溯的递归子程序如下:
char CH;// 存放当前的输入符号 void P_S()// 非终结符 S 的子程序 {
页 3/3 #
编译原理习题解答
页 4/4
FIRST(F)=FIRST(P)={(,a,b,^}; FIRST(F / )=FIRST(P)={*, ε }; FIRST(P)={(,a,b,^};
FOLLOW集合有:
FOLLOW(E)={),#};
FOLLOW(E/ )=FOLLOW(E)={),#};