1. 文法 G(S):spa
(1)S -> AB遞歸
(2)A ->Da|εit
(3)B -> cC語法
(4)C -> aADC |ε程序
(5)D -> b|εerror
驗證文法 G(S)是否是 LL(1)文法?cas
FIRST集:錯誤
FIRST(A)→FIRST(Da)→{a,b} b是由DA獲得的。void
FIRST(A)→FIRST(ε)→{ε}printf
FIRST(B)→FIRST(cC)→{a,c}
FIRST(C)→FIRST(aADC)→{a}
FIRST(C)→FIRST(ε)→{ε}
FIRST(D)→FIRST(b)→{b}
FIRST(D)→FIRST(ε)→{ε}
FOLLOW集:
FOLLOW(S)→{#}
FOLLOW(A)→{a,b,c,#}
FOLLOW(B)→{#}
FOLLOW(C)→{#}
FOLLOW(D)→{a,#}
SELECT集:
SELECT(A->Da)={b,a}
SELECT(A->ε)={a,b,c,#}
SELECT(B->cC)={c}
SELECT(C->aADC)={a}
SELECT(C->ε)={#}
SELECT(D->b)={b}
SELECT(D->ε)={a,#}
由於:
SELECT(A->Da) ∩SELECT(A->ε)={a,b}
因此文法 G(S)不是 LL(1)文法。
2.(上次做業)消除左遞歸以後的表達式文法是不是LL(1)文法?
E -> E+T | T
T -> T*F | F
F -> (E) | i
消除左遞歸:
E -> TE'
E' -> +TE' | ε
T -> FT'
T' ->*FT' | ε
F -> (E) | i
FIRST集:
FIRST(E)→FIRST(T)→FIRST(F)→{ ( , i }
FIRST(E')→{+,ε}
FIRST(T)→FIRST(F)→{ ( , i }
FIRST(T')→{*,ε}
FIRST(F)→{ ( , i }
FOLLOW集:
FOLLOW(E)→{ ) , # } 可由 (E)得出
FOLLOW(E')→{ ) , # } 可由 (TE')得出
FOLLOW(T)→{ + , ) , # } 可由 (T+T)得出
FOLLOW(T')→{ + , ) , # } 可由 (T+FT')得出
FOLLOW(F)→{ * , + , ) , # } 可由 F+F 、F*F 、(i+i)得出
SELECT集:
SELECT(E→TE')={ ( , i }
SELECT(E'→+TE')={+}
SELECT(E'→ε)= FIRST(ε)-{ ε } U FOLLOW(E') = FOLLOW(E')= { ) , # } FIRST(ε)不存在,因此等於FOLLOW(E')
SELECT(T→FT')={ ( , i }
SELECT(T'→*FT')={*}
SELECT(T'→ε)= FIRST(ε)-{ ε } U FOLLOW(T') = FOLLOW(T')={+,),#} FIRST(ε)不存在,因此等於FOLLOW(T')
SELECT(F→(E))={(}
SELECT(F→i)={i}
由於:
SELECT(E'→+TE')∩SELECT(E'→ε)= ∅
SELECT(T'→*FT')∩SELECT(T'→ε)=∅
SELECT(F→(E)) SELECT(F→i)=∅
因此:該文法 G(S)是 LL(1)文法。
3.接2,若是是LL(1)文法,寫出它的遞歸降低語法分析程序代碼。
E()
{T();
E'();
}
E'()
T()
T'()
F()
代碼:
//在此程序中 E' 改成 E1 , T‘ 改成 T1
void ParseE(){
switch(lookahead){
case (,i: //若是開始時的符號是 (,i 就對 E→TE'進行解析
ParseT(); //對 T 解析
ParseE1(); //對 E' 解析
break;
default: //其餘形式開頭的都是錯誤
printf("syntax error \n");
exit(0);
}
}
void ParseE1(){
switch(lookahead){ //對語法 E' -> +TE' | ε 進行解析
case +: //當 E' 開始時的符號是 + 就對 E→+TE'進行解析
MatchToken(+); // 匹配當前終結符和正在掃描的單詞符號
ParseT(); // 對 T 解析
ParseE1(); // 對 E'解析
break;
case #,): // 當 E' 開始時的符號是 #,) 就對 E→+TE'進行解析
break; //返回空竄
default: // 其餘形式開頭的都是錯誤
printf("syntax error \n");
exit(0);
}
}
void ParseT(){
switch(lookahead){ //對語法 T -> FT' 進行解析
case (,i: //當 T 開始時的符號是 (,i 就對 T -> FT'進行解析
ParseF(); // 對 F 解析
ParseT1(); // 對 T’ 解析
break;
default: // 其餘形式開頭的都是錯誤
printf("syntax error \n");
exit(0);
}
}
void ParseE1(){
switch(lookahead){ //對語法 T' ->*FT' | ε 進行解析
case *: //當 T‘ 開始時的符號是 * 就對 T' ->*FT'進行解析
MatchToken(*); // 匹配當前終結符和正在掃描的單詞符號
ParseF(); // 對 F解析
ParseT1(); // 對 T' 解析
break;
case #,),+: //當 T' 開始時的符號是 #,),+ 就對 T' ->ε進行解析
break;
default: // 其餘形式開頭的都是錯誤
printf("syntax error \n");
exit(0);
}
}
void ParseF(){
switch(lookahead){ //對語法 F -> (E) | i 進行解析
case (: //當 F 開始時的符號是 ( 就對 F -> (E)進行解析
MatchToken((); // 匹配當前終結符和正在掃描的單詞符號
ParseE(); // 對 E解析
MatchToken()); // 匹配當前終結符和正在掃描的單詞符號
break;
case i: //當 F 開始時的符號是 i 就對 F ->i 進行解析
MatchToken(i); // 匹配當前終結符i
break;
default: // 其餘形式開頭的都是錯誤
printf("syntax error \n");
exit(0);
}
}
4.加上實驗一的詞法分析程序,造成可運行的語法分析程序,分析任意輸入的符號串是否是合法的表達式。