LL(1)预测分析法

 

  • 实验目的
  1. 了解LL(1)预测分析法适用的文法特征。
  2. 了解LL(1)预测分析法基本结构。
  3. 理解LL(1)预测分析法基本原理,编程实现,并验证。
  • 实验预备知识
  1. 理解表驱动的LL(1)预测分析法中预测表的求解和作用。
  2. 参考配套教材《编译原理》预测分析法原理与方法。

 

 

#include <fstream>
#include<iostream>
#include<string>
#include<vector>
#include<set>
#include<unordered_map>
#include<stack>
#include <iomanip>
using namespace std;

typedef string  variable;//变量
typedef string  terminal;//终结符
typedef string  start;//开始符号

typedef struct production//产生式
{
	string left;
	vector<string> right;//将右部的产生式按照每一个变量和每一个终结符分割放入右部数组
}proudction;

typedef struct grammar
{
	set<variable> V;//变量集合
	set<terminal> T;//终结符集合
	vector<production> P;//产生式
	start S;//开始符号
	unordered_map<variable, set<terminal>>FIRST;//FIRST集合
	unordered_map<variable, set<terminal>>FLLOW;//FLLOW集合
}grammar;

unordered_map<variable, unordered_map<terminal, vector<string>>>foresee_table;//预测分析表

int split(vector<production>& pro, string s)//分割字符串取出产生式左部和右部
{
	production p;
	int i = 0;
	int spLR = -1;
	for (i; i < s.size() - 1; i++)
	{
		if (s[i] == '-' && s[i + 1] == '>')
		{
			spLR = i;
			break;
		}
	}
	if (i == 0 || i >= s.size())
	{
		cout << endl << "这个产生式" << s << "错误!!!请重新输入";
		return -1;
	}
	p.left = s.substr(0, i);
	s.erase(0, i + 2);

	p.right.push_back("");
	for (i = 0; i < s.size(); i++)
	{
		if (s[i] == '|')
		{
			if (p.right[0].size() == 0)
			{
				p.right[0] = "$";
			}
			pro.push_back(p);
			p.right[0] = "";
		}
		else
		{
			p.right[0] = p.right[0] + s[i];
		}
	}
	if (p.right[0].size() == 0)
	{
		p.right[0] = "$";
	}
	pro.push_back(p);
	return 0;
}

int getV_PR_S(grammar& G)//获得文法的变量,获得开始符号,以一个变量和一个终结符为单位分割产生式的右部
{
	G.S = G.P[0].left;//获得开始符号
	for (int i = 0; i < G.P.size(); i++)//获得变量
	{
		G.V.insert(G.P[i].left);
	}
	//以单一变量或者终结符为单位分割产生式右部
	for (int i = 0; i < G.P.size(); i++)
	{
		string s = G.P[i].right[0];//获得此时的产生式
		G.P[i].right.clear();//清空产生式右部分
		if (s == "$")//如果此时的产生式本身就是空的话把$加入右部之后直接进入下一次循环
		{
			G.P[i].right.push_back("$");
			continue;
		}
		int flag = 0;
		while (flag != 1)
		{
			flag = 1;
			int x = s.size();
			for (auto j = G.V.begin(); j != G.V.end(); j++)//先用变量集合去匹配
			{
				string v = *j;
				if (v.size() > s.size())//如果此时变量长度大于字符长度了就匹配下一个变量
				{
					continue;
				}
				string prfv = s.substr(s.size() - v.size(), v.size());
				//cout <<v<<":" << prfv;
				if (v == prfv)
				{
					G.P[i].right.insert(G.P[i].right.begin(), v);
					//cout << G.P[i].right[0] << " ";
					s.erase(s.size() - v.size());
				}
				//cout << endl;

			}

			for (auto j = G.T.begin(); j != G.T.end(); j++)//再用终结符集合去匹配
			{
				string t = *j;
				if (t.size() > s.size())//如果此时终结符长度大于字符长度了就匹配下一个终结符
				{
					continue;
				}
				string prft = s.substr(s.size() - t.size(), t.size());
				//cout << t << ":" << prft;
				if (t == prft)
				{
					G.P[i].right.insert(G.P[i].right.begin(), t);
					//cout << G.P[i].right[0] << " ";
					s.erase(s.size() - t.size());
				}
				//cout << endl;

			}
			if (s.size() < x)
			{
				flag++;
			}
		}
		if (s.size() > 0)
		{
			cout << "产生式中出现了不是变量也不是终结符的变量";
			exit(0);
		}
	}
}

