⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myyacc.cpp

📁 一个不算完整的编译器实现
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	delete []production;
	//开始求FIRST集,我只用求非终极符号的FIRST就可以了
	bool **first=new bool*[ntCount];
	for(int i=0;i<ntCount;i++)
	{//用一个bool型的二维数组表示nonterminal的FIRST集,为1时表明FIRST集里有对应terminal元素
		first[i]=new bool[tCount];
		for(int j=0;j<tCount;j++)
			first[i][j]=false;
	}
	while(1)
	{
		bool haschanged=false;//用来判断是否有新的变化产生,退出while的判断
		for(int i1=0;i1<productionCount;i1++)
		{//对于每一个产生式
			int see=1;//这是比较重要的一位,这一位表明应该看到产生式右部哪位的符号了,用来对ε进行处理
			int nsig=pro[i1][0].first;//nsig为产生式左部非终极符号的下标
			while(1)
			{
				if(see==pro[i1].size())//也就是当产生式最终推出来只有ε时
				{
					if(first[nsig][eposition]==false) haschanged=true;
					first[nsig][eposition]=true;//产生式左部非终极符号FIRST集包含ε
					break;
				}
				else if(!pro[i1][see].second && pro[i1][see].first!=eposition)
				{//为假时说明此为终极符号并且其不是ε时
					if(first[nsig][pro[i1][1].first]==false) haschanged=true;
					first[nsig][pro[i1][1].first]=true;//此产生式右部第一个终极符号属于产生式左部非终极符号的FIRST集
					break;
				}
				if(!pro[i1][see].second && pro[i1][see].first==eposition) see++;//当前符号为ε时
				else
				{//pro[i1][see].second为真的时候说明此为非终极符号
					bool hase=false;//表明FIRST集里是否包含有ε
					int thesig=pro[i1][see].first;//是当前要看的非终极符号的下标
					for(int i2=0;i2<tCount;i2++)
					{
						if(first[thesig][i2] && i2!=eposition)//如果thesig非终极符号在i2终极符号处FIRST为1
						{
							if(first[nsig][i2]==false) haschanged=true;
							first[nsig][i2]=true;
						}
						else if(first[thesig][i2] && i2==eposition)
						{
							hase=true;
						}
					}
					if(hase) see++;
					else break;
				}
			}
		}//for
		if(haschanged==false) break;
	}
	/*
	//用来检测FIRST集,基本测试没什么问题
	for(int i=0;i<ntCount;i++)
	{
		cout << "FIRST(" << ntToString[i] << ")={";
		for(int j=0;j<tCount;j++)
		{
			if(first[i][j]) cout << tToString[j] << "\t";
		}
		cout << "}\n";
	}
	*/
	//把FIRST集改为紧凑形式的
	vector<int> *FIRST = new vector<int>[ntCount];
	for(int i=0;i<ntCount;i++)
	{
		for(int j=0;j<tCount;j++)
			if(first[i][j]) FIRST[i].push_back(j);
	}
	/*
	for(int i=0;i<ntCount;i++)
	{
		cout << "FIRST(" << ntToString[i] << ")={";
		for(int j=0;j<FIRST[i].size();j++)
			cout << tToString[FIRST[i][j]] << " ";
		cout << "}" << endl;
	}
	*/
	//
	//------------------------------------------------------------------------
	//然后就是构造LR(1)的识别活前缀的DFA,这是个难点

	//首先,求各非终极符号的完全闭包项(存产生式号)
	//我的闭包项是两部分的总合,一部分是产生式左部为此非终极符号,一部分是产生式右部第一个符号是非终极符号时再加入的item
	vector<int> *bibao=new vector<int>[ntCount];
	vector<int> *bibaofirst=new vector<int>[ntCount];//这是记录闭包第一部分的,很有用
	bool **haspro=new bool*[ntCount];
	for(int i=0;i<ntCount;i++)
	{//初始化一下记录非终极符号闭包的bool数组
		haspro[i]=new bool[productionCount];
		for(int j=0;j<productionCount;j++)
			haspro[i][j]=false;
	}
	for(int i=0;i<productionCount;i++)
	{//把闭包第一部分写进来
		int ter=pro[i][0].first;
		haspro[ter][i]=true;
	}
	for(int i=0;i<ntCount;i++)
	{//把bool数组中的值给bibaofirst变量
		for(int j=0;j<productionCount;j++)
		{
			if(haspro[i][j]) bibaofirst[i].push_back(j);
		}
	}
	while(true)
	{//算闭包的第二部分,反复扫描产生式,看右部第一个非终极符号
		bool ischanged=false;
		for(int i=0;i<productionCount;i++)
		{
			int ter=pro[i][0].first;
			if(pro[i][1].second)
			{
				int ter2=pro[i][1].first;
				for(int j=0;j<productionCount;j++)
					if(haspro[ter][j]==false && haspro[ter2][j]==true)
					{
						haspro[ter][j]=true;
						ischanged=true;
					}
			}
		}
		if(!ischanged) break;
	}
	for(int i=0;i<ntCount;i++)
	{//把bool数组中的值给bibao变量
		for(int j=0;j<productionCount;j++)
		{
			if(haspro[i][j]) bibao[i].push_back(j);
		}
	}
