编译原理 算符优先

编译原理 算符优先

思路:

首先需要定义数据结构如下:

static struct Node2//用于构造算符优先算法
{
	char Left;
	char Right;
	bool isfirstvt;
	bool islastvt;
};

一个节点代表一个A->a这样的一个式子,left是非终结符,right为终结符。Isfirstvt为真是代表a是A的firstvt中的一员。Islastvt同理。
之后进行文法的扩展,与算符优先处理的初始化。如下:

GrammerSet[grammersetcount].Left = 'S';
	GrammerSet[grammersetcount].RightCount = 1;
	strcpy_s(GrammerSet[grammersetcount].Right[0], "#S#");
	GrammerSet[grammersetcount].Right[0][1] = GrammerSet[0].Left;
	grammersetcount++;
	Non_Ter[nontercount++] = 'S';
	TerSymbol[tersymbolcount++] = '#';

	for (int i = 0; i < nontercount; i++)
	{
		for (int j = 0; j < tersymbolcount; j++)
		{
			Algorithm[algorithmcount].Left = Non_Ter[i];
			Algorithm[algorithmcount].Right = TerSymbol[j];
			//Algorithm[algorithmcount].isfirstvt = infirst(Algorithm[algorithmcount].Left, Algorithm[algorithmcount].Right);
			//Algorithm[algorithmcount].islastvt = infollow(Algorithm[algorithmcount].Left, Algorithm[algorithmcount].Right);
			Algorithm[algorithmcount].islastvt = false;
			Algorithm[algorithmcount].isfirstvt = false;
			algorithmcount++;
		}
	}

求firstvt

遍历所有产生式,如果P->Qa或者P->a则将a是P的firstvt中的一员,将代表其的节点中的isfirstvt设为true即可。现在我们已经将所有明显可见的数据求出来了,下面进行隐式推导中的firstvt计算。先将上面的道德isfirstvt为真的数据入栈,循环以下计算直到栈为空。
首先将栈顶弹出栈,记为Q->a,遍历所有产生式,找到P->Q这样的产生式,如果P->a的isfirstvt为flase,则将其置为true再入栈。
求lastvt
这个与firstvt一样的道理。我就不赘述了。

构造分析表

for 每个形如 P->X1X2…Xn的产生式 do
for i =1 to n-1 do
begin
if Xi和Xi+1都是终结符 then
Xi = Xi+1
if i<= n-2, Xi和Xi+2 是终结符, 但Xi+1 为非终结符 then
Xi = Xi+2
if Xi为终结符, Xi+1为非终结符 then
for FirstVT 中的每个元素 a do
Xi < a ;
if Xi为非终结符, Xi+1为终结符 then
for LastVT 中的每个元素 a do
a > Xi+1 ;
end
遍历所有产生式根据上面的四种情况进行填入即可。

构造总控程序

这个是这次实验的最重要的一部分。从输入串中读入一个字符到a中,然后找到栈中第一个非终结符的位置,之后我们要判断栈中是否含有可以进行规约的句柄,存在的标志就是当前栈顶的算符优先左大于a的算符优先,只要满足这个条件我们就可以进行规约,以下为规约步骤。寻找最左素短语,最左素短语的头在栈里面,它的算符优先是右大于(右优先)在栈里面比他更深的哪一个终结符,由此我们可以找到最左素短语的头。而最左素短语的尾巴在栈顶,定位了最左素短语就进行规约。遍历所有产生式,如果一个产生式与当前最左素短语终结符一一对应相等,非终结符一一对应但不一定需要相等,那么就将这个最左素短语规约为这条产生式的LEFT非终结符。规约完成后,我们又要进行判断栈中是否含有可以进行规约的句柄,这就保证了算法的正确性,不会导致规约过多或者过少。其实这就是算符优先的特点。当栈里面没有句柄之后,跳出这层循环,进行移进操作,将a移入栈中,不过这之前还要判断栈顶与a的优先关系,查表若没有定义则报错。否则正常移进栈中。a指向输入串的下一个字符。当a为“#”的时候就结束。结束之后,我们的栈中应该是“#A#”的样子。判断一下,如果不是就报错,否则输出正确。

完整代码:

//代码是前几天改的,现在我也忘了改了什么,就这样吧。
有没有精通计算机网络与3D场景渲染方面的大佬?有些问题想请教一下。
#pragma once
#ifndef ALGORITHM_PRIORITY_H
#define ALGORITHM_PRIORITY_H

#include <iostream>
#include <fstream>
#include <stack>
#include <map>
#include <iostream>

using namespace std;

