DFA ⇒ 转换表
例:
Ii | a | |
---|---|---|
0 | 1 | 2 |
1 | 1 | 3 |
2 | 3 | |
3 | 1 |
则由表的前两行得 I0→aI1,I0→bI2
大概代码如下
state = 0;
while(1) {
ch = getchar();
s = lookup(state, ch);
if(s == ' ' && s is non-terminal state) {
error;
} else if(s == ' ' && s is terminal-state) {
ungetchar();
return;
} else {
state = s;
}
}
Language ⇒By experience RE
- 逐步求精法
- FA-based
例:一个2进制数能被3整除,我们做出在某个数后面添加一个0/1后模3余的结果电路转换图
语法分析
自上而下
递归下降分析法
一个非终结符对应一个子程序
若有以下文法:
S→aA|bB
A→cD|d
B→eB|f
D→g
则有对应程序:
int S() {
ch = getchar();
if(ch == 'a') {
return A();
} else if(ch == 'b') {
return B();
} else {
return 0;
}
}
int A() {
ch = getchar();
if(ch == 'c') {
return D();
} else if(ch == 'd') {
return 1; // 表示结束
} else {
return 0; // 表示出错
}
}
// 其余同理
换一种文法:
S→aA|aB
A→Ad|d
B→Be|e
int S() {
ch = getchar();
if(ch == 'a') {
if(A()) {
return 1;
} else {
return B();
}
}
}
int A() {
A();
if(ch == 'd') {
return 1;
} else {
return 0;
}
}
在这种情况下会出现回溯和栈溢出
不能出现公共左子表达式和左递归,会出现回溯。
因此想用这种方法的话,对文法的要求比较高。
预测分析法
预处理:
提取最大公共左子表达式
消除左递归
把左递归变成右递归的形式
左递归:
- 直接左递归: A→Aα|β
- 间接左递归: A→Bα|β,B→Aβ|θ
消除直接左递归
A→Aα|β⇒β,βα,βα2,⋯,βαn,⋯⇒βαn(n≥0)
记 αn=A′ ,则有 A→βA′,A′→ϵ|αA′
消除间接左递归
S→Qc|cQ→Rb|bR→Sa|a
此时有间接左递归
我们强行规定优先级: S>Q>R
S→Qc|cQ→Rb|bR→Sa|a→(Qc|c)a|a→Qca|ca|a→(Rb|b)ca|ca|a→Rbca|bca|ca|a
此时由消除直接左递归的方法得, R→(bac|ca|a)R′R′→bcaR′|ϵ
先消除直接左递归,再消除间接左递归
S→Qc|cQ→Qd|Rb|bR→Sa|a
Q→(Rb|b)Q′Q′→dQ′|ϵ
S→Q→RS→Qc|cQ→(Rb|b)Q′Q′→dQ′|ϵR→(Qc|c)a|a→Qca|ca|a→(Rb|b)Q′ca|ca|a→RbQ′ca|bQ′ca|ca|a
此时再用消除直接左递归的方法再消除一下就好了