int showG(grammar& G)
{
	cout << "\n\n终结符:";
	cout << endl << "\t";
	for (auto i = G.T.begin(); i != G.T.end(); i++)
	{
		cout << *i << " ";
	}
	cout << "\n\n变量:";
	cout << endl << "\t";
	for (auto i = G.V.begin(); i != G.V.end(); i++)
	{
		cout << *i << " ";
	}
	cout << "\n\n产生式:";
	cout << endl;
	for (int i = 0; i < G.P.size(); i++)
	{
		cout << "\t" << G.P[i].left << "->";
		for (int j = 0; j < G.P[i].right.size(); j++)
		{
			cout << G.P[i].right[j];
		}
		cout << endl;
	}
	cout << "\nFIRST集:";
	cout << endl;
	for (auto i = G.FIRST.begin(); i != G.FIRST.end(); i++)
	{
		cout << "\tFIRST(" << i->first << "):\t{ ";
		auto s = i->second.begin();
		s++;
		for (auto j = i->second.begin(); j != i->second.end(); j++)
		{
			cout << *j;
			if (s != i->second.end())
			{
				cout << ",";
				s++;
			}
		}
		cout << " }\n";
	}
	cout << "\nFOLLOW集:";
	cout << endl;
	for (auto i = G.FLLOW.begin(); i != G.FLLOW.end(); i++)
	{
		cout << "\tFOLLOW(" << i->first << "):\t{ ";
		auto s = i->second.begin();
		if(s!= i->second.end())
		      s++;
		for (auto j = i->second.begin(); j != i->second.end(); j++)
		{
			cout << *j;
			if (s != i->second.end())
			{
				cout << ",";
				s++;
			}
		}
		cout << " }\n";
	}
	return 0;
}

int getFIRST(grammar& G)
{
	//1.显式规则1
	int n = G.P.size();
	for (int i = 0; i < n; i++)
	{
		if (G.P[i].right.size() == 1 && G.P[i].right[0] == "$")
		{
			G.FIRST[G.P[i].left].insert("$");
		}
	}
	//2.显式规则2
	for (int i = 0; i < n; i++)
	{
		string s = G.P[i].right[0];
		if (G.T.find(s) != G.T.end())
		{
			G.FIRST[G.P[i].left].insert(s);
		}
	}
	//3.隐式规则1如果右边的第一个是变量的话把变量的first集合去空给first(左部)
	int flag = 0;
	while (flag != 1)
	{
		flag = 1;
		for (int i = 0; i < n; i++)
		{
			int num = G.FIRST[G.P[i].left].size();
			string s = G.P[i].right[0];
			if (G.V.find(s) != G.V.end())
			{
				set<terminal>se(G.FIRST[s]);
				se.erase("$");
				for (auto j = se.begin(); j != se.end(); j++)
				{
					G.FIRST[G.P[i].left].insert(*j);
				}
			}
			if (G.FIRST[G.P[i].left].size() > num)
			{
				flag++;
			}
		}
	}
	//4.隐式规则2和3
	flag = 0;
	while (flag != 1)
	{
		flag = 1;
		for (int i = 0; i < n; i++)
		{
			int num = G.FIRST[G.P[i].left].size();
			int m = G.P[i].right.size();
			int j = 0;
			for (; j < m; j++)
			{
				string s = G.P[i].right[j];
				if (G.V.find(s) != G.V.end() && G.FIRST[s].find("$") != G.FIRST[s].end())//这里是变量能推出来空
				{
					set<terminal>se(G.FIRST[s]);
					se.erase("$");
					for (auto j = se.begin(); j != se.end(); j++)
					{
						G.FIRST[G.P[i].left].insert(*j);
					}
				}
				else if (G.V.find(s) != G.V.end())//这里是变量不能推出来空
				{
					set<terminal>se(G.FIRST[s]);
					for (auto j = se.begin(); j != se.end(); j++)
					{
						G.FIRST[G.P[i].left].insert(*j);
					}
					break;
				}
				else//这里是终结符的FIRST集
				{
					G.FIRST[G.P[i].left].insert(s);
					break;
				}
			}
			if (j == m)
			{
				G.FIRST[G.P[i].left].insert("$");
			}
			if (G.FIRST[G.P[i].left].size() > num)
			{
				flag++;
			}
		}
	}
	//所有的终结符的first集是自己
	for (auto i = G.T.begin(); i != G.T.end(); i++)
	{
		G.FIRST[*i].insert(*i);
	}
	return 0;
}