static struct Node
{
	char Left;
	int RightCount;
	char Right[100][100];
	int FirstCount;
	int FollowCount;
	char First[100];
	char Follow[100];
};
static struct Node2//用于构造算符优先算法
{
	char Left;
	char Right;
	bool isfirstvt;
	bool islastvt;
};
static Node2 Algorithm[100];
static Node GrammerSet[100];
int grammersetcount = 0;
int tersymbolcount = 0;//终结符数量
int nontercount = 0;//非终结符数量  默认第一个非终结符为开始符号
char TerSymbol[200];//终结符 非大写字母
char Non_Ter[200];//非终结符 大写字母
char AllSymbol[400];//所有符号
char AlgorithmTable[100][100];//算符优先表
char text[1000];//输入要处理的字符串
int algorithmcount = 0;

class Algorithm_Priority
{
public:
	void Algorithm_Priority_main()
	{
		ReadGrammerSet();
		initvt();
		FirstVT();
		LastVT();
		CreateAlgorithmTable();
		ShowAlgorithmTable();
		AlgorithmMainControlProcess();
	}
private:


	void ShowGrammerSet(Node GrammerSet[])
	{

		for (int i = 0; i < grammersetcount; i++)
		{
			cout << i << "   " << GrammerSet[i].Left << endl;
			for (int j = 0; j < GrammerSet[i].RightCount; j++)
				cout << j << "   " << GrammerSet[i].Right[j] << endl;
		}
		cout << "非终结符的数量" << nontercount << endl;
		cout << "非终结符" << endl;
		for (int i = 0; i < nontercount; i++)
			cout << Non_Ter[i] << " ";
		cout << endl;
		cout << "终结符的数量" << tersymbolcount << endl;
		cout << "终结符" << endl;
		for (int i = 0; i < tersymbolcount; i++)
			cout << TerSymbol[i] << " ";
		cout << endl;

		for (int i = 0; i < grammersetcount; i++)
		{
			for (int j = 0; j < GrammerSet[i].RightCount; j++)
			{
				cout << GrammerSet[i].Left << "->" << GrammerSet[i].Right[j] << endl;
			}
		}

	}
	void ReadGrammerSet()
	{
		char str[100];
		while (1)
		{
			cin >> str;
			if (str[0] == '#')
				break;
			GrammerSet[grammersetcount].Left = str[0];
			SymbolProcess(str[0]);//处理左边的
			for (int i = 3; i < strlen(str); i++)
			{

				int j = 0;
				char str2[100];
				while ((str[i] != '|') && (str[i] != '\0'))
				{
					SymbolProcess(str[i]);//处理右边的
					str2[j++] = str[i++];
				}
				str2[j] = '\0';
				strcpy_s(GrammerSet[grammersetcount].Right[GrammerSet[grammersetcount].RightCount], str2);
				GrammerSet[grammersetcount].RightCount++;
			}
			grammersetcount++;
		}
	}
	bool isTerSymbol(char ch)
	{
		//	cout << "正在判断"<<ch<<"是否为终结符" << endl;
		if (ch >= 'A' && ch <= 'Z')
			return false;
		return true;
	}
	void SymbolProcess(char ch)
	{
		//非终结符
		if (ch <= 'Z' && ch >= 'A')
		{
			int flag = 0;
			for (int i = 0; i < nontercount; i++)
			{
				if (ch == Non_Ter[i])
				{
					flag = 1;
					break;//已收录
				}
			}
			if (flag == 0)
			{
				Non_Ter[nontercount++] = ch;
			}
		}
		else//终结符
		{
			int flag = 0;
			for (int i = 0; i < tersymbolcount; i++)
			{
				if (ch == TerSymbol[i])
				{
					flag = 1;
					break;//已收录
				}
			}
			if (flag == 0)
			{
				TerSymbol[tersymbolcount++] = ch;
			}
		}
	}
	//Algorithm Priority 算符优先
	void initvt()
	{
		//扩展
		GrammerSet[grammersetcount].Left = 'S';
		GrammerSet[grammersetcount].RightCount = 1;
		strcpy_s(GrammerSet[grammersetcount].Right[0], "#S#");
		GrammerSet[grammersetcount].Right[0][1] = GrammerSet[0].Left;
		grammersetcount++;
		Non_Ter[nontercount++] = 'S';
		TerSymbol[tersymbolcount++] = '#';

		for (int i = 0; i < nontercount; i++)
		{
			for (int j = 0; j < tersymbolcount; j++)
			{
				Algorithm[algorithmcount].Left = Non_Ter[i];
				Algorithm[algorithmcount].Right = TerSymbol[j];
				//Algorithm[algorithmcount].isfirstvt = infirst(Algorithm[algorithmcount].Left, Algorithm[algorithmcount].Right);
				//Algorithm[algorithmcount].islastvt = infollow(Algorithm[algorithmcount].Left, Algorithm[algorithmcount].Right);
				Algorithm[algorithmcount].islastvt = false;
				Algorithm[algorithmcount].isfirstvt = false;
				algorithmcount++;
			}
		}
		//cout << GrammerSet[grammersetcount - 1].Right[0] << endl;
		cout << "vt初始化完成" << endl;
	}
	void FirstVT()
	{
		cout << "进行FirstVT" << endl;
		//P->Qa  P->a
		for (int i = 0; i < grammersetcount; i++)
		{
			for (int j = 0; j < GrammerSet[i].RightCount; j++)
			{
				char P = GrammerSet[i].Left;
				char x1 = GrammerSet[i].Right[j][0];
				char x2 = GrammerSet[i].Right[j][1];
				if (isTerSymbol(x1))//a
				{
					for (int k = 0; k < algorithmcount; k++)
					{
						if (Algorithm[k].Left == P && Algorithm[k].Right == x1)
						{
							Algorithm[k].isfirstvt = true;
						}
					}
				}
				if (!isTerSymbol(x1) && isTerSymbol(x2))//Qa
				{
					for (int k = 0; k < algorithmcount; k++)
					{
						if (Algorithm[k].Left == P && Algorithm[k].Right == x2)
						{
							Algorithm[k].isfirstvt = true;
						}
					}
				}

			}
		}

		cout << "开始进行栈操作" << endl;
		stack<Node2>Stack;
		for (int i = 0; i < algorithmcount; i++)
		{
			if (Algorithm[i].isfirstvt == true)
			{
				Stack.push(Algorithm[i]);
			}
		}
		while (!Stack.empty())//循环至栈空
		{
			Node2 node1 = Stack.top();
			Stack.pop();//Q->a
			char Q = node1.Left;
			char a = node1.Right;
			for (int i = 0; i < grammersetcount; i++)
			{
				for (int j = 0; j < GrammerSet[i].RightCount; j++)
				{
					char P = GrammerSet[i].Left;
					if (GrammerSet[i].Right[j][0] == node1.Left)//P->Q
					{
						int pos = 0;
						for (pos = 0; pos < algorithmcount; pos++)
						{
							if (Algorithm[pos].Left == P && Algorithm[pos].Right == a)
							{
								break;
							}
						}
						if (Algorithm[pos].isfirstvt == false)
						{
							Algorithm[pos].isfirstvt = true;
							Stack.push(Algorithm[pos]);
						}
					}
				}
			}
		}
		//打印firstvt;
		for (int i = 0; i < algorithmcount; i++)
		{
			if (Algorithm[i].isfirstvt == true)
			{
				cout << Algorithm[i].Left << ":" << Algorithm[i].Right << endl;;
			}
		}
	}
	void LastVT()
	{
		cout << "进行LastVT" << endl;
		//P->......aQ  P->.....a
		for (int i = 0; i < grammersetcount; i++)
		{
			for (int j = 0; j < GrammerSet[i].RightCount; j++)
			{
				int length = strlen(GrammerSet[i].Right[j]);
				char P = GrammerSet[i].Left;
				char x1 = GrammerSet[i].Right[j][length - 1];
				char x2 = GrammerSet[i].Right[j][length - 2];
				if (isTerSymbol(x1))//......a
				{
					for (int k = 0; k < algorithmcount; k++)
					{
						if (Algorithm[k].Left == P && Algorithm[k].Right == x1)
						{
							Algorithm[k].islastvt = true;
						}
					}
				}
				if (!isTerSymbol(x1) && isTerSymbol(x2))//.....aQ
				{
					for (int k = 0; k < algorithmcount; k++)
					{
						if (Algorithm[k].Left == P && Algorithm[k].Right == x2)
						{
							Algorithm[k].islastvt = true;
						}
					}
				}

			}
		}

		cout << "开始进行栈操作" << endl;
		stack<Node2>Stack;
		for (int i = 0; i < algorithmcount; i++)
		{
			if (Algorithm[i].islastvt)
			{
				Stack.push(Algorithm[i]);
			}
		}

		while (!Stack.empty())//循环至栈空
		{
			Node2 node1 = Stack.top();
			Stack.pop();//Q->a
			char Q = node1.Left;
			char a = node1.Right;
			for (int i = 0; i < grammersetcount; i++)
			{
				for (int j = 0; j < GrammerSet[i].RightCount; j++)
				{
					char P = GrammerSet[i].Left;
					if (GrammerSet[i].Right[j][0] == node1.Left)//P->Q
					{
						int pos = 0;
						for (pos = 0; pos < algorithmcount; pos++)
						{
							if (Algorithm[pos].Left == P && Algorithm[pos].Right == a)
							{
								break;
							}
						}
						if (Algorithm[pos].islastvt == false)
						{
							Algorithm[pos].islastvt = true;
							Stack.push(Algorithm[pos]);
						}
					}
				}
			}
		}

		//打印lastvt;
		for (int i = 0; i < algorithmcount; i++)
		{
			if (Algorithm[i].islastvt == true)
			{
				cout << Algorithm[i].Left << ":" << Algorithm[i].Right << endl;;
			}
		}
	}
	bool infirstvt(char P, char a)
	{
		for (int i = 0; i < algorithmcount; i++)
		{
			if ((Algorithm[i].Left == P) && (Algorithm[i].Right == a))
				return Algorithm[i].isfirstvt;
		}
		return false;
	}
	bool inlastvt(char P, char a)
	{
		for (int i = 0; i < algorithmcount; i++)
		{
			if ((Algorithm[i].Left == P) && (Algorithm[i].Right == a))
				return Algorithm[i].islastvt;
		}
		return false;
	}
	void CreateAlgorithmTable()
	{
		for (int i = 1; i <= tersymbolcount; i++)
		{
			AlgorithmTable[i][0] = TerSymbol[i - 1];
			AlgorithmTable[0][i] = TerSymbol[i - 1];
		}

		for (int i = 0; i < grammersetcount; i++)
		{
			for (int j = 0; j < GrammerSet[i].RightCount; j++)
			{
				for (int k = 0; k < strlen(GrammerSet[i].Right[j]) - 1; k++)
				{
					char x1 = GrammerSet[i].Right[j][k];
					char x2 = GrammerSet[i].Right[j][k + 1];
					//1
					if (isTerSymbol(x1) && isTerSymbol(x2))
					{
						int pos1 = 0;
						int pos2 = 0;
						for (pos1 = 1; pos1 <= tersymbolcount; pos1++)
						{
							if (AlgorithmTable[pos1][0] == x1)
								break;
						}
						for (pos2 = 1; pos2 <= tersymbolcount; pos2++)
						{
							if (AlgorithmTable[0][pos2] == x2)
								break;
						}
						AlgorithmTable[pos1][pos2] = '=';
					}
					//2
					if (isTerSymbol(x1) && !isTerSymbol(x2))
					{
						for (int r = 0; r < algorithmcount; r++)
						{
							if ((Algorithm[r].Left == x2) && (Algorithm[r].isfirstvt == true))
							{
								char ch = Algorithm[r].Right;
								int pos1 = 0;
								int pos2 = 0;
								for (pos1 = 1; pos1 <= tersymbolcount; pos1++)
								{
									if (AlgorithmTable[pos1][0] == x1)
										break;
								}
								for (pos2 = 1; pos2 <= tersymbolcount; pos2++)
								{
									if (AlgorithmTable[0][pos2] == ch)
										break;
								}
								AlgorithmTable[pos1][pos2] = '<';
							}
						}
					}
					//3
					if (!isTerSymbol(x1) && isTerSymbol(x2))
					{
						for (int r = 0; r < algorithmcount; r++)
						{
							if ((Algorithm[r].Left == x1) && (Algorithm[r].islastvt == true))
							{
								char ch = Algorithm[r].Right;
								int pos1 = 0;
								int pos2 = 0;
								for (pos1 = 1; pos1 <= tersymbolcount; pos1++)
								{
									if (AlgorithmTable[pos1][0] == ch)
										break;
								}
								for (pos2 = 1; pos2 <= tersymbolcount; pos2++)
								{
									if (AlgorithmTable[0][pos2] == x2)
										break;
								}
								AlgorithmTable[pos1][pos2] = '>';
							}
						}
					}

					//4
					if (k < strlen(GrammerSet[i].Right[j]) - 2)
					{
						char x1 = GrammerSet[i].Right[j][k];
						char x3 = GrammerSet[i].Right[j][k + 1];
						char x2 = GrammerSet[i].Right[j][k + 2];
						if (isTerSymbol(x1) && isTerSymbol(x2) && !isTerSymbol(x3))
						{
							int pos1 = 0;
							int pos2 = 0;
							for (pos1 = 1; pos1 <= tersymbolcount; pos1++)
							{
								if (AlgorithmTable[pos1][0] == x1)
									break;
							}
							for (pos2 = 1; pos2 <= tersymbolcount; pos2++)
							{
								if (AlgorithmTable[0][pos2] == x2)
									break;
							}
							AlgorithmTable[pos1][pos2] = '=';
						}
					}
				}
			}
		}
	}
	void ShowAlgorithmTable()
	{
		for (int i = 0; i <= tersymbolcount; i++)
		{
			cout << endl << endl;
			for (int j = 0; j <= tersymbolcount; j++)
			{
				cout << AlgorithmTable[i][j] << "               ";
			}
		}
	}
	void AlgorithmMainControlProcess()
	{
		cout << endl;
		int pos = 0;
		ifstream fin;
		fin.open("test.txt");
		while (!fin.eof())
		{
			text[pos++] = fin.get();
		}
		fin.close();
	//	cout << text << endl;;
		pos = 0;

		char s[100] = { '\0' };//分析栈
		for (int i = 0; i < 100; i++)
			s[i] = '\0';
		int k = 1;
		s[0] = '#';
		s[1] = '#';
		int j = 1;
		char Q;
		char a;

		do {
			a = text[pos++];//把下一个符号读进a
			//找到栈中第一个非终结符的位置 用j指向这个非终结符
			if (isTerSymbol(s[k]))
			{
				j = k;
			}
			else
			{
				j = k - 1;//算符优先文法中不可能存在两个相邻的非终结符
			}
			//寻找最左素短语 
			while (serchAlgorithmTable(s[j], a) == 1)//s[j]>a
			{
				//寻找最左素短语
				while (1)
				{
					Q = s[j];
					if (isTerSymbol(s[j - 1]))
					{
						j = j - 1;
					}
					else
					{
						j = j - 2;
					}
					if (serchAlgorithmTable(s[j], Q) == -1)
						break;
				}
				for (int m = 0; m < grammersetcount; m++)
				{
					for (int n = 0; n < GrammerSet[m].RightCount; n++)
					{
						//遍历所有产生式
						int pos1 = 0;
						int pos2 = j + 1;
						int flag = 1;
						for (pos1 = 0; pos1 < strlen(GrammerSet[m].Right[n]); pos1++)
						{
							if (pos2 > k)
							{
								flag = 0;
								break;
							}
							//终结符对应相等 非终结符只要都是非终结符就好
							if ((GrammerSet[m].Right[n][pos1] == s[pos2]) || ((!isTerSymbol(s[pos2])) && (!isTerSymbol(GrammerSet[m].Right[n][pos1]))))
							{
								pos2++;
								if ((pos2 > k) && (pos1 == strlen(GrammerSet[m].Right[n]) - 1))//匹配完成且成功
								{
									flag = 1;
									pos2 = k;
									break;
								}
								flag = 1;
							}
							else
							{
								pos2++;
								flag = 0;
								break;
							}
						}
						if (pos2 != k)
							flag = 0;
						if (flag == 1)//匹配成功。可以规约
						{
							k = j + 1;
							for (int i = j + 1; i < 100; i++)
								s[i] = '\0';
							s[k] = GrammerSet[m].Left;
							cout << "规约成功-----" << GrammerSet[m].Left << endl;
							break;
						}
					}

				}

			}
			//移进
			if ((serchAlgorithmTable(s[j], a) == -1) || (serchAlgorithmTable(s[j], a) == 0))
			{
				k++;
				s[k] = a;
				cout << "移进" << a << endl;
			}
			else
			{
				cout << "error" << endl;
				return;
			}
		} while (a != '#');
		if (s[3] == '#' && (!isTerSymbol(s[2])))
			cout << "正确" << endl;
		else cout << "error" << endl;
		cout << s << endl;

	}
	int serchAlgorithmTable(char ch1, char ch2)
	{
		int flag = 9;//-1 0 1 分别代表 < = >
		int pos1 = 0;
		int pos2 = 0;
		for (pos1 = 1; pos1 <= tersymbolcount; pos1++)
		{
			if (AlgorithmTable[pos1][0] == ch1)
				break;
		}
		for (pos2 = 1; pos2 <= tersymbolcount; pos2++)
		{
			if (AlgorithmTable[0][pos2] == ch2)
				break;
		}
		if (AlgorithmTable[pos1][pos2] == '=')
			flag = 0;
		if (AlgorithmTable[pos1][pos2] == '<')
			flag = -1;
		if (AlgorithmTable[pos1][pos2] == '>')
			flag = 1;
		return flag;
	}
};


#endif
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值