LL(1)文法的判断,递归下降分析程序
1. 文法 G(S):
(1)S -> AB
(2)A ->Da|ε
(3)B -> cC
(4)C -> aADC |ε
(5)D -> b|ε
验证文法 G(S)是不是 LL(1)文法?
FIRST集:
FIRST(A)→FIRST(Da)→{a,b} b是由DA得到的。
FIRST(A)→FIRST(ε)→{ε}
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.加上实验一的词法分析程序,形成可运行的语法分析程序,分析任意输入的符号串是不是合法的表达式。