int getFLLOW(grammar& G)
{
	//1.显式规则
	G.FLLOW[G.S].insert("#");
	//2.显式规则
	for (int i = 0; i < G.P.size(); i++)
	{
		for (int j = 0; j < G.P[i].right.size() - 1; j++)
		{
			if (G.V.find(G.P[i].right[j]) != G.V.end() && G.T.find(G.P[i].right[j + 1]) != G.T.end())
			{
				G.FLLOW[G.P[i].right[j]].insert(G.P[i].right[j + 1]);
				j++;
			}
		}
	}
	//3.隐式规则
	int flag = 0;
	while (flag != 1)
	{
		flag = 1;
		vector<int>flag1(G.V.size());
		int x = 0;
		for (auto vv = G.V.begin(); vv != G.V.end(); vv++, x++)
		{
			flag1[x] = G.FLLOW[*vv].size();
		}
		//cout << "***";
		//隐式规则1
		for (int i = 0; i < G.P.size(); i++)
		{
			int j = 0;
			for (; j < G.P[i].right.size() - 1; j++)
			{
				string s = G.P[i].right[j];
				if (G.V.find(s) != G.V.end())//此时的必须是变量
				{
					//把下一个字符的first集去空给这个变量的follow集
					set<terminal>se(G.FIRST[G.P[i].right[j + 1]]);
					if (se.find("$") != se.end())//如果此时后面的量的first集有空$
					{
						se.erase("$");
						for (auto seb = se.begin(); seb != se.end(); seb++)
						{
							G.FLLOW[s].insert(*seb);
						}
						set<terminal>se1(G.FLLOW[G.P[i].right[j + 1]]);
						for (auto se1b = se1.begin(); se1b != se1.end(); se1b++)
						{
							G.FLLOW[s].insert(*se1b);
						}
					}
					else
					{
						se.erase("$");
						for (auto seb = se.begin(); seb != se.end(); seb++)
						{
							G.FLLOW[s].insert(*seb);
						}
						//break;
					}
				}
			}

			if (j == G.P[i].right.size() - 1 && G.V.find(G.P[i].right[j]) != G.V.end())//如果此时已经走到右部末尾了且最后一个还是变量那就要把左部的follow集给这个变量了
			{
				for (auto f = G.FLLOW[G.P[i].left].begin(); f != G.FLLOW[G.P[i].left].end(); f++)
				{
					G.FLLOW[G.P[i].right[j]].insert(*f);
				}
			}
		}
		x = 0;
		for (auto vv = G.V.begin(); vv != G.V.end(); vv++, x++)
		{
			if (flag1[x] != G.FLLOW[*vv].size())
			{
				flag++;
				break;
			}
		}
	}
	return 0;
}

void getforesee_table(grammar G)//开始插入这个表
{
	for (auto i = G.V.begin(); i != G.V.end(); i++)
	{
		foresee_table[*i];
		for (auto j = G.T.begin(); j != G.T.end(); j++)
		{
			if (*j != "$")
			{
				foresee_table[*i][*j];
			}
		}
		foresee_table[*i]["#"];
	}
	for (int i = 0; i < G.P.size(); i++)
	{
		int j;
		for (j = 0; j < G.P[i].right.size(); j++)//通过右部分
		{
			int flag = 0;
			for (auto m = G.FIRST[G.P[i].right[j]].begin(); m != G.FIRST[G.P[i].right[j]].end(); m++)//通过右边部分的first集合往里面填写
			{
				if (*m != "$")
				{
					for (int s_z = 0; s_z < G.P[i].right.size(); s_z++)//这里是追加右部
					{
						foresee_table[G.P[i].left][*m].push_back(G.P[i].right[s_z]);
					}
				}
				else
				{
					flag = 1;
				}
			}
			if (flag == 0)
			{
				break;
			}
		}
		if (j >= G.P[i].right.size())
		{
			for (auto m = G.FLLOW[G.P[i].left].begin(); m != G.FLLOW[G.P[i].left].end(); m++)
			{
				foresee_table[G.P[i].left][*m].push_back("$");
			}
		}
	}
}

void show(grammar G)
{
	cout << "\n预测分析表为:" << endl;
	for (auto j = G.T.begin(); j != G.T.end(); j++)
	{
		if (*j != "$")
		{
			cout << "\t" << *j;
		}
	}
	cout << "\n";
	for (auto i = G.V.begin(); i != G.V.end(); i++)
	{
		foresee_table[*i];
		cout << *i << "\t";
		for (auto j = G.T.begin(); j != G.T.end(); j++)
		{
			if (*j != "$")
			{
				for (int m = 0; m < foresee_table[*i][*j].size(); m++)
				{
					cout << foresee_table[*i][*j][m];
				}
				cout << "\t";
			}
		}
		
		cout << endl;
	}
}

