第四章 自顶向下语法分析
1、对文法G[S]
S→a|∧|(T)
T→T,S|S
(1) 给出(a,(a,a))和(((a,a),∧,(a)),a)的最左推导。
(a,(a,a)):
S->(T)-->(S,S)-->(a,S)-->(a,(T))-->(a,(T,S))-->(a,(S,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,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) 对文法G,进行改写,然后对每个非终结符写出不带回溯的递归子程序。
消除直接左递归:T-->T,S,把文法G改写为:
S->a
S-->∧
S-->(T)
T-->SN
N-->,SN
N-->ε
不带回溯的递归子程序:
Step1:计算FIRST集:
FIRST(S)={a,∧,(}
FIRST(T)=FIRST(S)={a,∧,(}
FIRST(N)={,,ε}
Step2:计算FOLLOW集:
FOLLOW(S)=(FIRST(N)-{ε})UFOLLOW(T)U{#}={#,,,)}
FOLLOW(T)=FIRST())={)}
FOLLOW(N)=FOLLOW{T}={)}
列表如下:
非终结符 | FIRST集 | FOLLOW集 |
S | {a,∧,(} | {#,,,)} |
T | {a,∧,(} | {)} |
N | {,,ε} | {)} |
Step3:计算SELECT集:
SELECT(S-->a)={a}
SELECT(S-->∧)={∧}
SELECT(S-->(T))={(}
SELECT(T-->SN)=FIRST(S)={a,∧,(}
SELECT(N-->,SN}={,}
SELECT(N-->ε)=FOLLOW(N)={)}
Step4:写出递归子程序
void ParseS()
{
switch(lookahead)
{
case a:
MatchToken(a);
break;
case ∧:
MatchToken(∧);
break;
case (:
MatchToken(();
ParseT();
MatchToken());
default:
printf("syntax error \n");
exit(0);
}
}
void ParseT()
{
switch(lookahead)
{
case a,∧,(:
ParseS();
ParseN();
break;
default:
printf("syntax error \n");
exit(0);
}
}
void ParseN()
{
switch(lookahead)
{
case ,:
MatchToken(,);
ParseS();
ParseN();
break;
case ):
break;
default:
printf("syntax error \n");
exit(0);
}
}
(3) 经改写后的文法是否是LL(1)的?给出它的预测分析表。
由(2)得:
SELECT(S-->a)∩SELECT(S-->∧)∩SELECT(S-->(T))={a}∩{∧}∩{(}=∅
SELECT(N-->,SN}∩SELECT(N-->ε)={,}∩{)}=∅
因此改写后的文法是LL(1)文法。
预测分析表:
a | ∧ | ( | ) | , | |
S | -->a | -->∧ | -->(T) | ||
T | -->SN | -->SN | -->SN | ||
N | -->ε | -->,SN |
(4) 给出输入串(a,a)#的分析过程,并说明该串是否为G 的句子。
栈 | 当前输入符 | 剩余输入符 | 所用产生式 |
#S | ( | a,a)# | S-->(T) |
#)T( | ( | a,a)# | |
#)T | a | ,a)# | T-->SN |
#)NS | a | ,a)# | S-->a |
#)Na | a | ,a)# | |
#)N | , | a)# | N-->SN |
#)NS, | , | a)# | |
#)NS | a | )# | S-->a |
#)Na | a | )# | |
#)N | ) | # | N-->ε |
#) | ) | # | |
# | # |
因此输入串(a,a)#是文法G的句子。
2、已知文法G[S]:
S→MH|a
H→LSo|ε
K→dML|ε
L→eHf
M→K|bLM
判断G 是否是LL(1)文法,如果是,构造LL(1)分析表。
计算各非终结符的FIRST集和FOLLOW集:
FIRST(S)={a}+FIRST(M)+FIRST(H)={a,b,d,e,ε}
FIRST(H)={ε}+FIRST(L)+
FIRST(K)={d,ε}
FIRST(L)={e}
FIRST(M)=FIRST(K)+{b}={d,b,ε}
FOLLOW(S)={#,o}
FOLLOW(H)=FOLLOW(S)+{f}={#,o,f}
FOLLOW(K)=FOLLOW(M)={e,#,o}
FOLLOW(L)=FIRST(M)-{ε}+FOLLOW(M)+FOLLOW(K)={b,d,e,#,o}
FOLLOW(M)=FIRST(L)+FIRST(H)-{ε}+FOLLOW(S)={e,#,o}
FIRST集 | FOLLOW集 | |
S | {a,b,d,e,ε} | {#,o} |
H | {e,ε} | {#,f,o} |
K | {d,ε} | {e,#,o} |
L | {e} | {#,o,b,d,e} |
M | {b,d,ε} | {e,#,o} |
因此,SELECT集计算如下:
SELECT(S-->MH)=FIRST(M)}-{ε}+FOLLOW(S)={b,d,e,o,#}
SELECT(S-->a)={a}
所以SELECT(S-->MH)∩SELECT(S-->a)=∅
SELECT(H-->LSo)=FIRST(L)={e}
SELECT(H-->ε)=FOLLOW(H)={#,f,o}
所以SELECT(H-->LSo)∩SELECT(H-->ε)=∅
SELECT(K-->dML)={d}
SELECT(K-->ε)=FOLLOW(K)={e,#,o}
所以SELECT(K-->dML)∩SELECT(K-->ε)=∅
SELECT(L-->eHf)={e}
SELECT(M-->K)=FIRST(K)-{ε}+FOLLOW(M)={d,e,#,o}
SELECT(M-->bLM)={b}
所以SELECT(M-->K)∩SELECT(M-->bLM)=∅
综上所述,该文法是LL(1)文法。
故预测分析表如下:
a | b | d | e | f | o | # | |
S | -->a | -->MH | -->MH | -->MH | -->MH | -->MH | |
H | -->LSo | -->ε | -->ε | -->ε | |||
K | -->dML | -->ε | -->ε | -->ε | |||
L | -->eHf | ||||||
M | -->bLM | -->K | -->K | -->K | -->K |