-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathFF.cpp
More file actions
328 lines (268 loc) · 9.38 KB
/
FF.cpp
File metadata and controls
328 lines (268 loc) · 9.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
#include <bits/stdc++.h>
using namespace std;
const char * output_path = "./ff.txt";
ofstream output_file(output_path);
unordered_map<string, vector<string>> production; // 存放产生式
unordered_map<string, unordered_set<string>> FirstSet; // 存放 FIRST 集合
unordered_map<string, unordered_set<string>> FirstSetBeta; // 存放 β 的 FIRST 集合
unordered_map<string, unordered_set<string>> FollowSet; // 存放 FOLLOW 集合
unordered_set<string> VnSet; // 存放非终结符集合
unordered_set<string> VtSet; // 存放终结符集合
string start = "program"; // 开始符号
static string path = "grammar.txt";
vector<string> getFileContext(string path) {
ifstream file(path);
vector<string> content;
string line;
while (getline(file, line)) {
content.push_back(line);
}
return content;
}
vector<string> split(const string str, const string delimiter) {
vector<string> tokens;
if (delimiter.empty()) {
return tokens; // 如果分隔符为空,直接返回空向量
}
int start = 0;
int end = str.find(delimiter);
while (end != string::npos) {
tokens.push_back(str.substr(start, end - start));
start = end + delimiter.length();
end = str.find(delimiter, start);
}
tokens.push_back(str.substr(start)); // 添加最后一个 token
return tokens;
}
// 去除空白字符
string trim(const string& str) {
if (str.empty()) return ""; // 如果字符串为空,直接返回空字符串
int first = str.find_first_not_of(" \t\n\r");
int last = str.find_last_not_of(" \t\n\r");
return str.substr(first, last - first + 1); // 提取去除空白后的子串
}
/**
* 将产生式存储到production,划分终结符和非终结符
*/
static void dividechar() {
vector<string> grammarStr = {};
grammarStr = getFileContext("./output/grammar.txt");
for (string str : grammarStr) {
vector<string> parts = split(str, "->");
std::cout << "Read production : " << str << std::endl;
string left = trim(parts[0]);
string right = trim(parts[1]);
// 如果 left 存在则取出其 vector,否则创建新 vector
vector<string>& list = production[left];
list.push_back(right);
VnSet.insert(left); // 在产生式左边的一定是非终结符
}
// 寻找终结符
for (const string& ch : VnSet) {
for (const string& str : production[ch]) {
vector<string> rightItems = split(str, " ");
for (const string& c : rightItems) {
if (VnSet.find(c) == VnSet.end()) { // 若非终结符集合中不包含该符号
VtSet.insert(c); // 添加到终结符集合
}
}
}
}
output_file << "**************t*****************" << endl;
for (string ch : VtSet) {
output_file << ch << endl;
}
output_file << "**************not t*****************" << endl;
for (string ch : VnSet) {
output_file << ch << endl;
}
}
void getfirst(const string& ch);
void First() {
// 遍历求每一个非终结符的 FIRST 集
for (const string& vn : VnSet) {
getfirst(vn);
}
}
void getfirst(const string& ch) {
vector<string> ch_production = production[ch]; // 获取该符号的产生式
unordered_set<string>& set = FirstSet[ch]; // FIRST 集合
// 当 ch 为终结符
if (VtSet.count(ch)) {
set.insert(ch);
return;
}
// ch 为非终结符
for (const string& str : ch_production) {
vector<string> temp2 = split(str, " ");
int i = 0;
while (i < temp2.size()) {
string tn = temp2[i];
getfirst(tn); // 递归调用
unordered_set<string>& tvSet = FirstSet[tn];
// 将 tn 的 FIRST 集加入到 ch 的 FIRST 集
for (const string& tmp : tvSet) {
if (tmp != "$") {
set.insert(tmp);
}
}
// 若 tn 的 FIRST 集包含空串,处理下一个符号
if (tvSet.count("$")) {
i++;
} else {
break;
}
}
// 若所有符号的 FIRST 集中均包含 "$"
if (i == temp2.size()) {
set.insert("$");
}
}
}
void getFirstBeta(const string& s) {
unordered_set<string>& set = FirstSetBeta[s]; // 获取或初始化 FirstSetBeta[s]
vector<string> temp3 = split(s, " ");
int i = 0;
while (i < temp3.size()) {
string tn = temp3[i];
// 如果 tn 不在 FirstSet 中,调用 getfirst 计算
if (FirstSet.find(tn) == FirstSet.end()) {
getfirst(tn);
}
// 获取 tn 的 FIRST 集合
const unordered_set<string>& tvSet = FirstSet[tn];
// 将非空的元素加入到 set
for (const string& tmp : tvSet) {
if (tmp != "$") {
set.insert(tmp);
}
}
// 如果 tvSet 包含空串,则处理下一个符号
if (tvSet.find("$") != tvSet.end()) {
i++;
} else {
break;
}
// 若已到达尾部且所有符号的 FIRST 集均包含空串
if (i == temp3.size()) {
set.insert("$");
}
}
// 更新 FirstSetBeta
FirstSetBeta[s] = set;
}
void getFollow(const string& c);
void Follow() {
for (int i = 0; i < 100; i++) {
for (const string& ch : VnSet) {
getFollow(ch);
}
}
}
void getFollow(const string& c) {
vector<string> list = production[c];
unordered_set<string>& setA = FollowSet[c];
// 如果是开始符号,添加 #
if (c == start) {
setA.insert("#");
}
// 计算初始 FOLLOW 集
for (const string& ch : VnSet) {
vector<string> l = production[ch];
for (const string& s : l) {
vector<string> rightItem = split(s, " ");
for (int i = 0; i < rightItem.size(); i++) {
if (rightItem[i] == c && i + 1 < rightItem.size() && VtSet.count(rightItem[i + 1])) {
setA.insert(rightItem[i + 1]);
}
}
}
}
FollowSet[c] = setA;
// 处理 c 的每个产生式,计算产生式右部各非终结符的 FOLLOW 集
for (const string& s : list) {
vector<string> rightItem = split(s, " ");
int i = rightItem.size() - 1;
// 从右向左遍历
while (i >= 0) {
string tn = rightItem[i];
// 处理非终结符
if (VnSet.count(tn)) {
if (i < rightItem.size() - 1) {
string right;
for (int j = i + 1; j < rightItem.size(); j++) {
right += rightItem[j] + " ";
}
right = right.substr(0, right.size() - 1); // 去掉尾部空格
// 计算 FIRST(β)
if (!FirstSetBeta.count(right)) {
getFirstBeta(right);
}
unordered_set<string> setF = FirstSetBeta[right];
// 将 β 的非空 FIRST 集加入到 FOLLOW(tn)
unordered_set<string>& setX = FollowSet[tn];
for (const string& var : setF) {
if (var != "$") {
setX.insert(var);
}
}
FollowSet[tn] = setX;
// 若 FIRST(β) 包含空串,将 FOLLOW(c) 加入 FOLLOW(tn)
if (setF.count("$")) {
if (tn != c) {
unordered_set<string>& setB = FollowSet[tn];
setB.insert(setA.begin(), setA.end());
FollowSet[tn] = setB;
}
}
}
// 若 β 不存在,将 FOLLOW(c) 加入 FOLLOW(tn)
else {
if (tn != c) {
unordered_set<string>& setB = FollowSet[tn];
setB.insert(setA.begin(), setA.end());
FollowSet[tn] = setB;
}
}
}
i--;
}
}
}
void output() {
output_file << "************* FIRST ************" << endl;
for (const string& c : VnSet) {
const unordered_set<string>& set = FirstSet[c];
output_file << setw(18) << c << " -> ";
for (const string& var : set) {
output_file << var << " ";
}
output_file << endl;
}
output_file << endl;
output_file << "************** FOLLOW *************" << endl;
for (const string& c : VnSet) {
const unordered_set<string>& set = FollowSet[c];
output_file << setw(18) << c << " : ";
for (const string& var : set) {
output_file << var << " ";
}
output_file << endl;
}
output_file << endl;
}
int main() {
dividechar(); // 划分终结符与非终结符
First(); // 计算 First 集合
// 对每个非终结符的产生式调用 getFirstBeta
for (const string& c : VnSet) {
vector<string> l = production[c];
for (const string& s : l) {
getFirstBeta(s);
}
}
Follow(); // 计算 Follow 集合
output(); // 打印结果
output_file.close();
return 0;
}