第四章 课后作业参考答案#
5. 考虑下面文法 G1:#
ST→a∣∧∣(T)→T,S∣S
(1) 消去 G1 的左递归。然后,对每个非终结符,写出不带回溯的递归子程序。
(2) 经改写后的文法是否是 LL(1) 的?给出它的预测分析表。
解答:
(1) 消去直接左递归并写出递归下降子程序#
文法中非终结符 T 的产生式含有直接左递归:T→T,S∣S。
应用消除左递归的常规公式 A→Aα∣β⟹A→βA′,A′→αA′∣ε,我们有:
T→ST′
T′→,ST′∣ε
消除左递归后的等价文法为:
STT′→a∣∧∣(T)→ST′→,ST′∣ε
不带回溯的递归下降子程序(伪代码):
procedure S;
begin
if lookahead = 'a' then
match('a')
else if lookahead = '^' then
match('^')
else if lookahead = '(' then
begin
match('(');
T;
match(')');
end
else
error("Syntax Error in S");
end;
procedure T;
begin
S;
T';
end;
procedure T';
begin
if lookahead = ',' then
begin
match(',');
S;
T';
end
else if lookahead = ')' then
{ 对应 T' -> ε,空匹配,因为 ) 属于 FOLLOW(T') }
begin end
else
error("Syntax Error in T'");
end;
(2) LL(1) 判定及预测分析表#
首先计算文法非终结符的 FIRST 与 FOLLOW 集合:
- FIRST(S)={a,∧,(}
- FIRST(T)=FIRST(S)={a,∧,(}
- FIRST(T′)={,,ε}
- \text{FOLLOW}(S) = \{ \, ,, ) }$
- FOLLOW(T)={)}
- FOLLOW(T′)=FOLLOW(T)={)}
LL(1) 判定:
对于含有选择分支的产生式 T′→,ST′∣ε,其两分支选择的 FIRST 交集为:
FIRST(,ST′)∩FOLLOW(T′)={,}∩{)}=∅
由于对所有非终结符,候选产生式的 FIRST 集合均两两互不相交,且包含 ε 的产生式其 FIRST 与 FOLLOW 的交集也为空。因此该文法是 LL(1) 文法。
预测分析表:
| 非终结符 | a | ∧ | ( | ) | , | $$$ |
|---|
| S | S→a | S→∧ | S→(T) | | | |
| T | T→ST′ | T→ST′ | T→ST′ | | | |
| T′ | | | | T′→ε | T′→,ST′ | |
6. 对下面的文法 G:#
EE′TT′FF′P→TE′→+E∣ε→FT′→T∣ε→PF′→∗F′∣ε→(E)∣a∣b∣∧
(1) 构造这个文法的每个非终结符的 FIRST 和 FOLLOW 集合。
(2) 证明这个文法是 LL(1) 的。
(3) 构造它的预测分析表。
(4) 构造它的递归下降分析程序。
解答:
(1) 计算 FIRST 与 FOLLOW 集合#
(详细推导见课本大题-答案)
| 非终结符 | FIRST 集合 | FOLLOW 集合 |
|---|
| E | {(,a,b,∧} | \{ \, ) }$ |
| E′ | {+,ε} | \{ \, ) }$ |
| T | {(,a,b,∧} | \{ +, \, ) }$ |
| T′ | {(,a,b,∧,ε} | \{ +, \, ) }$ |
| F | {(,a,b,∧} | \{ (, a, b, \wedge, +, \, ) }$ |
| F′ | {∗,ε} | \{ (, a, b, \wedge, +, \, ) }$ |
| P | {(,a,b,∧} | \{ *, (, a, b, \wedge, +, \, ) }$ |
(2) 证明是 LL(1) 文法#
文法中凡是具有多个候选产生式的非终结符,需要验证其 FIRST 与 FOLLOW 无交集冲突:
- 对于 E′→+E∣ε:
\text{FIRST}(+E) \cap \text{FOLLOW}(E') = \{ + \} \cap \{ \, ) } = \emptyset$。
- 对于 T′→T∣ε:
\text{FIRST}(T) \cap \text{FOLLOW}(T') = \{ (, a, b, \wedge \} \cap \{ +, \, ) } = \emptyset$。
- 对于 F′→∗F′∣ε:
\text{FIRST}(*F') \cap \text{FOLLOW}(F') = \{ * \} \cap \{ (, a, b, \wedge, +, \, ) } = \emptyset$。
- 对于 P→(E)∣a∣b∣∧:
各分支选择的首字符集分别为 {(}、{a}、{b}、{∧},它们两两不相交。
经检验,文法所有冲突均可完全解决,故该文法是 LL(1) 文法。
(3) 构造它的预测分析表#
(详细预测分析表见课本大题-答案)
(4) 递归下降分析程序#
procedure E;
begin
T; E';
end;
procedure E';
begin
if lookahead = '+' then
begin match('+'); E; end
else if lookahead in [')', '$'] then
{ 空匹配 }
else error;
end;
procedure T;
begin
F; T';
end;
procedure T';
begin
if lookahead in ['(', 'a', 'b', '^'] then
T
else if lookahead in ['+', '$', ')'] then
{ 空匹配 }
else error;
end;
procedure F;
begin
P; F';
end;
procedure F';
begin
if lookahead = '*' then
begin match('*'); F'; end
else if lookahead in ['(', 'a', 'b', '^', '+', '$', ')'] then
{ 空匹配 }
else error;
end;
procedure P;
begin
if lookahead = '(' then
begin match('('); E; match(')'); end
else if lookahead = 'a' then match('a')
else if lookahead = 'b' then match('b')
else if lookahead = '^' then match('^')
else error;
end;
7. 对下面文法:#
ExprExprTailVarVarTail→−Expr∣(Expr)∣Var ExprTail→−Expr∣ε→id VarTail→(Expr)∣ε
(1) 构造 LL(1) 分析表。
(2) 给出对句子 id−−id((id)) 的分析过程。
解答:
(1) FIRST / FOLLOW 及 LL(1) 预测分析表#
| 非终结符 | id | - | ( | ) | $ |
|---|
| Expr | Expr→Var ExprTail | Expr→−Expr | Expr→(Expr) | | |
| ExprTail | | ExprTail→−Expr | | ExprTail→ε | ExprTail→ε |
| Var | Var→id VarTail | | | | |
| VarTail | | VarTail→ε | VarTail→(Expr) | VarTail→ε | VarTail→ε |
(2) 句子 id−−id((id)) 的分析步骤过程#
下表展示了使用分析栈对句子进行分析的过程(其中 # 代表栈底标志):
| 步骤 | 符号栈 (从右至左压栈) | 剩余输入串 | 所用产生式 / 动作 |
|---|
| 1 | # Expr | id - - id ( ( id ) ) # | Expr→Var ExprTail |
| 2 | # ExprTail Var | id - - id ( ( id ) ) # | Var→id VarTail |
| 3 | # ExprTail VarTail id | id - - id ( ( id ) ) # | 匹配终结符 id (移进) |
| 4 | # ExprTail VarTail | - - id ( ( id ) ) # | VarTail→ε (因 - ∈ FOLLOW(VarTail)) |
| 5 | # ExprTail | - - id ( ( id ) ) # | ExprTail→−Expr |
| 6 | # Expr - | - - id ( ( id ) ) # | 匹配终结符 - (移进) |
| 7 | # Expr | - id ( ( id ) ) # | Expr→−Expr |
| 8 | # Expr - | - id ( ( id ) ) # | 匹配终结符 - (移进) |
| 9 | # Expr | id ( ( id ) ) # | Expr→Var ExprTail |
| 10 | # ExprTail Var | id ( ( id ) ) # | Var→id VarTail |
| 11 | # ExprTail VarTail id | id ( ( id ) ) # | 匹配终结符 id (移进) |
| 12 | # ExprTail VarTail | ( ( id ) ) # | VarTail→(Expr) (因 ( ∈ FIRST((Expr))) |
| 13 | # ExprTail ) Expr ( | ( ( id ) ) # | 匹配终结符 ( (移进) |
| 14 | # ExprTail ) Expr | ( id ) ) # | Expr→(Expr) |
| 15 | # ExprTail ) ) Expr ( | ( id ) ) # | 匹配终结符 ( (移进) |
| 16 | # ExprTail ) ) Expr | id ) ) # | Expr→Var ExprTail |
| 17 | # ExprTail ) ) ExprTail Var | id ) ) # | Var→id VarTail |
| 18 | # ExprTail ) ) ExprTail VarTail id | id ) ) # | 匹配终结符 id (移进) |
| 19 | # ExprTail ) ) ExprTail VarTail | ) ) # | VarTail→ε (因 ) ∈ FOLLOW(VarTail)) |
| 20 | # ExprTail ) ) ExprTail | ) ) # | ExprTail→ε (因 ) ∈ FOLLOW(ExprTail)) |
| 21 | # ExprTail ) ) | ) ) # | 匹配终结符 ) (移进) |
| 22 | # ExprTail ) | ) # | 匹配终结符 ) (移进) |
| 23 | # ExprTail | # | ExprTail→ε (因 # ∈ FOLLOW(ExprTail)) |
| 24 | # | # | 分析成功结束,句子合法被接受 |