一、FIRST集
FIRST(a)是从a 推导出的串的起始终结符的集合
计算方法
- 若X->a.., 则将终结符a加入FIRST(X)中
- 若X->e,则将e加入FIRST(X)中
- 若X->Y…,且Y属于非终结符,则将FIRST(Y)\{e}加入到FIRST(X)中
- 若X->Y1Y2..YK,且Y1,Y2,..Yi-1 (2≤i≤k)都是非终结符,且Y1,Y2,..Yi-1 的FIRST集合中均包含e,则将FIRST(Yj)的所有非e元素加入到FIRST(X)中,(j=1,2,..i).特别地,若Y1~YK均有e产生式,则将e加到FIRST(X)中
首先,S推出B,则FIRST(S)=FIRST(B)
同理FIRST(A)包含FIRST(B),且d∈FIRST(A)
由三式知,B可以推出a,b,c所以FIRST(B)={a,b,c}
二、FOLLOW集
FOLLOW(A)是在所有句型中紧跟在A后面的终结符集合
FOLLOW集计算方法
- 对文法开始符号S,置$于FOLLOW(S)中。
- 若有A->aBb,则将FIRST(b)\{e} 加入FOLLOW(B)中。 (此处a 可以为空)
- 若A->a B 或A->a B b,且 b -》e(即e 属于FIRST(b)),则将 FOLLOW(A)加入FOLLOW(B)中(此处a 可以为空)
首先对于开始符号S,将$加入FoLLOW(S)中(以下为了方便以F()代指FOLLOW())
B后面是A,因此将FIRST(A)加入到FOLLOW(B)中F(B)={a,b,c,d}
A在推导式最后,因此将F(S)加入F(A),F(A)={$,a,b,c,d}
对于式2,将FIRST(S)加入到F(B)中,F(B)={a,b,c,d}
将F(A)加入到F(S)中,F(S)={$,a,b,c,d}
对于式3,将F(B)加入到F(A),F(S)中
三、LL(1)文法
LL(1)文法有一些明显的特征
- 没有公共的左因子
- 不是二义的
- 不含左递归
该推导显然含有左递归,因此不是LL(1)文法
这是消除左递归后的形式
上式可判断不含左递归,不含公共的左因子,是不是LL(1)文法只需要判断是否满足定义中关于FIRST集和FOLLOW集的条件
显然交集为空,因此该式是LL(1)文法
四、自上而下分析法的递归实现
S(){
B();
A();
}
A(){
if(lookahead==‘a’|’b’|’c’){
B(); S();
}else
match(‘d’);
}
B(){
if(lookahead==‘a’){
match(‘a’); A();
}else if(lookahead==‘b’){
match(‘b’); S();
}else
match(‘c’);
}
五、自上而下分析法非递归的预测分析
以下表为例,接受id*id+id时
非终 结符 | 输 入 符 号 | |||
id | + | * | . . . | |
E | E -> TE ¢ |
|
|
|
E ‘ |
| E ' -> +TE ' |
|
|
T | T -> FT ' |
|
|
|
T ' |
| T ' -> e | T ' -> *FT ' |
|
F | F -> id |
|
|
|
从开始符号入栈,根据栈顶元素和输入到表中对应的行列寻找推导式,将推导结果倒序入栈(替换),栈顶和输入匹配时二者都释放直至都为空。
预测分析表的构建
(1)对文法的每个产生式A -> a ,执行(2)和(3)。
(2)对FIRST(a)的每个终结符a,把A ->a 加入 M[A, a](即加入表中A行a列)。
(3)如果e在FIRST(a)中,对FOLLOW(A)的每个终结符b(包括$), 把A -> a 加入M[A, b]。
(4)M的其它没有定义的条目都是error。
五、预测分析的错误恢复
对于非终结符X对应的一行,把FOLLOW(X)中终结符的对应列都填上同步记号
- 查表,当前表项空白,指向记号流的指针后移;
- 查表,当前表项中含有同步记号synch,将当前栈中的非终结符弹出栈;
- 栈顶终结符和当前指针指向的终结符不匹配,将栈顶终结符弹出栈。
1 栈顶不动;2,3指针不动