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

📄 myyacc.cpp

📁 一个不算完整的编译器实现
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<fstream>
#include<algorithm>
#include<queue>
#include<stdlib.h>
using namespace std;

struct item_struct
{
	int pronum;//产生式号
	int pp;//pointposition,点的位置,例:E->a.Bc,pp=1
	vector<int> searchnum;//搜索符数组,存进来的时候要保证是升序排列
};
struct DFAnode_struct
{
	vector<item_struct> heart;//代表核心项
	string id;//代表状态核心项确定的唯一标识
	vector<pair<int,int> > nontermin,termin;
	//这两个是转移边,前面的是通过非终极符号转到的状态,在GOTO表中用;后面的是通过终极符号转到的状态,在ACTION表中用
	//pair中前面的int是输入符,后面的int是状态
};
//------------------------------------------------------------------------
string cal_state_id(vector<item_struct> &heart)
{//用来计算核心项的标识字符串
	vector<string> heart_string;
	char c[10];
	sprintf(c,"%d;",heart.size());
	string result=c;
	for(int i=0;i<heart.size();i++)
	{//分别把每一个项目转成字符串,然后对字符串排序
		char pn[20];
		sprintf(pn,"%d;%d;",heart[i].pronum,heart[i].pp);
		string item=pn;
		for(int j=0;j<heart[i].searchnum.size();j++)
		{
			sprintf(pn,"%d,",heart[i].searchnum[j]);
			item += pn;
		}
		heart_string.push_back(item);
	}
	sort(heart_string.begin(),heart_string.end());
	for(int i=0;i<heart_string.size();i++)
	{
		//cout << heart_string[i] << endl;
		result += heart_string[i] + ";";
	}
//	cout << result << endl;
	return result;
}
//------------------------------------------------------------------------
void show_item(item_struct &item,vector<pair<int,bool> > *pro,vector<string> &tToString,vector<string> &ntToString)
{//用来输出一个产生式项目
	int pp=item.pp;
	int pn=item.pronum;
	cout << ntToString[pro[pn][0].first] << " --> ";
	for(int i=1;i<pro[pn].size();i++)
	{
		if(pp==i-1) cout << " . ";
		if(pro[pn][i].second==true)
		{
			cout << ntToString[pro[pn][i].first] << " ";
		}
		else cout << tToString[pro[pn][i].first] << " ";
	}
	cout << "\t|||\t";
	for(int i=0;i<item.searchnum.size();i++)
	{
		cout << tToString[item.searchnum[i]] << "  ";
	}
	cout << endl;
}
void showDFA(vector<DFAnode_struct> &DFAnode,vector<pair<int,bool> > *pro,vector<string> &tToString,vector<string> &ntToString,bool *state_used)
{//用来把整个DFA所有结点输出
	for(int i=0;i<DFAnode.size();i++)
	{
		if(!state_used[i]) continue;
		cout << "STATE" << i << endl;
		for(int j=0;j<DFAnode[i].heart.size();j++)
		{
			show_item(DFAnode[i].heart[j],pro,tToString,ntToString);
		}
		for(int j=0;j<DFAnode[i].nontermin.size();j++)
		{
			cout << "通过" << ntToString[DFAnode[i].nontermin[j].first] << "到状态" << DFAnode[i].nontermin[j].second << endl;
		}
		for(int j=0;j<DFAnode[i].termin.size();j++)
		{
			cout << "通过" << tToString[DFAnode[i].termin[j].first] << "到状态" << DFAnode[i].termin[j].second << endl;
		}
	}
}
void showACTION(const vector<int*> &action_table,const vector<string> &tToString,const int pc)
{//打印出ACTION表
	printf("\t");
	for(int i=0;i<tToString.size();i++)
		printf("%s\t",tToString[i].c_str());
	cout << endl;
	for(int i=0;i<action_table.size();i++)
	{
		printf("%d\t",i);
		for(int j=0;j<tToString.size();j++)
		{
			if(action_table[i][j]>0) printf("S%d\t",action_table[i][j]);
			else if(action_table[i][j]<0) 
			{
				if(action_table[i][j]<-pc-5) printf("ACC\t");
				else printf("R%d\t",-action_table[i][j]);
			}
			else printf("%d\t",0);
		}
		cout << endl;
	}
}
void showGOTO(const vector<int*> &goto_table,const vector<string> &ntToString)
{
	printf("\t");
	for(int i=0;i<ntToString.size();i++)
		printf("%s\t",ntToString[i].c_str());
	cout << endl;
	for(int i=0;i<goto_table.size();i++)
	{
		printf("%d\t",i);
		for(int j=0;j<ntToString.size();j++)
		{
			if(goto_table[i][j]>0) printf("S%d\t",goto_table[i][j]);
			else printf("%d\t",0);
		}
		cout << endl;
	}
}
//------------------------------------------------------------------------
string get_num(const string &id,int &count)
{//就是提取分号前的字符的函数
	string result="";
	for(;count<id.size();count++)
	{
		if(id[count]!=';') result.push_back(id[count]);
		else
		{
			count++;
			return result;
		}
	}
}
bool is_same_heart(DFAnode_struct &s1,DFAnode_struct &s2)
{//用来判断两个状态的核心项是否相同
 //id组成:第一个是核心项的个数n;然后有n项,每一项第一个为项目产生式号,第二个是点的位置,后面都是搜索符号
 //看id是否相等,先看核心项个数是否相等,相等再看每一项的项目产生式号和点的位置,不看搜索符
	bool result=true;
	string id1=s1.id,id2=s2.id;
	string left="",right="";
	int count1=0,count2=0;
	//先判断核心项数是否相同
	left=get_num(id1,count1);
	right=get_num(id2,count2);
	if(left!=right) return false;
	while(1)
	{//这时两个id的核心项个数肯定相同
		//得到每一项的第一部分
		left=get_num(id1,count1);
		right=get_num(id2,count2);
		if(left!=right) return false;
		//得到每一项的第二部分
		left=get_num(id1,count1);
		right=get_num(id2,count2);
		if(left!=right) return false;
		//忽略搜索符
		left=get_num(id1,count1);
		right=get_num(id2,count2);
		//看是否到了id的末尾
		if(count1>=id1.size() && count2>=id2.size()) return true;
	}
	return result;
}
void combine_searchsymbol(DFAnode_struct &from,DFAnode_struct &to,const int tCount)
{//把from的各项目的搜索符给to的对应项目
	for(int i=0;i<from.heart.size();i++)
	{//对于每一个核心项
		item_struct &fromheart=from.heart[i];
		item_struct &toheart=to.heart[i];
		bool *ss=new bool[tCount];//用来记录哪些是搜索符
		for(int j=0;j<tCount;j++)
			ss[j]=false;
		//把from和to的对应项目的搜索符都记下来
		for(int j=0;j<fromheart.searchnum.size();j++)
			ss[fromheart.searchnum[j]]=true;
		for(int j=0;j<toheart.searchnum.size();j++)
			ss[toheart.searchnum[j]]=true;
		vector<int> newss;//这个就是新的记录搜索符的结构,用来替换原来的
		for(int j=0;j<tCount;j++)
			if(ss[j]) newss.push_back(j);
		to.heart[i].searchnum=newss;//赋新值
	}
	//搜索符更新完以后更改id标识
	to.id=cal_state_id(to.heart);
	return;
}
//-------------------------------------------------------------------------
int main()
{
	//语法分析器生成器
	//从文件读入上下文无关方法,取出来终极字符和非终极字符
	//要求输入的文法是已经拓广了的,也就是只有一个是开始符号
	ifstream infile;
	infile.open("system\\grammar.txt");
	if(!infile)
	{//打开文件失败就退出
		printf("Unable to open the LexText file.\n");
		return -1;
	}
	vector<string> grammar1;//原始文法
	string input="";
	while(getline(infile,input))
	{
		//输入串末尾加个空格,分词的时候容易些
		input.push_back(' ');
		grammar1.push_back(input);
	}
	//建立产生式的存储结构,我用vector<string>[]数组来存
	vector<string> *production=new vector<string>[grammar1.size()];
	for(int i=0;i<grammar1.size();i++)
	{
		input="";
		//把原始文法分词后写入到产生式数组中
		for(int j=0;j<grammar1[i].size();j++)
		{
			if(grammar1[i][j]!=' ') input.push_back(grammar1[i][j]);
			else
			{
				production[i].push_back(input);
				input="";
			}
		}
	}
	int productionCount=grammar1.size();
	/*
	for(int i=0;i<grammar1.size();i++)
	{//检测输入是否正确
		for(int j=0;j<production[i].size();j++)
			cout << production[i][j] << "\t";
		cout << endl;
	}
	*/
	
	//用来识别非终极符和终极符
	map<string,int> nonterminal;
	vector<string> ntToString;
	int ntCount=0;
	map<string,int> terminal;
	vector<string> tToString;
	int tCount=0;
	int eposition=-1;//用来记录ε的位置
	for(int i=0;i<productionCount;i++)
	{//先识别非终极符
		input=production[i][0];
		if(nonterminal.find(input)==nonterminal.end())
		{
			nonterminal[input]=ntCount++;
			ntToString.push_back(input);
		}
	}
	for(int i=0;i<productionCount;i++)
	{//识别终极符
		for(int j=1;j<production[i].size();j++)
		{
			input=production[i][j];
			if(nonterminal.find(input)==nonterminal.end())
			{
				if(terminal.find(input)==terminal.end())
				{
					terminal[input]=tCount++;
					tToString.push_back(input);
				}
			}
		}
	}
	if(terminal.find("#")!=terminal.end()) eposition=terminal.find("#")->second;//找#(ε)
	vector<pair<int,bool> > *pro=new vector<pair<int,bool> >[productionCount];
	//把原始的文法变成可以很容易看出是否为非终极符和终极符的结构,pair的second为1时为非终极符,为0时为终极符
	//pair的first为对应输入串的下标编号
	for(int i=0;i<productionCount;i++)
	{
		for(int j=0;j<production[i].size();j++)
		{
			bool isNT=true;
			int num=-1;
			input=production[i][j];
			if(nonterminal.find(input)!=nonterminal.end())
			{
				num=nonterminal.find(input)->second;
				isNT=true;
			}
			else
			{
				num=terminal.find(input)->second;
				isNT=false;
			}
			pro[i].push_back(make_pair(num,isNT));
		}
	}
	/*//用来测试转换后的产生式是否正确
	for(int i=0;i<productionCount;i++)
	{
		for(int j=0;j<pro[i].size();j++)
		{
			if(pro[i][j].second) cout << ntToString[pro[i][j].first] << " " << pro[i][j].second << "\t";
			else cout << tToString[pro[i][j].first] << " " << pro[i][j].second << "\t";
		}
		cout << endl;
	}
	*/

⌨️ 快捷键说明

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