实验一:LL(1)预测分析表设计与实现

前置知识

1.C++中输出csv格式的文件(分隔符为","

#include <fstream>
ofstream p;
string file_path = "output" + to_string(sum) + ".csv";
p.open(file_path, ios::out | ios::trunc);
p << "," << *vn << "->" << M[*vn][*vt];

核心操作

//SELECT集
string M[255][255];

1.select 函数的主要步骤
*初始化预测分析表 (M): 预测分析表M 是一个二维数组,初始化时,所有元素设置为空字符串。
*处理每个非终结符:
*遍历每个非终结符的产生式。
*对于每个产生式,计算其 SELECT 集合,这个集合决定了在预测分析表中的填充位置。
*计算 SELECT 集合:
*对于每个产生式,首先计算其首字符串(即产生式右侧)的 FIRST 集合。
*如果 FIRST 集合包含空串($),则将产生式左侧非终结符的 FOLLOW 集合也并入 SELECT 集合中,并从 SELECT 集合中移除空串。
*如果 FIRST 集合不包含空串,则直接将 FIRST 集合并入 SELECT 集合。
*填充预测分析表:
*对于 SELECT 集合中的每个终结符,将产生式填入预测分析表的对应位置。
*例如,如果A->α 的 SELECT 集合包含终结符b,则将α 填入表中M[A][b] 的位置。
2.打印 SELECT 集合:为了验证和调试,函数在计算每个产生式的 SELECT 集合后打印它。

具体实现

#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#include <string>
#include <fstream>
using namespace std;

//G文法结构体
struct G {
	int Vt_number;
	int Vn_number;
	int P_number;
	set<char> Vt;
	set<char> Vn;
	char S;
	vector<string> P[255];
}G_instance;

//打印文法
void printG() {
	cout << "Vt is:";
	for (auto i = G_instance.Vt.begin(); i != G_instance.Vt.end(); i++) {
		cout << *i << " ";
	}
	cout << endl;
	cout << "Vn is:";
	for (auto i = G_instance.Vn.begin(); i != G_instance.Vn.end(); i++) {
		cout << *i << " ";
	}
	cout << endl;
	for (auto i = G_instance.Vn.begin(); i != G_instance.Vn.end(); i++) {
		if (!G_instance.P[*i].empty()) {
			for (auto p = G_instance.P[*i].begin(); p != G_instance.P[*i].end(); p++) {
				cout << *i << "->" << *p << endl;
			}
		}
	}
}

//FIRST集
set<char> First[255];

set<char> first_string_set;
void first_string(string str) {
	first_string_set.clear();
	for (int i = 0; i < str.length(); i++) {
		set<char> temp_first_sub_string;
		set_union(temp_first_sub_string.begin(), temp_first_sub_string.end(), First[str[i]].begin(), First[str[i]].end(), inserter(temp_first_sub_string, temp_first_sub_string.begin()));
		if (First[str[i]].find('$') != First[str[i]].end() && i != str.length() - 1) {
			temp_first_sub_string.erase('$');
			set_union(temp_first_sub_string.begin(), temp_first_sub_string.end(), first_string_set.begin(), first_string_set.end(), inserter(first_string_set, first_string_set.end()));
		}
		else {
			set_union(temp_first_sub_string.begin(), temp_first_sub_string.end(), first_string_set.begin(), first_string_set.end(), inserter(first_string_set, first_string_set.end()));
			break;
		}
	}
}

void check() {
	for (auto vn = G_instance.Vn.begin(); vn != G_instance.Vn.end(); vn++) {
		if (!G_instance.P[*vn].empty()) {
			for (auto p = G_instance.P[*vn].begin(); p != G_instance.P[*vn].end(); p++) {
				first_string(*p);
				set_union(first_string_set.begin(), first_string_set.end(), First[*vn].begin(), First[*vn].end(), inserter(First[*vn], First[*vn].begin()));
			}
		}
	}
}


void first() {
	//flag为1表示first集有更新
	//      0表示first集无更新
	int flag = 1;
	while (flag == 1) {
		flag = 0;
		for (auto i = G_instance.Vn.begin(); i != G_instance.Vn.end(); i++) {
			//遍历非终结符号*i的产生式
			//*p为当前的产生式
			int len = First[*i].size();
			if (!G_instance.P[*i].empty()) {
				for (auto p = G_instance.P[*i].begin(); p != G_instance.P[*i].end(); p++) {
					//首字符为终结符号
					if (G_instance.Vt.find((*p)[0]) != G_instance.Vt.end()) {
						First[*i].insert((*p)[0]);
					}
					else {
						//首字符为非终结符号
						for (int index = 0; index < (*p).length(); index++) {
							//temp为FIRST(Y_k)
							set<char> temp;
							set_union(temp.begin(), temp.end(), First[(*p)[index]].begin(), First[(*p)[index]].end(), inserter(temp, temp.begin()));
							if (temp.find('$') != temp.end() && index != (*p).length() - 1) {
								temp.erase('$');
								set_union(First[*i].begin(), First[*i].end(), temp.begin(), temp.end(), inserter(First[*i], First[*i].end()));
							}
							else {
								set_union(First[*i].begin(), First[*i].end(), temp.begin(), temp.end(), inserter(First[*i], First[*i].end()));
								break;
							}
						}
					}
				}
			}
			int new_len = First[*i].size();
			if (new_len > len) {
				flag = 1;
			}
		}
	}
	//终结符号的first集
	for (auto i = G_instance.Vt.begin(); i != G_instance.Vt.end(); i++) {
		First[*i].insert(*i);
	}
	check();
}

//打印first集
void print_first() {
	for (auto i = G_instance.Vn.begin(); i != G_instance.Vn.end(); i++) {
		cout << "first(" << *i << "):";
		for (auto item = First[*i].begin(); item != First[*i].end(); item++) {
			cout << *item << " ";
		}
		cout << endl;
	}
}


//FOLLOW集
//#表示结束标志
set<char> Follow[255];
void follow() {
	Follow[G_instance.S].insert('#');
	//flag为1表示FOLLOW集有更新
	//		0			 无更新
	int flag = 1;
	while (flag == 1) {
		flag = 0;
		for (auto i = G_instance.Vn.begin(); i != G_instance.Vn.end(); i++) {
			//遍历非终结符号*i
			if (!G_instance.P[*i].empty()) {
				for (auto p = G_instance.P[*i].begin(); p != G_instance.P[*i].end(); p++) {
					//*p为当前非终结符号*i->产生式*p
					for (int j = 0; j < (*p).length(); j++) {
						char temp_vn = (*p)[j];
						int len = Follow[temp_vn].size();
						if (G_instance.Vn.find(temp_vn) != G_instance.Vn.end()) {
							//当前字符为产生式中最后一个字符
							if (j == (*p).length() - 1) {
								set_union(Follow[temp_vn].begin(), Follow[temp_vn].end(), Follow[*i].begin(), Follow[*i].end(), inserter(Follow[temp_vn], Follow[temp_vn].end()));
							}
							else {
								string temp_string = (*p).substr(j + 1, (*p).length() - j - 1);
								//后继first集中包含空
								first_string(temp_string);
								if (first_string_set.find('$') != first_string_set.end()) {
									first_string_set.erase('$');
									set_union(first_string_set.begin(), first_string_set.end(), Follow[temp_vn].begin(), Follow[temp_vn].end(), inserter(Follow[temp_vn], Follow[temp_vn].end()));
									set_union(Follow[temp_vn].begin(), Follow[temp_vn].end(), Follow[*i].begin(), Follow[*i].end(), inserter(Follow[temp_vn], Follow[temp_vn].end()));
								}
								else {
									//后继first集不含空
									set_union(first_string_set.begin(), first_string_set.end(), Follow[temp_vn].begin(), Follow[temp_vn].end(), inserter(Follow[temp_vn], Follow[temp_vn].end()));
								}
							}
						}
						if (len < Follow[temp_vn].size()) {
							flag = 1;
						}
					}
				}
			}
		}
	}
}

void print_follow() {
	for (auto i = G_instance.Vn.begin(); i != G_instance.Vn.end(); i++) {
		cout << "follow(" << *i << "):";
		for (auto item = Follow[*i].begin(); item != Follow[*i].end(); item++) {
			cout << *item << " ";
		}
		cout << endl;
	}
}

//SELECT集
string M[255][255];
void select() {
	//初始化M
	for (int i = 0; i < 255; i++) {
		for (int j = 0; j < 255; j++) {
			M[i][j] = "";
		}
	}
	for (auto i = G_instance.Vn.begin(); i != G_instance.Vn.end(); i++) {
		//遍历非终结符号*i
		if (!G_instance.P[*i].empty()) {
			for (auto p = G_instance.P[*i].begin(); p != G_instance.P[*i].end(); p++) {
				//*p为当前非终结符号*i->产生式*p
				set<char> select;
				first_string(*p);
				if (first_string_set.find('$') != first_string_set.end()) {
					set_union(Follow[*i].begin(), Follow[*i].end(), select.begin(), select.end(), inserter(select, select.end()));
				}
				first_string_set.erase('$');
				set_union(first_string_set.begin(), first_string_set.end(), select.begin(), select.end(), inserter(select, select.end()));
				for (auto select_ = select.begin(); select_ != select.end(); select_++) {
					M[*i][*select_] = *p;
				}
				cout << "SELECT(" << *i << "->" << *p << "):";
				for (auto p_s = select.begin(); p_s != select.end(); p_s++) {
					cout << *p_s << " ";
				}
				cout << endl;
			}
		}
	}
}

void print_select(int sum) {
	ofstream p;
	string file_path = "output" + to_string(sum) + ".csv";
	p.open(file_path, ios::out | ios::trunc);
	p << "Vn" << ",";
	set<char> input_set;
	set_union(input_set.begin(), input_set.end(), G_instance.Vt.begin(), G_instance.Vt.end(), inserter(input_set, input_set.begin()));
	input_set.erase('$');
	input_set.insert('#');
	for (auto vt = input_set.begin(); vt != input_set.end(); vt++) {
		p << *vt << ",";
	}
	p << endl;
	for (auto vn = G_instance.Vn.begin(); vn != G_instance.Vn.end(); vn++) {
		p << *vn;
		for (auto vt = input_set.begin(); vt != input_set.end(); vt++) {
			if (M[*vn][*vt] != "") {
				p << "," << *vn << "->" << M[*vn][*vt];
			}
			else {
				p << "," << " ";
			}
		}
		p << endl;
	}
	p.close();
}

void clear() {
	G_instance.P_number = 0;
	G_instance.Vn_number = 0;
	G_instance.Vt_number = 0;
	G_instance.S = ' ';
	for (int i = 0; i < 255; i++) {
		G_instance.P[i].clear();
		Follow[i].clear();
		First[i].clear();
	}
	G_instance.Vn.clear();
	G_instance.Vt.clear();
	first_string_set.clear();
	for (int i = 0; i < 255; i++) {
		for (int j = 0; j < 255; j++) {
			M[i][j] = "";
		}
	}
}

int main() {
	string file_path = "./FIRST-FOLLOW.txt";
	ifstream file(file_path);
	string arr[100];
	int count = 0;
	int sum = 0;
	while (getline(file, arr[count]) && count < 100) {
		if (arr[count].empty()) {
			clear();
			G_instance.P_number = count;
			G_instance.S = arr[0][0];
			for (int i = 0; i < count; i++) {
				int len = arr[i].length();
				string str = arr[i];
				G_instance.Vn.insert(str[0]);
				G_instance.P[str[0]].push_back(str.substr(2, len - 2));
				for (int index = 0; index < len; index++) {
					if ((str[index] >= 'a' && str[index] <= 'z') || str[index] == '$') {
						G_instance.Vt.insert(str[index]);
					}
				}
			}
			G_instance.Vt_number = G_instance.Vt.size();
			G_instance.Vn_number = G_instance.Vn.size();
			printG();
			cout << endl;
			count = 0;
			first();
			print_first();
			follow();
			print_follow();
			select();
			sum++;
			print_select(sum);
			cout << endl;
		}
		else {
			count++;
		}
	}
	file.close();
	return 0;
}
  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值