生成FIRST集和FOLLOW集
时间: 2023-10-22 15:11:49 浏览: 94
在编译原理中,FIRST集和FOLLOW集是用来辅助LL(1)语法分析的重要工具,它们分别表示一个文法符号能够推导出的所有串的首字符集合和尾字符集合。下面是生成FIRST集和FOLLOW集的算法:
1. 生成FIRST集:
(1)对于终结符号,其FIRST集合就是它本身。
(2)对于非终结符号A,如果存在产生式A→aβ,则将a加入A的FIRST集合中。
(3)如果存在产生式A→ε,则将ε加入A的FIRST集合中。
(4)如果存在产生式A→B1B2...Bn,则将B1的FIRST集合中除ε外的所有元素加入A的FIRST集合中。如果B1的FIRST集合中包含ε,则将B2的FIRST集合中除ε外的所有元素加入A的FIRST集合中,以此类推,直到Bn的FIRST集合中不包含ε为止。
2. 生成FOLLOW集:
(1)将文法开始符号的FOLLOW集合设为$。
(2)对于每个产生式A→αBβ,将B的FOLLOW集合中的所有元素加入β的FIRST集合中,如果β的FIRST集合中包含ε,则将A的FOLLOW集合加入B的FOLLOW集合中。
(3)重复步骤(2),直到没有新的元素可以被加入为止。
以上就是生成FIRST集和FOLLOW集的算法。需要注意的是,这些算法可以应用于任何类型的文法,但是对于某些文法(如左递归文法),需要进行一些特殊处理。
相关问题
帮我写一段根据产生式生成first集和follow集的代码
好的,以下是一个简单的 Python 代码示例:
```
# 产生式列表
productions = [
('E', ['T', 'E\'']),
('E\'', ['+', 'T', 'E\'']),
('E\'', []),
('T', ['F', 'T\'']),
('T\'', ['*', 'F', 'T\'']),
('T\'', []),
('F', ['(', 'E', ')']),
('F', ['id'])
]
# first集和follow集
first = {}
follow = {}
# 计算first集
def calc_first(symbol):
if symbol in first:
return first[symbol]
first[symbol] = set()
for production in productions:
if production[0] == symbol:
if len(production[1]) == 0:
first[symbol].add('ε')
else:
for i in range(len(production[1])):
first[symbol].update(calc_first(production[1][i]))
if 'ε' not in first[production[1][i]]:
break
return first[symbol]
# 计算follow集
def calc_follow(symbol):
if symbol in follow:
return follow[symbol]
follow[symbol] = set()
if symbol == productions[0][0]:
follow[symbol].add('$')
for production in productions:
for i in range(len(production[1])):
if production[1][i] == symbol:
if i == len(production[1]) - 1:
follow[symbol].update(calc_follow(production[0]))
else:
for j in range(i+1, len(production[1])):
follow[symbol].update(calc_first(production[1][j]))
if 'ε' not in calc_first(production[1][j]):
break
else:
follow[symbol].update(calc_follow(production[0]))
return follow[symbol]
# 计算所有符号的first集和follow集
for production in productions:
calc_first(production[0])
calc_follow(production[0])
# 输出结果
print('First集:')
for key, value in first.items():
print(key, value)
print('\nFollow集:')
for key, value in follow.items():
print(key, value)
```
这段代码适用于 LL(1) 文法,可以根据需要进行修改。需要注意的是,这里默认空串为 'ε',如果你的文法中使用的是其他符号,请修改代码中的相关部分。
帮我用c++写一段根据产生式生成first集和follow集的代码
好的,以下是用C++实现的根据产生式生成first集和follow集的代码:
```cpp
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
// 存储产生式的结构体
struct Production {
char left; // 左部非终结符
vector<string> right; // 右部产生式
};
// 产生式列表
vector<Production> productions = {
{'E', {"T", "E'"}},
{'E\'', {"+", "T", "E'"}},
{'E\'', {}},
{'T', {"F", "T'"}},
{'T\'', {"*", "F", "T'"}},
{'T\'', {}},
{'F', {"(", "E", ")"}},
{'F', {"id"}}
};
// first集
unordered_map<char, vector<string>> first;
// follow集
unordered_map<char, vector<string>> follow;
// 判断字符是否为终结符
bool isTerminal(char c) {
return !isupper(c);
}
// 计算first集
void calcFirst() {
for (auto &p : productions) {
char left = p.left;
for (auto &s : p.right) {
// 如果产生式右部第一个字符是终结符或空串,则将其加入first集
if (isTerminal(s[0]) || s == "") {
first[left].push_back(s);
} else {
// 如果产生式右部第一个字符是非终结符,则将其first集中的元素加入当前非终结符的first集
for (auto &f : first[s[0]]) {
if (f != "") {
first[left].push_back(f);
}
}
// 如果产生式右部第一个字符的first集中包含空串,则继续遍历后面的字符
if (first[s[0]].size() > 0 && first[s[0]][0] == "") {
for (int i = 1; i < s.size(); ++i) {
// 如果后面的字符是终结符,则将其加入first集
if (isTerminal(s[i])) {
first[left].push_back(string(1, s[i]));
break;
} else {
// 如果后面的字符是非终结符,则将其first集中的元素加入当前非终结符的first集
bool flag = false;
for (auto &f : first[s[i]]) {
if (f != "") {
first[left].push_back(f);
} else {
flag = true;
}
}
// 如果后面的字符的first集不包含空串,则退出循环
if (!flag) {
break;
}
}
}
// 如果后面的字符都能推出空串,则将空串加入当前非终结符的first集
if (s.back() != "" && !isTerminal(s.back())) {
first[left].push_back("");
}
}
}
}
}
}
// 计算follow集
void calcFollow() {
follow['E'].push_back("#"); // 将结束符号加入起始非终结符E的follow集
bool flag = true;
while (flag) {
flag = false;
for (auto &p : productions) {
char left = p.left;
for (auto &s : p.right) {
for (int i = 0; i < s.size(); ++i) {
if (!isTerminal(s[i])) {
// 如果当前字符是非终结符
if (i == s.size() - 1) {
// 如果当前字符是产生式右部的最后一个字符,则将产生式左部的follow集加入当前非终结符的follow集
for (auto &f : follow[left]) {
if (find(follow[s[i]].begin(), follow[s[i]].end(), f) == follow[s[i]].end()) {
follow[s[i]].push_back(f);
flag = true;
}
}
} else {
bool hasEmpty = false;
// 如果当前字符后面有其他字符,则将后面的字符的first集中不包含空串的元素加入当前非终结符的follow集
for (int j = i + 1; j < s.size(); ++j) {
for (auto &f : first[s[j]]) {
if (f != "") {
if (find(follow[s[i]].begin(), follow[s[i]].end(), f) == follow[s[i]].end()) {
follow[s[i]].push_back(f);
flag = true;
}
} else {
hasEmpty = true;
}
}
if (!hasEmpty) {
break;
}
}
// 如果后面的字符都能推出空串,则将产生式左部的follow集加入当前非终结符的follow集
if (hasEmpty) {
for (auto &f : follow[left]) {
if (find(follow[s[i]].begin(), follow[s[i]].end(), f) == follow[s[i]].end()) {
follow[s[i]].push_back(f);
flag = true;
}
}
}
}
}
}
}
}
}
}
// 输出first集
void printFirst() {
cout << "First集:" << endl;
for (auto &f : first) {
cout << f.first << " : { ";
for (auto &s : f.second) {
cout << s << " ";
}
cout << "}" << endl;
}
}
// 输出follow集
void printFollow() {
cout << "Follow集:" << endl;
for (auto &f : follow) {
cout << f.first << " : { ";
for (auto &s : f.second) {
cout << s << " ";
}
cout << "}" << endl;
}
}
int main() {
calcFirst();
calcFollow();
printFirst();
printFollow();
return 0;
}
```
以上代码实现了根据产生式生成first集和follow集的功能,并对文法`E -> T E' ; E' -> + T E' | ε ; T -> F T' ; T' -> * F T' | ε ; F -> ( E ) | id`进行了测试。其中,first集和follow集使用了unordered_map进行存储,isTerminal函数用于判断一个字符是否为终结符,calcFirst函数用于计算first集,calcFollow函数用于计算follow集,printFirst函数用于输出first集,printFollow函数用于输出follow集。
阅读全文