/*
	//用来检测一下闭包项
	for(int i=0;i<ntCount;i++)
	{//第一部分
		cout << ntToString[i] << "\t";
		for(int j=0;j<bibaofirst[i].size();j++)
			cout << bibaofirst[i][j] << " ";
		cout << endl;
	}
	cout << endl;
	for(int i=0;i<ntCount;i++)
	{
		cout << ntToString[i] << "\t";
		for(int j=0;j<productionCount;j++)
			if(haspro[i][j]==true) cout << j << "  ";
		cout << endl;
	}
*/
	for(int i=0;i<ntCount;i++)
		delete []haspro[i];
	delete []haspro;
	
	terminal["$"]=tCount++;
	tToString.push_back("$");
	//把界符加入到终极符号中
	vector<DFAnode_struct> DFAnode;
	int DFACount=0;

	item_struct start;
	start.pronum=0; start.pp=0; start.searchnum.push_back(tCount-1);//开始符号的产生式S'->S
	DFAnode_struct newnode;
	newnode.heart.push_back(start);//给第一个状态赋核心项,即为开始产生式
	//计算开始状态的核心项唯一标识
	map<string,int> stateid;//用来存放状态核心项标识
	string caledid=cal_state_id(newnode.heart);
	stateid[caledid]=DFACount++;
	newnode.id=caledid;
	DFAnode.push_back(newnode);
	//对第一个结点的核心写入工作完成,现在开始进行LR(1)DFA的整体计算
	int now_state=0;
	while(now_state<DFAnode.size())
	{
		vector<item_struct> bibao_item;//用来存放当前状态核心项产生的所有闭包项,后来又把核心项也放进去了,放了方便
		DFAnode_struct &nownode=DFAnode[now_state];
		bool *isbibao=new bool[productionCount];//用来记录产生式是不是闭包项,然后都算完了再给bibao_item
		bool **sid = new bool*[productionCount];//用sid来记录闭包项的搜索符
		for(int i=0;i<productionCount;i++)
		{
			sid[i]=new bool[tCount];
			for(int j=0;j<tCount;j++)
				sid[i][j]=false;
		}
		for(int i=0;i<productionCount;i++)
			isbibao[i]=false;
		for(int i=0;i<nownode.heart.size();i++)
		{
			item_struct &theheart = nownode.heart[i];
			if(theheart.pp == pro[theheart.pronum].size()-1)//这时就是归约项了,点到了产生式的最右端
				continue;
			if(pro[theheart.pronum][theheart.pp+1].second)
			{//当核心项目点后为非终极符时,看它的闭包
				int tempnt=pro[theheart.pronum][theheart.pp+1].first;//把非终极符号先记下来
				for(int j=0;j<bibao[tempnt].size();j++)
					isbibao[bibao[tempnt][j]]=true;
			}
		}

		//求核心项传递给闭包项的搜索符
		for(int i=0;i<nownode.heart.size();i++)
		{
			item_struct &theheart = nownode.heart[i];
			//这里要对核心项中的归约项进行处理,否则后面会下标越界退出
			if(theheart.pp == pro[theheart.pronum].size()-1)//这时就是归约项了,点到了产生式的最右端
				continue;

			if(pro[theheart.pronum][theheart.pp+1].second)
			{//只有点后是非终极符的时候才有闭包项
				int tempnt=pro[theheart.pronum][theheart.pp+1].first;//把非终极符号先记下来
				for(int i2=theheart.pp+2;i2<=pro[theheart.pronum].size();i2++)
				{
					bool hase=false;
					if(i2==pro[theheart.pronum].size())
					{
						for(int j=0;j<bibaofirst[tempnt].size();j++)
						{
							for(int k=0;k<theheart.searchnum.size();k++)
								sid[bibaofirst[tempnt][j]][theheart.searchnum[k]]=true;//如果到产生式最右端了就把自己的搜索符加入到目的搜索符中
						}
						break;
					}
					if(pro[theheart.pronum][i2].second==false)//表示点后面的非终极符号的右面是终极符号时,就把这个终极符号加入搜索符
					{
						int tempt=pro[theheart.pronum][i2].first;
						for(int j=0;j<bibaofirst[tempnt].size();j++)
						{
							sid[bibaofirst[tempnt][j]][tempt]=true;
						}
						break;
					}
					else//为非终极符号的情况,把FIRST集放到搜索符中,要注意有ε的时候
					{
						int tempt=pro[theheart.pronum][i2].first;//这里的tempt是点后面非终极符号后的非终极符号
						for(int i3=0;i3<FIRST[tempt].size();i3++)
						{//加入所有FIRST集中的内容
							if(FIRST[tempt][i3]==eposition)
							{//搜索符中不能有ε
								hase=true;
								continue;
							}
							for(int i4=0;i4<bibaofirst[tempnt].size();i4++)
							{
								sid[bibaofirst[tempnt][i4]][FIRST[tempt][i3]]=true;
							}
						}
						if(!hase) break;//FIRST中没有ε的话搜索符就求完了
					}//else
				}//for_i2
			}//if是非终极符号
		}//for_i
		//闭包项传递给闭包项的搜索符
		queue<int> itemqueue;//用来存放要传递搜索符的闭包项,记录的是闭包产生式
		for(int i=0;i<nownode.heart.size();i++)
		{
			item_struct &theheart = nownode.heart[i];
			if(theheart.pp == pro[theheart.pronum].size()-1)//这时就是归约项了,点到了产生式的最右端
				continue;
			if(pro[theheart.pronum][theheart.pp+1].second)
			{//当核心项目点后为非终极符时,看它的闭包
				int tempnt=pro[theheart.pronum][theheart.pp+1].first;//把非终极符号先记下来
				for(int j=0;j<bibaofirst[tempnt].size();j++)
				{
					itemqueue.push(bibaofirst[tempnt][j]);
				}
			}
		}
		//---------------------------------搜索符计算可以了
		while(!itemqueue.empty())//没有更新就退出
		{
			bool haschanged=false;
			int thepro=itemqueue.front();
			itemqueue.pop();
			if(pro[thepro][1].second)
			{//这个闭包产生式右部第一个为非终极符号时{计算搜索符}{若搜索符有改变才加入其bibaofirst中所有项到队列中}
				int thent=pro[thepro][1].first;
				for(int i1=2;i1<=pro[thepro].size();i1++)
				{//计算搜索符
					bool hase=false;
					if(i1==pro[thepro].size())
					{//相等的时候把此产生式的搜索传给闭包项
						for(int i2=0;i2<tCount;i2++)
						{
							if(sid[thepro][i2])
							{
								for(int i3=0;i3<bibaofirst[thent].size();i3++)
								{
									if(sid[bibaofirst[thent][i3]][i2]==false)
									{
										sid[bibaofirst[thent][i3]][i2]=true;
										haschanged=true;
									}
								}
							}
						}
						break;
					}
					if(pro[thepro][i1].second==false)//表示点后面的非终极符号的右面是终极符号时,就把这个终极符号加入搜索符
					{
						int tempt=pro[thepro][i1].first;
						for(int j=0;j<bibaofirst[thent].size();j++)
						{
							if(sid[bibaofirst[thent][j]][tempt]==false)
							{
								sid[bibaofirst[thent][j]][tempt]=true;
								haschanged=true;
							}
						}
						break;
					}
					else//为非终极符号的情况,把FIRST集放到搜索符中,要注意有ε的时候

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -