算符优先分析法

  • 实验目的
  1. 加深对语法分析器工作过程的理解;
  2. 加强对算符优先分析法实现语法分析程序的掌握;
  3. 能够釆用一种编程语言实现算符优先分析法总控程序;
  • 实验预备知识 
  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>>FIRSTOP;//FIRST集合
    	unordered_map<variable, set<terminal>>LASTOP;//FLLOW集合
    }grammar;
    
    unordered_map<terminal, unordered_map<terminal, string>>Priority_Relationship_Matrix;//优先关系矩阵
    
    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 << "\n\nFIRSTOP集:";
    	cout << endl;
    	for (auto i = G.FIRSTOP.begin(); i != G.FIRSTOP.end(); i++)
    	{
    		cout << "\tFIRSTOP(" << 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 << "\n\nLASTOP集:";
    	cout << endl;
    	for (auto i = G.LASTOP.begin(); i != G.LASTOP.end(); i++)
    	{
    		cout << "\tLASTOP(" << 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";
    	}
    	return 0;
    }
    
    void getFIRSTOP(grammar &G)
    {
    	int flag = 0;
    	while (flag!=1)
    	{
    		flag = 1;
    		for (int i = 0; i < G.P.size(); i++)
    		{
    			int x = G.FIRSTOP[G.P[i].left].size();
    			if (G.T.find(G.P[i].right[0]) != G.T.end())//这里是处理如果产生式第一个是终结符则把这个终结符加入到这个产生式左部的firstop集合里去
    			{
    				G.FIRSTOP[G.P[i].left].insert(G.P[i].right[0]);
    			}
    			else //把这个产生式右部第一个变量之后的终结符加入到这个产生式左部的firstop集合里去,还要把第一个变量的firstop集合加入到这个产生式左部的firstop集合里去
    			{
    				for (auto j = G.FIRSTOP[G.P[i].right[0]].begin(); j != G.FIRSTOP[G.P[i].right[0]].end(); j++)
    				{
    					G.FIRSTOP[G.P[i].left].insert(*j);
    				}
    				if (G.P[i].right.size() >= 2)
    				{
    					G.FIRSTOP[G.P[i].left].insert(G.P[i].right[1]);
    				}
    			}
    			if (G.FIRSTOP[G.P[i].left].size() > x)
    			{
    				flag++;
    			}
    		}
    	}
    }
    
    void getLASTOP(grammar &G)//类似与求firstop的方法
    {
    	int flag = 0;
    	while (flag != 1)
    	{
    		flag = 1;
    		for (int i = 0; i < G.P.size(); i++)
    		{
    			int x = G.LASTOP[G.P[i].left].size();
    			int m = G.P[i].right.size();
    			if (G.T.find(G.P[i].right[m-1]) != G.T.end())//这里是处理如果产生式倒数第一个是终结符则把这个终结符加入到这个产生式左部的lastop集合里去
    			{
    				G.LASTOP[G.P[i].left].insert(G.P[i].right[m-1]);
    			}
    			else //把这个产生式右部倒数第一个变量之后的终结符加入到这个产生式左部的lastop集合里去,还要把第一个变量的lastop集合加入到这个产生式左部的lastop集合里去
    			{
    				for (auto j = G.LASTOP[G.P[i].right[m-1]].begin(); j != G.LASTOP[G.P[i].right[m-1]].end(); j++)
    				{
    					G.LASTOP[G.P[i].left].insert(*j);
    				}
    				if (G.P[i].right.size() >= 2)
    				{
    					G.LASTOP[G.P[i].left].insert(G.P[i].right[m-2]);
    				}
    			}
    			if (G.LASTOP[G.P[i].left].size() > x)
    			{
    				flag++;
    			}
    		}
    	}
    }
    
    void getPriority_Relationship_Matrix(grammar &G)
    {
    	for (auto i = G.T.begin(); i != G.T.end(); i++)//先创建这个表
    	{
    		Priority_Relationship_Matrix[*i];
    		for (auto j = G.T.begin(); j != G.T.end(); j++)
    		{
    			Priority_Relationship_Matrix[*i][*j];
    		}
    	}
    	for (int i = 0; i < G.P.size(); i++)//直接遍历这个产生式如果有终结符就处理
    	{
    		for (int j = 0; j < G.P[i].right.size(); j++)//经过分析大部分都符合这个情况,之后处理可能出现的情况(开头和末尾是终结符,按照这个文法来说不可能出现这种情况)
    		{
    			if (G.T.find(G.P[i].right[j]) != G.T.end())//如果此时的这个是终结符
    			{
    				if (j + 1 < G.P[i].right.size()&&G.T.find(G.P[i].right[j + 1]) != G.T.end())//如果后面的一个是终结符
    				{
    					Priority_Relationship_Matrix[G.P[i].right[j]][G.P[i].right[j + 1]] = "=";
    				}
    				else
    				{
    					if (j + 1 < G.P[i].right.size())
    					{
    						for (auto f = G.FIRSTOP[G.P[i].right[j + 1]].begin(); f != G.FIRSTOP[G.P[i].right[j + 1]].end(); f++)//处理后面是变量的情况
    						{
    							Priority_Relationship_Matrix[G.P[i].right[j]][*f] = "<";
    						}
    					}
    					if (j + 2 < G.P[i].right.size() && G.T.find(G.P[i].right[j + 2]) != G.T.end())//如果变量之后是终结符
    					{
    						Priority_Relationship_Matrix[G.P[i].right[j]][G.P[i].right[j + 2]] = "=";
    					}
    				}
    				
    				if (j - 1 >= 0 && G.T.find(G.P[i].right[j - 1]) == G.T.end())//如果前面的一个是变量
    				{
    					for (auto l = G.LASTOP[G.P[i].right[j - 1]].begin(); l != G.LASTOP[G.P[i].right[j - 1]].end(); l++)//处理前面是变量的情况
    					{
    						Priority_Relationship_Matrix[*l][G.P[i].right[j]] = ">";
    					}
    				}
    			}
    		}
    		Priority_Relationship_Matrix["#"]["#"] = "停止";
    		/*
    		if (G.T.find(G.P[i].right[0]) != G.T.end()&& G.P[i].right.size()>=2)//如果第一个是终结符
    		{
    			for (auto f = G.FIRSTOP[G.P[i].right[1]].begin(); f != G.FIRSTOP[G.P[i].right[1]].end(); f++)//处理后面是变量的情况
    			{
    				Priority_Relationship_Matrix[G.P[i].right[0]][*f] = "<";
    			}
    		}
    		if (G.T.find(G.P[i].right[G.P[i].right.size() - 1]) != G.T.end()&& G.P[i].right.size() >= 2)//如果最后一个是终结符
    		{
    			for (auto l = G.LASTOP[G.P[i].right[G.P[i].right.size() - 2]].begin(); l != G.LASTOP[G.P[i].right[G.P[i].right.size() - 2]].end(); l++)//处理前面是变量的情况
    			{
    				Priority_Relationship_Matrix[*l][G.P[i].right[G.P[i].right.size() - 1]] = ">";
    			}
    		}
    		*/
    	}
    }
    
    void showPriority_Relationship_Matrix()
    {
    	cout << "\n优先关系矩阵为:" << endl;
    	for (auto j = (Priority_Relationship_Matrix.begin())->second.begin();j!= (Priority_Relationship_Matrix.begin())->second.end();j++)
    	{
    		cout << "\t" << j->first;
    	}
    	cout << endl;
    	for (auto i = Priority_Relationship_Matrix.begin(); i != Priority_Relationship_Matrix.end(); i++)
    	{
    		cout << i->first<<"\t";
    		for (auto j = i->second.begin(); j != i->second.end(); j++)
    		{
    			cout << Priority_Relationship_Matrix[i->first][j->first]<<"\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 showanalysis(int i,vector<string>&s,string &Priority_relationship,string &id,vector<string> &input)
    {
    	cout << i << " \t";
    	cout <<"" << setw(8);
    	for (int i = 0; i < s.size(); i++)
    	{
    		cout << s[i];
    	}
    	cout <<"\t"<<setw(8)<< Priority_relationship << "\t\t" << id << "\t\t";
    	for (int i = 0; i < input.size(); i++)
    	{
    		cout << input[i];
    	}
    	cout << "\n";
    }
    
    void analysis(vector<string>&setence,grammar&G)
    {
    	cout <<"步骤\t       栈\t       优先关系\t        当前输入字符R\t输入字符串" << endl;
    
    	vector<string>an;
    	an.push_back("#");
    	int number = 0;
    	string R = setence[0];
    	setence.erase(setence.begin() + 0);
    	while (1)
    	{
    		int i = an.size() - 1;
    		while (i > 0)
    		{
    			if (G.T.find(an[i]) != G.T.end())
    			{
    				break;
    			}
    			i--;
    		}
    		if (R == "#" && an[i] == "#")
    		{
    			break;
    		}
    		showanalysis(number, an, Priority_Relationship_Matrix[an[i]][R], R, setence);
    		while(Priority_Relationship_Matrix[an[i]][R] == ">")
    		{
    			string Q=an[i];
    			int j = i - 1;
    			while(j >= 0 && G.T.find(an[j])==G.T.end()) 
    			{
    				j--;
    				
    			}
    			while (j>=0 && Priority_Relationship_Matrix[an[j]][Q] != "<")
    			{
    				if (Priority_Relationship_Matrix[an[j]][Q] == "=")
    				{
    					Q = an[j];
    					j--;
    				}
    				while (j>=0 && G.T.find(an[j]) == G.T.end() )
    				{
    					j--;
    				}
    			}
    			while (an.size() - 1 > j)
    			{
    				an.pop_back();
    			}
    			i = j;
    			an.push_back("N");
    			number++;
    			showanalysis(number, an, Priority_Relationship_Matrix[an[i]][R], R, setence);
    		}
    		if(Priority_Relationship_Matrix[an[i]][R] == "<" || Priority_Relationship_Matrix[an[i]][R] == "=" || Priority_Relationship_Matrix[an[i]][R]=="停止")
    		{
    			an.push_back(R);
    		}
    		else
    		{
    			cout << "出错,分析的句子不符合此文法!!!";
    			exit(0);
    		}
    		number++;
    		if (setence.size() > 0)
    		{
    			R = setence[0];
    			setence.erase(setence.begin() + 0);
    		}
    		
    	}
    }
    
    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);
    	getFIRSTOP(G);
    	getLASTOP(G);
    	showG(G);
    	getPriority_Relationship_Matrix(G);
    	showPriority_Relationship_Matrix();
    	vector<string>setence;
    	cout << "\n请输入要分析的式子:\n";
    	infile >> s;
    	split_sentence(s, G, setence);
    	analysis(setence, G);
    	infile.close();
    	return 0;
    }
    
    
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值