第05章 自顶向下语法分析方法.docx
《第05章 自顶向下语法分析方法.docx》由会员分享,可在线阅读,更多相关《第05章 自顶向下语法分析方法.docx(18页珍藏版)》请在冰豆网上搜索。
第05章自顶向下语法分析方法
第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)
(((a,a),∧,(a)),S)(((a,a),∧,(a)),a)
(2)改写文法为:
0)S→a
1)S→∧
2)S→(T)
3)T→SN
4)N→,SN
5)N→ε
非终结符
FIRST集
FOLLOW集
S
{a,∧,(}
{#,,,)}
T
{a,∧,(}
{)}
N
{,,ε}
{)}
对左部为N的产生式可知:
FIRST(→,SN)={,}FIRST(→ε)={ε}FOLLOW(N)={)}
由于SELECT(N→,SN)∩SELECT(N→ε)={,}∩{)}=
所以文法是LL
(1)的。
预测分析表(PredictingAnalysisTable)
a
∧
(
)
#
S
→a
→∧
→(T)
T
→SN
→SN
→SN
N
→ε
→,SN
也可由预测分析表中无多重入口判定文法是LL
(1)的。
(3)对输入串(a,a)#的分析过程为:
栈(STACK
当前输入符
)
(CUR_CHAR)
剩余输入符
(INOUT_STRING)
所用产生式
(OPERATION)
#S
#)T(
#)T
#)NS
#)Na
#)N
#)NS,
#)NS
#)Na
#)N
#)
#
((aaa
aa
)
)
#
a,a)#
a,a)#
a)#
a)#
a)#a)#a)#
)#
)#
#
#
S→(T)
T→SNS→a
N→,SNS→aN→ε
可见输入串(a,a)#是文法的句子。
第3题
已知文法G[S]:
S→MH|aH→LSo|εK→dML|εL→eHfM→K|bLM
判断G是否是LL
(1)文法,如果是,构造LL
(1)分析表。
答案:
文法展开为:
0)S→MH
1)S→a
2)H→LSo
3)H→ε
4)K→dML
5)K→ε
6)L→eHf
7)M→K
8)M→bLM
非终结符
FIRST集
FOLLOW集
S
{a,d,b,ε,e}
{#,o}
M
{d,ε,b}
{e,#,o}
H
{ε,e}
{#,f,o}
L
{e}
{a,d,b,e,o,#}
K
{d,ε}
{e,#,o}
对相同左部的产生式可知:
SELECT(S→MH)∩SELECT(S→a)={d,b,e,#,o}∩{a}=SELECT(H→LSo)∩SELECT(H→ε)={e}∩{#,f,o}=SELECT(K→dML)∩SELECT(K→ε)={d}∩{e,#,o}=
SELECT(M→K)∩SELECT(M→bLM)={d,e,#,o}∩{b}=
所以文法是LL
(1)的。
预测分析表:
a
o
d
e
f
b
#
S
→a
→MH
→MH
→MH
→MH
→MH
M
→K
→K
→K
→bLM
→K
H
→ε
→LSo
→ε
→ε
L
→eHf
K
→ε
→dML
→ε
→ε
由预测分析表中无多重入口也可判定文法是LL
(1)的。
第7题
对于一个文法若消除了左递归,提取了左公共因子后是否一定为LL
(1)文法?
试对下面文法进行改写,并对改写后的文法进行判断。
(1)A→baB|ε
B→Abb|a
(2)A→aABe|a
B→Bb|d
(3)S→Aa|bA→SBB→ab
答案:
(1)先改写文法为:
0)A→baB
1)A→ε
2)B→baBbb
3)B→bb
4)B→a
再改写文法为:
0)A→baB
1)A→ε
2)B→bN
3)B→a
4)N→aBbb
5)N→b
FIRST
FOLLOW
A
{b}
{#}
B
{b,a}
{#,b}
N
{b,a}
{#,b}
预测分析表:
a
b
#
A
→baB
→ε
B
→a
→bN
N
→aBbb
→b
由预测分析表中无多重入口判定文法是LL
(1)的。
(2)文法:
A→aABe|aB→Bb|d
提取左公共因子和消除左递归后文法变为:
0)A→aN
1)N→ABe
2)N→ε
3)B→dN1
4)N1→bN1
5)N1→ε
非终结符
FIRST集
FOLLOW集
A
{a}
{#,d}
B
{d}
{e}
N
{a,ε}
{#,d}
N1
{b,ε}
{e}
对相同左部的产生式可知:
SELECT(N→ABe)∩SELECT(N→ε)={a}∩{#,d}=
SELECT(N1→bN1)∩SELECT(N1→ε)={b}∩{e}=
所以文法是LL
(1)的。
预测分析表(PredictingAnalysisTable)
a
e
b
d
#
A
→aN
B
→dN1
N1
→ε
→bN1
N
→ABe
→ε
→ε
也可由预测分析表中无多重入口判定文法是LL
(1)的。
(3)文法:
S→Aa|bA→SBB→ab
第1种改写:
用A的产生式右部代替S的产生式右部的A得:
S→SBa|bB→ab消除左递归后文法变为:
0)S→bN
1)N→BaN
2)N→ε
3)B→ab
非终结符
FIRST集
FOLLOW集
S
{b}
{#}
B
{a}
{a}
N
{ε,a}
{#}
对相同左部的产生式可知:
SELECT(N→BaN)∩SELECT(N→ε)={a}∩{#}=
所以文法是LL
(1)的。
预测分析表(PredictingAnalysisTable)
a
b
#
S
→bN
B
→ab
N
→BaN
→ε
也可由预测分析表中无多重入口判定文法是LL
(1)的。
第2种改写:
用S的产生式右部代替A的产生式右部的S得:
S→Aa|bA→AaB|bBB→ab
消除左递归后文法变为:
0)S→Aa
1)S→b
2)A→bBN
3)N→aBN
4)N→ε
5)B→ab
非终结符
FIRST集
FOLLOW集
S
{b}
{#}
A
{b}
{a}
B
{a}
{a}
N
{a,ε}
{a}
对相同左部的产生式可知:
SELECT(S→Aa)∩SELECT(S→b)={b}∩{b}={b}≠
SELECT(N→aBN)∩SELECT(N→ε)={a}∩{a}={a}≠
所以文法不是LL
(1)的。
预测分析表:
a
b
#
S
→Aa
→b
A
→bBN
B
→ab
N
→aBN
→ε
也可由预测分析表中含有多重入口判定文法不是LL
(1)的。
附加题
问题1:
已知文法G[A]如下,试用类C或类PASCAL语言写出其递归下降子程序.(主程序不需写)
G[A]:
A→[B
B→X]{A}X→(a|b){a|b}
答案:
不妨约定:
在进入一个非终结符号相应的子程序前,已读到一个单词.word:
存放当前读
到的单词,Getsym()为一子程序,每调用一次,完成读取一单词的工作。
error()为出错处理
程序.FIRST(A)为终结符A的FIRST集.
类C程序如下:
voidA()
{
ifword=='['
{
Getsym();B();
}
elseerror();
}
voidB()
{X();
ifword==']'
{
Getsym();
while(wordin
FIRST(A))A();
}
elseerror();
voidX()
{
if(word=='a'||word=='b')
{
Getsym();
while(word=='a'||word=='b')Getsym();
}
elseerror();
}
}
问题2:
设有文法G[A]的产生式集为:
A→BaC|CbB
B→Ac|c
C→Bb|b
试消除G[A]的左递归。
答案:
提示:
不妨以A、B、C排序.先将A代入B中,然后消除B中左递归;再将A、B代入C中。
再消除C中左递归。
最后结果为:
G[A]:
A→BaC|CbB
B→CbBcB'|cB'
B'→aCcB'|ε
C→cB'bC'|bC'
C'→bBcB'bC'|ε
问题3:
试验证如下文法G[E]是LL
(1)文法:
E→[F]E′
E’→E⏐ε
F→aF’
F’→aF’⏐ε
其中E,F,E’,F’为非终结符
答案:
各非终结符的FIRST集和FOLLOW集如下:
FIRST(E)={[}FOLLOW(E)={#}FIRST(E′)={[,ε}FOLLOW(E′)={#}FIRST(F)={a}FOLLOW(F)={]}FIRST(F′)={a,ε}FOLLOW(F′)={]}
对于E’→E⏐ε,FIRST(E)∩FIRST(ε)=⎫
FIRST(E)∩FOLLOW(E’)=⎫
对于F’→aF’⏐ε,FIRST(aF’)∩FIRST(ε)=⎫
FIRST(aF’)∩FOLLOW(F’)=⎫
所以,文法G[E]是LL
(1)文法。
问题4:
文法G[E]是LL
(1)文法:
E→[F]E′
E’→E⏐ε
F→aF’
F’→aF’⏐ε
其中E,F,E’,F’为非终结符。
对文法G[E]构造递归下降分析程序。
答案:
/*用类C语言写出G[E]的递归子程序,其中yylex()为取下一单词过程,变量lookahead存放当前单词。
*/
intlookahead;
voidParseE()
{
MatchToken(′[′);ParseF();MatchToken(′]′);ParseE’();
}
voidParseE’()
{
switch(lookahead){
case′[′:
ParseE();
break;
case′#′:
break;
default:
printf("syntaxerror\n")
exit(0);
}
}
voidParseF()
{
MatchToken(′a′);ParseF’();
}
voidParseF’()
{
switch(lookahead){
case′a′:
MatchToken(′a′);ParseF’();
break;
case′]′:
break;
default:
printf("syntaxerror\n")
exit(0);
}
}
voidMatchToken(intexpected)
{
if(lookahead!
=expected)//判别当前单词是否与期望的终结符匹配
{
printf("syntaxerror\n");
exit(0);
}
else//若匹配,消费掉当前单词并读入下一个调用词法分析程序
lookahead=yylex();
}
问题5:
文法G[E]是LL
(1)文法:
E→[F]E′
E’→E⏐ε
F→aF’
F’→aF’⏐ε其中E,F,E’,F’为非终结符。
构造文法G[E]的LL
(1)分析表。
答案:
问题6:
试消除下面文法G[A]中的左递归和左公因子,并判断改写后的文法是否为LL
(1)文法?
G[A]:
A→aABe⏐a
B→Bb⏐d
答案:
提取左公共因子和消除左递归后,G[A]变换为等价的G′[A]如下:
A→aA′A′→ABe|εB→dB′B′→bB′|ε
—计算非终结符的FIRST集和FOLLOW集结果如下:
FIRST(A)={a}FOLLOW(A)={#,d}FIRST(B)={d}FOLLOW(B)={e}FIRST(A′)={a,ε}FOLLOW(A′)={#,d}FIRST(B′)={b,ε}FOLLOW(B′)={e}
—对相同左部的产生式可知:
FIRST(ABe)∩FOLLOW(A′)={a}∩{#,d}=∅
FIRST(bB′)∩FOLLOW(B′)={b}∩{e}=∅
所以G′[S]是LL
(1)文法。