void split_sentence(string s, grammar G, vector<string>& sentence)
{
	int flag = 0;
	while (flag != 1)
	{
		flag = 1;
		int x = s.size();
		for (auto j = G.V.begin(); j != G.V.end(); j++)//先用变量集合去匹配
		{
			string v = *j;
			if (v.size() > s.size())//如果此时变量长度大于字符长度了就匹配下一个变量
			{
				continue;
			}
			string prfv = s.substr(s.size() - v.size(), v.size());
			if (v == prfv)
			{
				sentence.insert(sentence.begin(), v);
				s.erase(s.size() - v.size());
			}

		}
		for (auto j = G.T.begin(); j != G.T.end(); j++)//再用终结符集合去匹配
		{
			string t = *j;
			if (t.size() > s.size())//如果此时终结符长度大于字符长度了就匹配下一个终结符
			{
				continue;
			}
			string prft = s.substr(s.size() - t.size(), t.size());
			if (t == prft)
			{
				sentence.insert(sentence.begin(), t);
				s.erase(s.size() - t.size());
			}
		}
		if (s.size() < x)
		{
			flag++;
		}
	}
	sentence.push_back("#");
	if (s.size() > 0)
	{
		cout << "产生式中出现了不是变量也不是终结符的变量";
		exit(0);
	}
	/*
	for (int i = 0; i < sentence.size(); i++)
	{
		cout << sentence[i]<<"$";
	}
	*/
}

void foresee_analyze(vector<string>sentence,grammar&g)//用传进来的字符串数组完成
{
	stack<string>sta;
	sta.push("#");
	sta.push(g.S);
	int i = 0;
	string out = "";
	cout << "步骤\t\t栈\t\t输入缓存区\t\t输出\n";
	while (sta.top() != "#")
	{
		cout << i << "\t\t";
		stack<string>outsta;
		while (!sta.empty())
		{
			outsta.push(sta.top());
			sta.pop();
		}
		while (!outsta.empty())
		{
			cout << outsta.top();
			sta.push(outsta.top());
			outsta.pop();
		}
		cout << "\t\t";
		string se = "";
		for (int i = 0; i < sentence.size(); i++)
		{
			se = se + sentence[i];
		}
		cout << setw(8) << se;
		if (out == "")
		{
			cout << endl;
		}
		else
		{
			cout << "\t\t" << out << "\n";
		}
		out.clear();
		string st = sta.top();
		sta.pop();
		if (st == sentence[0])
		{
			i++;
			sentence.erase(sentence.begin());
			continue;
		}
		if (foresee_table[st][sentence[0]].size() == 0)
		{
			cout << "此句子不符合本文法";
			return ;
		}
		for (int i = foresee_table[st][sentence[0]].size() - 1; i >= 0; i--)
		{
			if (foresee_table[st][sentence[0]][i] != "$")
				sta.push(foresee_table[st][sentence[0]][i]);
		}
		out = out + st + "->";
		for (int i = 0; i < foresee_table[st][sentence[0]].size(); i++)
		{
			out = out + foresee_table[st][sentence[0]][i];
		}
		i++;
	}
	cout << i << "\t\t";
	stack<string>outsta;
	while (!sta.empty())
	{
		outsta.push(sta.top());
		sta.pop();
	}
	while (!outsta.empty())
	{
		cout << outsta.top();
		sta.push(outsta.top());
		outsta.pop();
	}
	cout << "\t\t";
	string se = "";
	for (int i = 0; i < sentence.size(); i++)
	{
		se = se + sentence[i];
	}
	cout << setw(8) << se;
	if (out == "")
	{
		cout << endl;
	}
	else
	{
		cout << "\t\t" << out << "\n";
	}
}

int main()
{
	ifstream infile;
	infile.open("production.txt");
	grammar G;
	string s;
	infile >> s;
	//cin >> s;
	cout << "请先输入终结符(输入stop表示终结符输入完成):\n";
	while (s != "stop")
	{
		G.T.insert(s);
		infile >> s;
		//cin >> s;
	}
	cout << "\n请输入产生式(输入stop表示产生式输入完毕):\n";
	infile >> s;
	//cin >> s;
	while (s != "stop")
	{
		split(G.P, s);
		infile >> s;
		//cin >> s;
	}
	getV_PR_S(G);
	getFIRST(G);
	getFLLOW(G);
	showG(G);
	getforesee_table(G);
	show(G);
	vector<string>setence;
	cout << "\n请输入要分析的式子:\n";
	infile >> s;
	split_sentence(s, G, setence);
	foresee_analyze(setence,G);
	infile.close();
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值