帮我写计算first和follow集的c++代码
时间: 2023-10-11 11:23:06 浏览: 123
好的,下面是C++代码实现:
```cpp
#include <iostream>
#include <vector>
#include <unordered_set>
#include <unordered_map>
using namespace std;
// 存放产生式
vector<string> productions = {
"S->AB",
"A->aA|b",
"B->cB|d"
};
// 存放每个非终结符的 FIRST 集
unordered_map<char, unordered_set<char>> first;
// 存放每个非终结符的 FOLLOW 集
unordered_map<char, unordered_set<char>> follow;
// 判断是否为终结符
bool is_terminal(char c) {
return !isupper(c);
}
// 计算 FIRST 集
void calc_first(char c) {
// 如果已经计算过了,直接返回
if (first.find(c) != first.end()) {
return;
}
// 新建一个集合
unordered_set<char> s;
// 如果是终结符,直接加入
if (is_terminal(c)) {
s.insert(c);
} else {
// 否则遍历该非终结符的所有产生式
for (auto &p : productions) {
// 如果产生式左边是该非终结符
if (p[0] == c) {
// 如果右边第一个字符是该非终结符本身,递归计算其 FIRST 集
if (!is_terminal(p[2])) {
calc_first(p[2]);
// 把其 FIRST 集加到当前集合中
for (auto &ch : first[p[2]]) {
s.insert(ch);
}
} else {
// 否则直接加入字符
s.insert(p[2]);
}
}
}
}
// 把集合加入到 FIRST 集中
first[c] = s;
}
// 计算 FOLLOW 集
void calc_follow(char c) {
// 如果已经计算过了,直接返回
if (follow.find(c) != follow.end()) {
return;
}
// 新建一个集合
unordered_set<char> s;
// 如果是起始符号,加入 $
if (c == productions[0][0]) {
s.insert('$');
}
// 遍历所有产生式
for (auto &p : productions) {
// 查找该非终结符在产生式中的位置
auto pos = p.find(c);
if (pos == string::npos) {
continue;
}
// 如果该非终结符不在产生式最后一个位置
if (pos + 1 < p.size()) {
// 如果后面是终结符,直接加入
if (is_terminal(p[pos + 1])) {
s.insert(p[pos + 1]);
} else {
// 否则加入该非终结符的 FIRST 集
calc_first(p[pos + 1]);
for (auto &ch : first[p[pos + 1]]) {
s.insert(ch);
}
}
} else {
// 如果该非终结符在产生式最后一个位置或者后面是空串,则递归计算左边非终结符的 FOLLOW 集
calc_follow(p[0]);
for (auto &ch : follow[p[0]]) {
s.insert(ch);
}
}
}
// 把集合加入到 FOLLOW 集中
follow[c] = s;
}
int main() {
// 计算所有非终结符的 FIRST 集
for (auto &p : productions) {
calc_first(p[0]);
}
// 计算所有非终结符的 FOLLOW 集
for (auto &p : productions) {
for (auto &ch : p) {
if (!is_terminal(ch)) {
calc_follow(ch);
}
}
}
// 输出结果
for (auto &p : productions) {
cout << "FIRST(" << p[0] << ")={";
for (auto &ch : first[p[0]]) {
cout << ch << ",";
}
cout << "}" << endl;
cout << "FOLLOW(" << p[0] << ")={";
for (auto &ch : follow[p[0]]) {
cout << ch << ",";
}
cout << "}" << endl;
}
return 0;
}
```
该代码实现了计算文法的 FIRST 和 FOLLOW 集,以及输出结果。其中,文法产生式存放在 `productions` 数组中,非终结符的 FIRST 和 FOLLOW 集分别存放在 `first` 和 `follow` 哈希表中。
阅读全文