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

📄 myyacc.cpp

📁 一个不算完整的编译器实现
💻 CPP
📖 第 1 页 / 共 3 页
字号:
					{
						int tempt=pro[thepro][i1].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[thent].size();i4++)
							{
								if(sid[bibaofirst[thent][i4]][FIRST[tempt][i3]]==false)
								{
									sid[bibaofirst[thent][i4]][FIRST[tempt][i3]]=true;
									haschanged=true;
								}
							}
						}
						if(!hase) break;//FIRST中没有ε的话搜索符就求完了
					}//else
				}//
				if(haschanged)
				{
					for(int i1=0;i1<bibaofirst[thent].size();i1++)
					{//加入其bibaofirst中所有项到队列
						itemqueue.push(bibaofirst[thent][i1]);
					}
				}
			}
		}
		/*
		//测试最后的一个项目的搜索符
		cout << eposition << endl;
		cout << "\t";
		for(int i=0;i<tCount;i++)
			cout << tToString[i] << "\t";
		cout << endl;
		for(int i=0;i<productionCount;i++)
		{
			cout << ntToString[pro[i][0].first] << "\t";
			for(int j=0;j<tCount;j++)
				cout << sid[i][j] << "\t";
			cout << endl;
		}
		*/
		for(int i=0;i<productionCount;i++)
		{
			if(isbibao[i])
			{//如果产生式是闭包项,就把算出来的搜索符给它
				item_struct temp;
				temp.pp=0;
				temp.pronum=i;
				for(int j=0;j<tCount;j++)
				{
					if(sid[i][j])
						temp.searchnum.push_back(j);
				}
				bibao_item.push_back(temp);
			}
		}
		delete []isbibao;
		for(int i=0;i<nownode.heart.size();i++)
		{//把核心项也加入到bibao_item,形成所有的状态中的项目集
			bibao_item.push_back(nownode.heart[i]);
		}
		/*//测试项目集的搜索符
		for(int i=0;i<bibao_item.size();i++)
		{
			cout << ntToString[pro[bibao_item[i].pronum][0].first] << "\t";
			for(int j=0;j<bibao_item[i].searchnum.size();j++)
				cout << tToString[bibao_item[i].searchnum[j]] << "\t";
			cout << endl;
		}
		*/
		//--------------------------------------------------------开始生成新的状态及其核心项了
		//所有当前的项目都在bibao_item中了,对这个集合进行点的后移
		//当点已经到了最后面的情况时,就算归约项了
		bool *ntOK=new bool[ntCount];
		bool *tOK=new bool[tCount];
		for(int i=0;i<ntCount;i++)
			ntOK[i]=false;
		for(int i=0;i<tCount;i++)
			tOK[i]=false;
		//上面的bool数组用来记录转移的时候项目的符号点后的符号是否已经用过了
		for(int i=0;i<bibao_item.size();i++)
		{
			item_struct &theitem=bibao_item[i];
			if(theitem.pp == pro[theitem.pronum].size()-1)//为归约项,跳过
				continue;

			int thet=pro[theitem.pronum][theitem.pp+1].first;
			if((pro[theitem.pronum][theitem.pp+1].second==false && tOK[thet]==false) || (pro[theitem.pronum][theitem.pp+1].second==true && ntOK[thet]==false))
			{//以前没算过的时候再去算
				vector<item_struct> newheart;
				for(int j=i;j<bibao_item.size();j++)
				{//从i后开始看就行了,因为前面的肯定已经做过了
					item_struct &theitemin=bibao_item[j];
					if(theitemin.pp == pro[theitemin.pronum].size()-1)//为归约项,跳过
						continue;
					if(pro[theitemin.pronum][theitemin.pp+1].second == pro[theitem.pronum][theitem.pp+1].second &&
						pro[theitemin.pronum][theitemin.pp+1].first == pro[theitem.pronum][theitem.pp+1].first)
					{
						item_struct nextitem=bibao_item[j];
						nextitem.pp++;//点向后移一位,搜索符已经带着了
						newheart.push_back(nextitem);
					}
				}
				//创建新的状结点,写入核心项和标识字符串
				string theid=cal_state_id(newheart);
				if(stateid.find(theid)==stateid.end())//没找到含有相同核心项的状态
				{
					stateid[theid]=DFACount++;
					DFAnode_struct newnode;
					newnode.heart=newheart;
					newnode.id=theid;
					DFAnode.push_back(newnode);
					if(pro[theitem.pronum][theitem.pp+1].second==false) 
						DFAnode[now_state].termin.push_back(make_pair(thet,DFACount-1));//!很奇怪,这里用nownode就不行
					else 
						DFAnode[now_state].nontermin.push_back(make_pair(thet,DFACount-1));
					//上面的是终极符或非终极符添加边的情况
				}
				else//找到了相同状态结点的时候
				{
					int next_state_num=stateid.find(theid)->second;
					if(pro[theitem.pronum][theitem.pp+1].second==false) DFAnode[now_state].termin.push_back(make_pair(thet,next_state_num));
					else DFAnode[now_state].nontermin.push_back(make_pair(thet,next_state_num));
				}
			}//if
			if(pro[theitem.pronum][theitem.pp+1].second==false) tOK[thet]=true;
			else ntOK[thet]=true;
		}//for_i
		now_state++;
		delete []ntOK;
		delete []tOK;
	}//while_算状态结点的
	bool *state_used=new bool[(int)DFAnode.size()];
	for(int i=0;i<(int)DFAnode.size();i++)
		state_used[i]=true;
	//state_used用来标记此状态是否是被合并了的,也就是是否还要使用
	//showDFA(DFAnode,pro,tToString,ntToString,state_used);
	//以上把所有LR(1)状态都求出来了,每个状态记录的都只是它的核心项
	//------------------------------------------
	//下面就要进行LR(1)状态的合并,合并同心项
	map<int,int> state_change;
	//用来表示两个状态合并时是哪两个状态,后面的是合并到的状态号,前面的是被合并的状态号,此map用来在合并后对状态的边进行修改,
	//也就是把被合并的状态的入度边指向改为合并到的状态
	for(int i=0;i<DFAnode.size();i++)
	{
		if(!state_used[i]) continue;
		for(int j=i+1;j<DFAnode.size();j++)
		{//每一个状态都和后面所有的状态去比较核心项,若相同就合并搜索符并相应更变边的指向
			if(!state_used[j]) continue;
			if(is_same_heart(DFAnode[i],DFAnode[j]))
			{//两个状态是同心的时候,进行合并:把后面的状态的搜索符合到前面的状态,并增加到后面的边,再建立两个状态的联系(map)
				combine_searchsymbol(DFAnode[j],DFAnode[i],tCount);
				/*//显示合并后的项目
				for(int k=0;k<DFAnode[i].heart.size();k++)
					show_item(DFAnode[i].heart[k],pro,tToString,ntToString);
				*/
				
				//!!!由于如果两个状态的核心项目(除搜索符)完全一样,那么它们通过符号到达的下一个状态的核心项目(除搜索符)也会完全一样,也就是最终由
				//由此这两个状态到达的状态也应该会合并,故没有必要再去把边加到前面去
				state_used[j]=false;
				state_change[j]=i;
			}
		}
	}
	//修改边,把无效的状态号改成合并到的状态号
	for(int i=0;i<DFAnode.size();i++)
	{
		if(!state_used[i]) continue;
		for(int j=0;j<DFAnode[i].nontermin.size();j++)
		{//对于非终极符号的
			int nextstate=DFAnode[i].nontermin[j].second;
			if(state_change.find(nextstate)!=state_change.end())//在状态合并项中找到
			{
				DFAnode[i].nontermin[j].second=state_change.find(nextstate)->second;//改变边
			}
		}
		for(int j=0;j<DFAnode[i].termin.size();j++)
		{//对于终极符号的
			int nextstate=DFAnode[i].termin[j].second;
			if(state_change.find(nextstate)!=state_change.end())
			{
				DFAnode[i].termin[j].second=state_change.find(nextstate)->second;
			}
		}
	}
	//showDFA(DFAnode,pro,tToString,ntToString,state_used);
	//-----------------------------------------------------------------------------------------------
	//用来生成分析表ACTION和GOTO
	//先生成ACTION表,规定:移入项目用正数,数为状态号;归约用负数,数为对应的产生式
	vector<int*> action_table;
	vector<int> yasuo;//因为状态集只用了state_used来标识状态是否是使用的,在做表的时候就不留空白空间了,要把状态压缩,无效的去掉,下标是原状态号,值是新的表项号(状态号)
	for(int i=0;i<DFAnode.size();i++)
	{
		yasuo.push_back(action_table.size());//记下来前后的序号对应关系
		if(!state_used[i]) continue;
		int *line=new int[tCount];//表示表中的一行,用0(错误)来初始化
		for(int j=0;j<tCount;j++)
			line[j]=0;
		for(int j=0;j<DFAnode[i].termin.size();j++)
		{//移入项目
			pair<int,int> temp=DFAnode[i].termin[j];
			line[temp.first]=temp.second;
		}
		for(int j=0;j<DFAnode[i].heart.size();j++)
		{//找有无归约项
			const item_struct temp=DFAnode[i].heart[j];
			if(temp.pp>=pro[temp.pronum].size()-1)//点到最后了
			{//在搜索符处归约
				for(int k=0;k<temp.searchnum.size();k++)
				{
					int snum=temp.searchnum[k];
					line[snum]=-temp.pronum;//在搜索符snum处归约产生式号为temp.pronum的产生式
					if(line[snum]==0)//此时归约的是0号产生式,即开始符号推出的产生式
						line[snum]=-productionCount-10;
				}
			}
		}
		action_table.push_back(line);
	}
	for(int i=0;i<action_table.size();i++)
	{//用来修改移入的状态号
		for(int j=0;j<tCount;j++)
		{
			if(action_table[i][j]>0)//为移入项时
			{
				action_table[i][j]=yasuo[action_table[i][j]];
			}
		}
	}
	//输出一下ACTION表
	//showACTION(action_table,tToString,productionCount);
	//再生成GOTO表
	vector<int*> goto_table;
	for(int i=0;i<DFAnode.size();i++)
	{
		if(!state_used[i]) continue;
		int *line=new int[ntCount];
		for(int j=0;j<ntCount;j++)
			line[j]=0;
		for(int j=0;j<DFAnode[i].nontermin.size();j++)
		{
			pair<int,int> temp=DFAnode[i].nontermin[j];
			line[temp.first]=temp.second;
		}
		goto_table.push_back(line);
	}
	for(int i=0;i<goto_table.size();i++)
	{//用来修改GOTO的状态号
		for(int j=0;j<ntCount;j++)
		{
			if(goto_table[i][j]>0)
			{
				goto_table[i][j]=yasuo[goto_table[i][j]];
			}
		}
	}
	//输出一下GOTO表
	//showGOTO(goto_table,ntToString);
	/*//输出来谁压缩谁
	for(int i=0;i<yasuo.size();i++)
	{
		cout << "状态" << i << "压缩成状态" << yasuo[i] << endl;
	}
	*/
