// 刚开始代码中用的是 Ne,现在改为 toEpsilon
Dictionary<char, bool> toEpsilon = new Dictionary<char, bool>(); // 是否能推出 epsilon
void ComputeEpsilon() { // 第一步求出能推出 epsilon 的非终结符
Dictionary<char, List> curr = LR.ToDictionary(entry => entry.Key, entry => entry.Value.ToList());
Dictionary<char, int> record2 = new Dictionary<char, int>(record); // 记录以某一非终结符为左部的产生式的数量
foreach (KeyValuePair<char, List> s in curr) {
// 产生式: A->BC, s1:BC s2:A
List s1 = s.Value;
char s2 = s.Key;
for (int i = 0; i < s1.Count; i++) {
if (s1[i].Length == 1 && s1[i][0] == '=') { // 如果产生式右侧只有 epsilon
toEpsilon[s2] = true;
curr[s2] = new List() { '' }; // 将所有此非终结符的产生式置空
break;
}
for (int j = 0; j < s1[i].Length; j++) {
if (VT.Contains(s1[i][j])) { // 为非终结符
curr[s2][i] = ''; // 此产生式删除
record2[s2]--; // s2 的产生式减 1
if (record2[s2] == 0) { // 如果 s2 的产生式都被删除,则为 false
toEpsilon[s2] = false;
}
}
}
}
}
int judge = 0;
while (judge <= 20) { // 第三步, 迭代 20 次
foreach (KeyValuePair<char, List> s in curr) {
List s1 = s.Value;
char s2 = s.Key;
for (int i = 0; i < s1.Count; i++) {
int len = s1[i].Length; // 用 len 来记录该产生式右部剩下的字符数
for (int j = 0; j < s1[i].Length; j++) {
if (toEpsilon.ContainsKey(s1[i][j]) && VN.Contains(s1[i][j])) { // 为非终结符
if (toEpsilon[s1[i][j]]) {
len--; // 删去该终结符,右部字符数 - 1
if (len == 0) { // 全部删了, 则为 true
toEpsilon[s2] = true;
break;
}
} else {
curr[s2][i] = ''; // 删去该产生式
record2[s2]--;
if (record2[s2] == 0) {
toEpsilon[s2] = false;
break;
}
}
}
}
}
}
judge++;
}
}