//--------------------------------------------------------------------------------------------
	//用来把分析表输出到文件(格式:第一行:终极符号名称;第二行:非终极符号名称;第三行:状态数;后面就分别是ACTION表和GOTO表,每个状态为一行)
	ofstream outfile;
	outfile.open("system\\action_goto_tables.txt");
	for(int i=0;i<tCount;i++)
	{
		outfile << tToString[i] << " ";
	}
	outfile << endl;
	for(int i=0;i<ntCount;i++)
	{
		outfile << ntToString[i] << " ";
	}
	outfile << endl;
	outfile << action_table.size() << endl;
	for(int i=0;i<action_table.size();i++)
	{
		for(int j=0;j<tCount;j++)
		{
			outfile << action_table[i][j] << " ";
		}
		outfile << endl;
	}
	for(int i=0;i<goto_table.size();i++)
	{
		for(int j=0;j<ntCount;j++)
		{
			outfile << goto_table[i][j] << " ";
		}
		outfile << endl;
	}
	system("system\\compile3.exe");
}
//动态分配的内存FIRST,first,bibao,bibaofirst
//闭包项传递的搜索符退出while循环的方法,用一个bool数组记下来用过哪些产生式,再想想吧

/*所有变量名
DFAcount:DFA状态数
DFAnode:vector<DFAnode_struct> DFAnode表示状态结点
map<int,int> state_change;//用来表示两个状态合并时是哪两个状态,后面的是合并到的状态号,前面的是被合并的状态号,此map用来在合并后对状态的边进行修改,也就是把被合并的状态的入度边指向改为合并到的状态
bool state_used[]表示状态是否是有用的

函数:
showDFA:用来显示当前vector<DFAnode_struct>中的树形结构
*/

⌨️ 快捷键说明

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