buct编译原理个人作业

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

一、正则表达式 -> DFA -> 最小化DFA

#include<iostream>
#include<cstring>
#include<string>
#include<stack>
#include<vector>
#include<set>
#include<queue>

#define MAX 128

using namespace std;

typedef set<int> IntSet;
typedef set<char> CharSet;

/********************表达式转NFA********************/

struct NfaState				/*定义NFA状态*/
{
	
	int index;				/*NFA状态的状态号*/ 
	
	char input;				/*NFA状态弧上的值*/
	int chTrans;			/*NFA状态弧转移到的状态号*/ 
	
	IntSet epTrans;			/*当前状态通过ε转移到的状态号集合*/ 
};

struct NFA
{
	
	NfaState *head;			/*NFA的头指针*/
	NfaState *tail;			/*NFA的尾指针*/
};

NfaState NfaStates[MAX];	/*NFA状态数组*/ 
int nfaStateNum = 0;		/*NFA状态总数*/ 

/*从状态n1到状态n2添加一条弧,弧上的值为ch*/
void add(NfaState *n1, NfaState *n2, char ch)
{
	
	n1->input = ch;
	n1->chTrans = n2->index;
}

/*从状态n1到状态n2添加一条弧,弧上的值为ε*/
void add(NfaState *n1, NfaState *n2)
{
	
	n1->epTrans.insert(n2->index);
}

/*新建一个NFA(即从NFA状态数组中取出两个状态)*/
NFA creatNFA(int sum)
{
	
	NFA n;
	
	n.head = &NfaStates[sum];
	n.tail = &NfaStates[sum + 1];

	return n;
}

/*在字符串s第n位后面插入字符ch*/
void insert(string &s, int n, char ch)
{
	
	s += '#';
	
	for(int i = s.size() - 1; i > n; i--)
	{
		s[i] = s[i - 1];
	}
	
	s[n] = ch;
}

/*对字符串s进行预处理,在第一位是操作数、‘*’或‘)’且第二位是操作数或‘(’之间加入连接符‘&’*/ 
void preprocess(string &s)
{
	
	int i = 0 , length = s.size();
	
	while(i < length)
	{
		if((s[i] >= 'a' && s[i] <= 'z') || (s[i] == '*') || (s[i] == ')'))
		{
			if((s[i + 1] >= 'a' && s[i + 1] <= 'z') || s[i + 1] == '(')
			{
			
				insert(s, i+1 , '&');
				length ++;
			}
		}

		i++;
	}
} 

/*中缀转后缀时用到的优先级比较,即为每个操作符赋一个权重,通过权重大小比较优先级*/
int priority(char ch)
{

	if(ch == '*')
	{
		return 3;
	}
		
	if(ch == '&')
	{
		return 2;
	}
		
	if(ch == '|')
	{
		return 1;
	}
	
	if(ch == '(')
	{
		return 0;
	}
}

/*中缀表达式转后缀表达式*/
string infixToSuffix(string s)
{
	
	preprocess(s);			/*对字符串进行预处理*/
	
	string str;				/*要输出的后缀字符串*/
	stack<char> oper;		/*运算符栈*/
	
	for(int i = 0; i < s.size(); i++)
	{
		
		if(s[i] >= 'a' && s[i] <= 'z')	/*如果是操作数直接输出*/
		{
			str += s[i];
		} 
		else							/*遇到运算符时*/ 
		{
			
			if(s[i] == '(')			/*遇到左括号压入栈中*/
			{
				oper.push(s[i]);
			} 
			
			else if(s[i] == ')')	/*遇到右括号时*/
			{
					
				char ch = oper.top();
				while(ch != '(')		/*将栈中元素出栈,直到栈顶为左括号*/
				{
					
					str += ch;
				
					oper.pop();
					ch = oper.top();
				}
				
				oper.pop();				/*最后将左括号出栈*/ 
			}
			else					/*遇到其他操作符时*/ 
			{
				
				if(!oper.empty())			/*如果栈不为空*/ 
				{
					
					char ch = oper.top();
					while(priority(ch) >= priority(s[i]))	/*弹出栈中优先级大于等于当前运算符的运算符*/ 
					{
						
						str +=	ch;
						oper.pop();
						
						if(oper.empty())	/*如果栈为空则结束循环*/ 
						{
							break;
						} 								
						else ch = oper.top();
					} 

					oper.push(s[i]);		/*再将当前运算符入栈*/ 
				}
				
				else				/*如果栈为空,直接将运算符入栈*/
				{
					oper.push(s[i]);
				}
			}
		}
	}
	
	/*最后如果栈不为空,则出栈并输出到字符串*/
	while(!oper.empty())
	{
		
		char ch = oper.top();
		oper.pop();
		
		str += ch;
	}
	
	cout<<"*******************************************"<<endl<<endl;
	cout<<"中缀表达式为:"<<s<<endl<<endl; 
	cout<<"后缀表达式为:"<<str<<endl<<endl;

	return str;
} 

/*后缀表达式转nfa*/
NFA strToNfa(string s)
{
	
	stack<NFA> NfaStack;		/*定义一个NFA栈*/ 
	
	for(int i = 0; i < s.size(); i++)		/*读取后缀表达式,每次读一个字符*/ 
	{

		if(s[i] >= 'a' && s[i] <= 'z')		/*遇到操作数*/ 
		{
			
			NFA n = creatNFA(nfaStateNum);		/*新建一个NFA*/ 
			nfaStateNum += 2;					/*NFA状态总数加2*/
			
			add(n.head, n.tail, s[i]);			/*NFA的头指向尾,弧上的值为s[i]*/

			NfaStack.push(n);					/*将该NFA入栈*/
		}
		
		else if(s[i] == '*')		/*遇到闭包运算符*/
		{
			
			NFA n1 = creatNFA(nfaStateNum);		/*新建一个NFA*/
			nfaStateNum += 2;					/*NFA状态总数加2*/

			NFA n2 = NfaStack.top();			/*从栈中弹出一个NFA*/
			NfaStack.pop();
			
			add(n2.tail, n1.head);				/*n2的尾通过ε指向n1的头*/
			add(n2.tail, n1.tail);				/*n2的尾通过ε指向n1的尾*/
			add(n1.head, n2.head);				/*n1的头通过ε指向n2的头*/
			add(n1.head, n1.tail);				/*n1的头通过ε指向n1的尾*/
			
			NfaStack.push(n1);					/*最后将新生成的NFA入栈*/
		}
		
		else if(s[i] == '|')		/*遇到或运算符*/
		{
			
			NFA n1, n2;							/*从栈中弹出两个NFA,栈顶为n2,次栈顶为n1*/
			n2 = NfaStack.top();
			NfaStack.pop();
			
			n1 = NfaStack.top();
			NfaStack.pop();
			
			NFA n = creatNFA(nfaStateNum);		/*新建一个NFA*/
			nfaStateNum +=2;					/*NFA状态总数加2*/

			add(n.head, n1.head);				/*n的头通过ε指向n1的头*/
			add(n.head, n2.head);				/*n的头通过ε指向n2的头*/	
			add(n1.tail, n.tail);				/*n1的尾通过ε指向n的尾*/
			add(n2.tail, n.tail);				/*n2的尾通过ε指向n的尾*/
			
			NfaStack.push(n);					/*最后将新生成的NFA入栈*/
		}
		
		else if(s[i] == '&')		/*遇到连接运算符*/
		{
			
			NFA n1, n2, n;				/*定义一个新的NFA n*/
			
			n2 = NfaStack.top();				/*从栈中弹出两个NFA,栈顶为n2,次栈顶为n1*/
			NfaStack.pop();
			
			n1 = NfaStack.top();
			NfaStack.pop();
			
			add(n1.tail, n2.head);				/*n1的尾通过ε指向n2的尾*/
			
			n.head = n1.head;					/*n的头为n1的头*/
			n.tail = n2.tail;					/*n的尾为n2的尾*/

			NfaStack.push(n);					/*最后将新生成的NFA入栈*/
		}
	}
	
	return NfaStack.top();		/*最后的栈顶元素即为生成好的NFA*/
}

/*打印NFA函数*/
void printNFA(NFA nfa)
{

	cout<<"***************     NFA     ***************"<<endl<<endl; 
	cout<<"NFA总共有"<<nfaStateNum<<"个状态,"<<endl;
	cout<<"初态为"<<nfa.head->index<<",终态为" <<nfa.tail->index<<"。"<<endl<<endl<<"转移函数为:"<<endl;
	
	for(int i = 0; i < nfaStateNum; i++)		/*遍历NFA状态数组*/
	{
		
		if(NfaStates[i].input != '#')			/*如果弧上的值不是初始时的‘#’则输出*/
		{
			cout<<NfaStates[i].index<<"-->'"<<NfaStates[i].input<<"'-->"<<NfaStates[i].chTrans<<'\t';
		}
		
		IntSet::iterator it;					/*输出该状态经过ε到达的状态*/
		for(it = NfaStates[i].epTrans.begin(); it != NfaStates[i].epTrans.end(); it++)
		{
			cout<<NfaStates[i].index<<"-->'"<<' '<<"'-->"<<*it<<'\t';
		}
		
		cout<<endl;
	}
}

/********************NFA转DFA********************/

struct Edge			/*定义DFA的转换弧*/
{
	
	char input;			/*弧上的值*/
	int Trans;			/*弧所指向的状态号*/
};

struct DfaState		/*定义DFA状态*/
{
	
	bool isEnd;			/*是否为终态,是为true,不是为false*/
	
	int index;			/*DFA状态的状态号*/
	IntSet closure;		/*NFA的ε-move()闭包*/
	
	int edgeNum;		/*DFA状态上的射出弧数*/
	Edge Edges[10];		/*DFA状态上的射出弧*/
};

DfaState DfaStates[MAX];		/*DFA状态数组*/
int dfaStateNum = 0;			/*DFA状态总数*/

struct DFA			/*定义DFA结构*/
{
	
	int startState;				/*DFA的初态*/
	
	set<int> endStates;			/*DFA的终态集*/
	set<char> terminator;		/*DFA的终结符集*/
	
	int trans[MAX][26];		/*DFA的转移矩阵*/
};

/*求一个状态集的ε-cloure*/
IntSet epcloure(IntSet s)
{
	
	stack<int> epStack;		/*(此处栈和队列均可)*/
	
	IntSet::iterator it;
	for(it = s.begin(); it != s.end(); it++)
	{
		epStack.push(*it);			/*将该状态集中的每一个元素都压入栈中*/
	}
	
	while(!epStack.empty())			/*只要栈不为空*/
	{
		
		int temp = epStack.top();		/*从栈中弹出一个元素*/
		epStack.pop();
		
		IntSet::iterator iter;
		for(iter = NfaStates[temp].epTrans.begin(); iter != NfaStates[temp].epTrans.end(); iter++)
		{
			if(!s.count(*iter))				/*遍历它通过ε能转换到的状态集*/
			{								/*如果当前元素没有在集合中出现*/
				s.insert(*iter);			/*则把它加入集合中*/
				epStack.push(*iter);		/*同时压入栈中*/
			}
		}
	}
	
	return s;		/*最后的s即为ε-cloure*/
}

/*求一个状态集s的ε-cloure(move(ch))*/
IntSet moveEpCloure(IntSet s, char ch)
{
	
	IntSet temp;
	
	IntSet::iterator it;
	for(it = s.begin(); it != s.end(); it++)		/*遍历当前集合s中的每个元素*/
	{
		if(NfaStates[*it].input == ch)				/*如果对应转换弧上的值为ch*/
		{
			temp.insert(NfaStates[*it].chTrans);		/*则把该弧通过ch转换到的状态加入到集合temp中*/
		}
	}
	
	temp = epcloure(temp);			/*最后求temp的ε闭包*/
	return temp;
}

/*判断一个状态是否为终态*/
bool IsEnd(NFA n, IntSet s)
{
	
	IntSet::iterator it;
	for(it = s.begin(); it != s.end(); it++)	/*遍历该状态所包含的nfa状态集*/
	{
		if(*it == n.tail->index)				/*如果包含nfa的终态,则该状态为终态,返回true*/
		{
			return true;
		}
	}
	
	return false;		/*如果不包含,则不是终态,返回false*/
}

/*nfa转dfa主函数*/
DFA nfaToDfa(NFA n, string str)		/*参数为nfa和后缀表达式*/
{
	
	cout<<"***************     DFA     ***************"<<endl<<endl; 
	
	int i;
	DFA d;
	set<IntSet> states;		/*定义一个存储整数集合的集合,用于判断求出一个状态集s的ε-cloure(move(ch))后是否出现新状态*/
	
	memset(d.trans, -1, sizeof(d.trans));	/*初始化dfa的转移矩阵*/ 
	
	for(i = 0; i < str.size(); i++)			/*遍历后缀表达式*/
	{
		if(str[i] >= 'a' && str[i] <= 'z')		/*如果遇到操作数,则把它加入到dfa的终结符集中*/
		{
			d.terminator.insert(str[i]);
		}
	}
	
	d.startState = 0;		/*dfa的初态为0*/
	
	IntSet tempSet;
	tempSet.insert(n.head->index);		/*将nfa的初态加入到集合中*/
	
	DfaStates[0].closure = epcloure(tempSet);		/*求dfa的初态*/
	DfaStates[0].isEnd = IsEnd(n, DfaStates[0].closure);		/*判断初态是否为终态*/
	
	dfaStateNum++;			/*dfa数量加一*/
	
	queue<int> q;
	q.push(d.startState);		/*把dfa的初态存入队列中(此处栈和队列均可)*/
	
	while(!q.empty())		/*只要队列不为空,就一直循环*/
	{
		
		int num = q.front();				/*出去队首元素*/
		q.pop();
		
		CharSet::iterator it;
		for(it = d.terminator.begin(); it != d.terminator.end(); it++)		/*遍历终结符集*/
		{
			
			IntSet temp = moveEpCloure(DfaStates[num].closure, *it);		/*计算每个终结符的ε-cloure(move(ch))*/
			/*IntSet::iterator t;
			cout<<endl;
			for(t = temp.begin(); t != temp.end(); t++)   打印每次划分 
			{
				cout<<*t<<' ';
			}
			cout<<endl;*/
			if(!states.count(temp) && !temp.empty())	/*如果求出来的状态集不为空且与之前求出来的状态集不同,则新建一个DFA状态*/
			{
				
				states.insert(temp);				/*将新求出来的状态集加入到状态集合中*/

				DfaStates[dfaStateNum].closure = temp;
				
				DfaStates[num].Edges[DfaStates[num].edgeNum].input = *it;				/*该状态弧的输入即为当前终结符*/
				DfaStates[num].Edges[DfaStates[num].edgeNum].Trans = dfaStateNum;		/*弧转移到的状态为最后一个DFA状态*/
				DfaStates[num].edgeNum++;												/*该状态弧的数目加一*/
				
				d.trans[num][*it - 'a'] = dfaStateNum;		/*更新转移矩阵*/
				
				DfaStates[dfaStateNum].isEnd = IsEnd(n, DfaStates[dfaStateNum].closure);	/*判断是否为终态*/
				
				q.push(dfaStateNum);		/*将新的状态号加入队列中*/
				
				dfaStateNum++;		/*DFA状态总数加一*/
			}
			else			/*求出来的状态集在之前求出的某个状态集相同*/
			{
				for(i = 0; i < dfaStateNum; i++)		/*遍历之前求出来的状态集合*/
				{
					if(temp == DfaStates[i].closure)		/*找到与该集合相同的DFA状态*/
					{
						
						DfaStates[num].Edges[DfaStates[num].edgeNum].input = *it;		/*该状态弧的输入即为当前终结符*/
						DfaStates[num].Edges[DfaStates[num].edgeNum].Trans = i;			/*该弧转移到的状态即为i*/
						DfaStates[num].edgeNum++;										/*该状态弧的数目加一*/
						
						d.trans[num][*it - 'a'] = i;		/*更新转移矩阵*/
						
						break;
					}
				}
			}
		}
	}
	
	/*计算dfa的终态集*/
	for(i = 0; i < dfaStateNum; i++)	/*遍历dfa的所有状态*/	
	{
		if(DfaStates[i].isEnd == true)		/*如果该状态是终态*/
		{
			d.endStates.insert(i);		/*则将该状态号加入到dfa的终态集中*/
		}
	}
	
	return d;
}

/*打印dfa函数*/
void printDFA(DFA d)
{
	
	int i, j;
	cout<<"DFA总共有"<<dfaStateNum<<"个状态,"<<"初态为"<<d.startState<<endl<<endl;
	
	cout<<"有穷字母表为{ ";
	set<char>::iterator it;
	for(it = d.terminator.begin(); it != d.terminator.end(); it++)
	{
		cout<<*it<<' ';
	}
	cout<<'}'<<endl<<endl;
	
	cout<<"终态集为{ "; 
	IntSet::iterator iter;
	for(iter = d.endStates.begin(); iter != d.endStates.end(); iter++)
	{
		cout<<*iter<<' ';
	}
	cout<<'}'<<endl<<endl;
	
	cout<<"转移函数为:"<<endl;
	for(i = 0; i < dfaStateNum; i++)
	{
		for(j = 0; j < DfaStates[i].edgeNum; j++)
		{
			
			if(DfaStates[DfaStates[i].Edges[j].Trans].isEnd == true)
			{
				cout<<DfaStates[i].index<<"-->'"<<DfaStates[i].Edges[j].input;
				cout<<"'--><"<<DfaStates[i].Edges[j].Trans<<">\t";
			}
			else
			{
				cout<<DfaStates[i].index<<"-->'"<<DfaStates[i].Edges[j].input;
				cout<<"'-->"<<DfaStates[i].Edges[j].Trans<<'\t';
			}
		}
		cout<<endl;
	}
	
	cout<<endl<<"转移矩阵为:"<<endl<<"     ";
	CharSet::iterator t;
	for(t = d.terminator.begin(); t != d.terminator.end(); t++)
	{
		cout<<*t<<"   ";
	}
	cout<<endl;
	
	for(i = 0; i < dfaStateNum; i++)
	{
		
		if(d.endStates.count(i))
		{
			cout<<'<'<<i<<">  ";
		}
		else
		{
			cout<<' '<<i<<"   ";
		}
		
		for(j = 0; j < 26; j++)
		{
			if(d.terminator.count(j + 'a'))
			{
				if(d.trans[i][j] != -1)
				{
					cout<<d.trans[i][j]<<"   ";
				}
				else
				{
					cout<<"    "; 
				}
			}
		}
		
		cout<<endl;
	}
}

/******************DFA的最小化******************/
IntSet s[MAX];					/*划分出来的集合数组*/
DfaState minDfaStates[MAX];		/*minDfa状态数组*/

int minDfaStateNum = 0;			/*minDfa的状态总数,同时也是划分出的集合数*/

struct stateSet			/*划分状态集*/
{
	
	int index;			/*该状态集所能转换到的状态集标号*/  
	IntSet s;			/*该状态集中的dfa状态号*/
};

/*当前划分总数为count,返回状态n所属的状态集标号i*/
int findSetNum(int count, int n)
{
	
	for(int i = 0; i < count; i++)
	{
		if(s[i].count(n))
		{						
			return i;
		}
	}
}

/*最小化DFA*/
DFA minDFA(DFA d)
{
	
	int i, j;
	cout<<endl<<"*************     minDFA     **************"<<endl<<endl;
	
	DFA minDfa;
	minDfa.terminator = d.terminator;		/*把dfa的终结符集赋给minDfa*/
	
	memset(minDfa.trans, -1, sizeof(minDfa.trans));		/*初始化minDfa转移矩阵*/
	
	/*做第一次划分,即将终态与非终态分开*/
	bool endFlag = true;					/*判断dfa的所有状态是否全为终态的标志*/ 
	for(i = 0; i < dfaStateNum; i++)	/*遍历dfa状态数组*/
	{
		if(DfaStates[i].isEnd == false)			/*如果该dfa状态不是终态*/
		{

			endFlag = false;						/*标志应为false*/
			minDfaStateNum = 2;						/*第一次划分应该有两个集合*/
			
			s[1].insert(DfaStates[i].index);		/*把该状态的状态号加入s[1]集合中*/
		}
		else									/*如果该dfa状态是终态*/
		{
			s[0].insert(DfaStates[i].index);		/*把该状态的状态号加入s[0]集合中*/
		}
	}
	
	if(endFlag)					/*如果标志为真,则所有dfa状态都是终态*/
	{
		minDfaStateNum = 1;			/*第一次划分结束应只有一个集合*/
	}
	
	bool cutFlag = true;		/*上一次是否产生新的划分的标志*/
	while(cutFlag)				/*只要上一次产生新的划分就继续循环*/
	{
		
		int cutCount = 0;			/*需要产生新的划分的数量*/
		for(i = 0; i < minDfaStateNum; i++)			/*遍历每个划分集合*/
		{
			
			CharSet::iterator it;
			for(it = d.terminator.begin(); it != d.terminator.end(); it++)		/*遍历dfa的终结符集*/
			{
				
				int setNum = 0;				/*当前缓冲区中的状态集个数*/
				stateSet temp[20];			/*划分状态集“缓冲区”*/
				
				IntSet::iterator iter;
				for(iter = s[i].begin(); iter != s[i].end(); iter++)		/*遍历集合中的每个状态号*/
				{
					
					bool epFlag = true;			/*判断该集合中是否存在没有该终结符对应的转换弧的状态*/
					for(j = 0; j < DfaStates[*iter].edgeNum; j++)		/*遍历该状态的所有边*/
					{

						if(DfaStates[*iter].Edges[j].input == *it)		/*如果该边的输入为该终结符*/
						{

							epFlag = false;			/*则标志为false*/
							
							/*计算该状态转换到的状态集的标号*/
							int transNum = findSetNum(minDfaStateNum, DfaStates[*iter].Edges[j].Trans);
						
							int curSetNum = 0;			/*遍历缓冲区,寻找是否存在到达这个标号的状态集*/
							while((temp[curSetNum].index != transNum) && (curSetNum < setNum))
							{
								curSetNum++;
							}
							
							if(curSetNum == setNum)		/*缓冲区中不存在到达这个标号的状态集*/
							{
								
								/*在缓冲区中新建一个状态集*/
								temp[setNum].index = transNum;		/*该状态集所能转换到的状态集标号为transNum*/	
								temp[setNum].s.insert(*iter);		/*把当前状态添加到该状态集中*/
								
								setNum++;		/*缓冲区中的状态集个数加一*/
							}
							else			/*缓冲区中存在到达这个标号的状态集*/
							{
								temp[curSetNum].s.insert(*iter);	/*把当前状态加入到该状态集中*/
							}
						}
					}
					
					if(epFlag)		/*如果该状态不存在与该终结符对应的转换弧*/
					{
						
						/*寻找缓冲区中是否存在转换到标号为-1的状态集
						这里规定如果不存在转换弧,则它所到达的状态集标号为-1*/
						int curSetNum = 0;
						while((temp[curSetNum].index != -1) && (curSetNum < setNum))
						{
							curSetNum++;
						}
							
						if(curSetNum == setNum)			/*如果不存在这样的状态集*/
						{
							
							/*在缓冲区中新建一个状态集*/
							temp[setNum].index = -1;			/*该状态集转移到的状态集标号为-1*/
							temp[setNum].s.insert(*iter);		/*把当前状态加入到该状态集中*/
							
							setNum++;		/*缓冲区中的状态集个数加一*/
						}
						else			/*缓冲区中存在到达这个标号的状态集*/
						{
							temp[curSetNum].s.insert(*iter);	/*把当前状态加入到该状态集中*/
						}
					}	
				}
				
				if(setNum > 1)	/*如果缓冲区中的状态集个数大于1,表示同一个状态集中的元素能转换到不同的状态集,则需要划分*/
				{
					
					cutCount++;		/*划分次数加一*/
					
					/*为每组划分创建新的dfa状态*/
					for(j = 1; j < setNum; j++)		/*遍历缓冲区,这里从1开始是将第0组划分留在原集合中*/
					{
						
						IntSet::iterator t;
						for(t = temp[j].s.begin(); t != temp[j].s.end(); t++)
						{
							
							s[i].erase(*t);						/*在原来的状态集中删除该状态*/
							s[minDfaStateNum].insert(*t);		/*在新的状态集中加入该状态*/
						}
						
						minDfaStateNum++;		/*最小化DFA状态总数加一*/
					}
				}
			}	
		}
		
		if(cutCount == 0)		/*如果需要划分的次数为0,表示本次不需要进行划分*/
		{
			cutFlag = false;
		}
	}
	
	/*遍历每个划分好的状态集*/
	for(i = 0; i < minDfaStateNum; i++)
	{
		
		IntSet::iterator y;
		for(y = s[i].begin(); y != s[i].end(); y++)		/*遍历集合中的每个元素*/
		{
			
			if(*y == d.startState)			/*如果当前状态为dfa的初态,则该最小化DFA状态也为初态*/
			{
				minDfa.startState = i;
			}
			
			if(d.endStates.count(*y))		/*如果当前状态是终态,则该最小化DFA状态也为终态*/
			{
				
				minDfaStates[i].isEnd = true;
				minDfa.endStates.insert(i);		/*将该最小化DFA状态加入终态集中*/
			}
			
			for(j = 0; j < DfaStates[*y].edgeNum; j++)		/*遍历该DFA状态的每条弧,为最小化DFA创建弧*/
			{

				/*遍历划分好的状态集合,找出该弧转移到的状态现在属于哪个集合*/
				for(int t = 0; t < minDfaStateNum; t++)
				{
					if(s[t].count(DfaStates[*y].Edges[j].Trans))
					{
						
						bool haveEdge = false;		/*判断该弧是否已经创建的标志*/
						for(int l = 0; l < minDfaStates[i].edgeNum; l++)	/*遍历已创建的弧*/
						{					/*如果该弧已经存在*/
							if((minDfaStates[i].Edges[l].input == DfaStates[*y].Edges[j].input) && (minDfaStates[i].Edges[l].Trans == t))
							{
								haveEdge = true;		/*标志为真*/
							}
						}
						
						if(!haveEdge)		/*如果该弧不存在,则创建一条新的弧*/
						{
							
							minDfaStates[i].Edges[minDfaStates[i].edgeNum].input = DfaStates[*y].Edges[j].input;	/*弧的值与DFA的相同*/
							minDfaStates[i].Edges[minDfaStates[i].edgeNum].Trans = t;	/*该弧转移到的状态为这个状态集的标号*/
							
							minDfa.trans[i][DfaStates[*y].Edges[j].input - 'a'] = t;	/*更新转移矩阵*/
							
							minDfaStates[i].edgeNum++;		/*该状态的弧的数目加一*/
						}

						break;
					}
				}
			}
		}
	}
	
	return minDfa;
}

void printMinDFA(DFA d)
{
	
	int i, j;
	cout<<"minDFA总共有"<<minDfaStateNum<<"个状态,"<<"初态为"<<d.startState<<endl<<endl;
	
	cout<<"有穷字母表为{ ";
	set<char>::iterator it;
	for(it = d.terminator.begin(); it != d.terminator.end(); it++)
	{
		cout<<*it<<' ';
	}
	cout<<'}'<<endl<<endl;
	
	cout<<"终态集为{ "; 
	IntSet::iterator iter;
	for(iter = d.endStates.begin(); iter != d.endStates.end(); iter++)
	{
		cout<<*iter<<' ';
	}
	cout<<'}'<<endl<<endl;
	
	cout<<"转移函数为:"<<endl;
	for(i = 0; i < minDfaStateNum; i++)
	{
		for(j = 0; j < minDfaStates[i].edgeNum; j++)
		{
			
			if(minDfaStates[minDfaStates[i].Edges[j].Trans].isEnd == true)
			{
				cout<<minDfaStates[i].index<<"-->'"<<minDfaStates[i].Edges[j].input;
				cout<<"'--><"<<minDfaStates[i].Edges[j].Trans<<">\t";
			}
			else
			{
				cout<<minDfaStates[i].index<<"-->'"<<minDfaStates[i].Edges[j].input;
				cout<<"'-->"<<minDfaStates[i].Edges[j].Trans<<'\t';
			}
		}
		cout<<endl;
	}
	
	cout<<endl<<"转移矩阵为:"<<endl<<"     ";
	CharSet::iterator t;
	for(t = d.terminator.begin(); t != d.terminator.end(); t++)
	{
		cout<<*t<<"   ";
	}
	cout<<endl;
	
	for(i = 0; i < minDfaStateNum; i++)
	{
		
		if(d.endStates.count(i))
		{
			cout<<'<'<<i<<">  ";
		}
		else
		{
			cout<<' '<<i<<"   ";
		}
		
		for(j = 0; j < 26; j++)
		{
			if(d.terminator.count(j + 'a'))
			{
				if(d.trans[i][j] != -1)
				{
					cout<<d.trans[i][j]<<"   ";
				}
				else
				{
					cout<<"    "; 
				}
			}
		}
		
		cout<<endl;
	}
	cout<<endl<<"*******************************************";
}


int main()
{
	
	/*测试样例1 
	string str = "(a|b)*abb";*/
	
	/*测试样例2*/
	string str = "(a|b*)c*";
	str = infixToSuffix(str);		/*将中缀表达式转换为后缀表达式*/

	/***初始化所有的数组***/
	int i, j;
	for(i = 0; i < MAX; i++)
	{
		
		NfaStates[i].index = i;
		NfaStates[i].input = '#';
		NfaStates[i].chTrans = -1;
	}
	
	for(i = 0; i < MAX; i++)
	{
		
		DfaStates[i].index = i;
		DfaStates[i].isEnd = false;
		
		for(j = 0; j < 10; j++)
		{
			
			DfaStates[i].Edges[j].input = '#';
			DfaStates[i].Edges[j].Trans = -1;
		}
	}
	
	for(i = 0; i < MAX; i++)
	{
		
		minDfaStates[i].index = i;
		minDfaStates[i].isEnd = false;
		
		for(int j = 0; j < 10; j++)
		{
			
			minDfaStates[i].Edges[j].input = '#';
			minDfaStates[i].Edges[j].Trans = -1;
		}
	}
	
	NFA n = strToNfa(str);
	printNFA(n);
	
	DFA d = nfaToDfa(n, str);
	printDFA(d);
	
	DFA minDfa = minDFA(d);
	printMinDFA(minDfa);
	
	
	return 0;
}

二、LL(1)

#include <cstdio>
#include <vector>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <stack>
using namespace std;

// 未实现处理左递归 & 公共左因子 仅能处理LL(1)文法
// 用&符号代表一步赛龙e,且不充当表格行头的终结符。 



/* 产生式结构体 */
struct Production {
    char left; // 左部符号
    vector<char> rigths;  // 右部符号串
};

/* 文法结构体 */
struct Grammar {
    int num;  // 产生式数量
    vector<char> T;   // 终结符
    vector<char> N;   // 非终结符
    vector<Production> prods;  //产生式
} grammar;

/* FIRST集和FOLLOW集 */
map<char, set<char> > first;
map<char, set<char> > follow;

/* 分析栈 */
stack<char> ST;

/* 待分析串 */
string str;

/* 预测分析表 */
vector<char> M[50][50];

/* 判断ch是否是终结符 */
int isInT(char ch)
{
    for (int i = 0; i < grammar.T.size(); i++) {
        if (grammar.T[i] == ch) {
            return i + 1;
        }
    }
    return 0;
}

/* 判断ch是否是非终结符 */
int isInN(char ch)
{
    for (int i = 0; i < grammar.N.size(); i++) {
        if (grammar.N[i] == ch) {
            return i + 1;
        }
    }
    return 0;
}
/* 求(T U N)的FIRST集 */
void getFirstSet()
{
    /* 终结符的FIRST集是其本身 */
    for (int i = 0; i < grammar.T.size(); i++) {
        char X = grammar.T[i];
        set<char> tmp;
        tmp.insert(X);
        first[X] = tmp;
    }
    /* 当非终结符的FIRST集发生变化时循环 */
    bool change = true;
    while (change) {
        change = false;
        /* 枚举每个产生式 */
        for (int i = 0; i < grammar.prods.size(); i++) {
            Production &P = grammar.prods[i];
            char X = P.left;
            set<char> &FX = first[X];
            /* 如果右部第一个符号是空或者是终结符,则加入到左部的FIRST集中 */
            if (isInT(P.rigths[0]) || P.rigths[0] == '&') {
                /* 查找是否FIRST集是否已经存在该符号 */
                auto it = FX.find(P.rigths[0]);
                /* 不存在 */
                if (it == FX.end()) {
                    change = true; // 标注FIRST集发生变化,循环继续
                    FX.insert(P.rigths[0]);
                }
            } else {
                /* 当前符号是非终结符,且当前符号可以推出空,则还需判断下一个符号 */
                bool next = true;
                /* 待判断符号的下标 */
                int idx = 0;
                while (next && idx < P.rigths.size()) {
                    next = false;
                    char Y = P.rigths[idx];
                    set<char> &FY = first[Y];
                    for (auto it = FY.begin(); it != FY.end(); it++) {
                        /* 把当前符号的FIRST集中非空元素加入到左部符号的FIRST集中 */
                        if (*it != '&') {
                            auto itt = FX.find(*it);
                            if (itt == FX.end()) {
                                change = true;
                                FX.insert(*it);
                            }
                        }
                    }
                    /* 当前符号的FIRST集中有空, 标记next为真,idx下标+1 */
                    auto it = FY.find('&');
                    if (it != FY.end()) {
                        next = true;
                        idx = idx + 1;
                    }
                }
                
            }
        }
    }
    
    printf("FIRST:\n");
    for (int i = 0; i < grammar.N.size(); i++) {
        char X = grammar.N[i];
        printf("%c: ", X);
        for (auto it = first[X].begin(); it != first[X].end(); it++) {
            printf("%c ", *it);
        }
        printf("\n");
    }
}
/* 产找alpha串的FIRST集, 保存到FS集合中 */
void getFirstByAlphaSet(vector<char> &alpha, set<char> &FS)
{
    /* 当前符号是非终结符,若当前符号可以推出空,则还需判断下一个符号 */
    bool next = true;
    int idx = 0;
    while (idx < alpha.size() && next) {
        next = false;
        /* 当前符号是终结符或空,加入到FIRST集中 */
        if (isInT(alpha[idx]) || alpha[idx] == '&') {
            /* 判断是否已经在FIRST集中 */
            auto itt = FS.find(alpha[idx]);
            if (itt == FS.end()) {
                FS.insert(alpha[idx]);
            }
        } else {
            char B = alpha[idx];
            set<char> &FB = first[B];
            for (auto it = first[B].begin(); it != first[B].end(); it++) {
                /* 当前符号FIRST集包含空,标记next为真,并跳过当前循环 */
                if (*it == '&') {
                    next = true;
                    continue;
                }
                /* 把非空元素加入到FIRST集中 */
                auto itt = FS.find(*it);
                if (itt == FS.end()) {
                    FS.insert(*it);
                }
            }
        }
        idx = idx + 1;
    }
    /* 如果到达产生式右部末尾next还为真,说明alpha可以推空,将空加入到FIRST集中 */
    if (next) {
        FS.insert('&');
    }
}
/* 求非终结符的FOLLOW集 */
void getFollowSet()
{
    /* 初始化终结符的FOLLOW集为空集 */
    for (int i = 0; i < grammar.N.size(); i++) {
        char B = grammar.N[i];
        follow[B] = set<char>();
    }
    /* 将$加入到文法的开始符号的FOLLOW集中 */
    char S = grammar.N[0];
    follow[S].insert('$');

    bool change = true;
    while (change) {
        change = false;
        /* 枚举每个产生式 */
        for (int i = 0; i < grammar.prods.size(); i++) {
            Production &P = grammar.prods[i];
            for (int j = 0; j < P.rigths.size(); j++) {
                char B = P.rigths[j];
                /* 当前符号是非终结符 */
                if (isInN(B)) {
                    set<char> &FB = follow[B];
                    set<char> FS;
                    /* alpha是从当前符号下一个符号开始的符号串 */
                    vector<char> alpha(P.rigths.begin() + j + 1, P.rigths.end());
                    /* 求alpha的FIRST集,即FS */
                    getFirstByAlphaSet(alpha, FS);
                    /* 将alpha的FIRST集中所有非空元素加入到当前符号的FOLLOW集中 */
                    for (auto it = FS.begin(); it != FS.end(); it++) {
                        if (*it == '&') {
                            continue;
                        }
                        auto itt = FB.find(*it);
                        if (itt == FB.end()) {
                            change = true;
                            FB.insert(*it);
                        }
                    }
                    /* 如果alpha能推空,或者当前符号是产生式右部末尾,则将文法左部符号的FOLLOW集加入到当前符号的FOLLOW集中 */
                    auto itt = FS.find('&');
                    if (itt != FS.end() || (j + 1) >= P.rigths.size()) {
                        char A = P.left;    // A为左部符号
                        for (auto it = follow[A].begin(); it != follow[A].end(); it++) {
                            auto itt = FB.find(*it);
                            if (itt == FB.end()) {
                                change = true;
                                FB.insert(*it);
                            }
                        }    
                    }
                }
            }
        }
    }

    printf("FOLLOW:\n");
    for (int i = 0; i < grammar.N.size(); i++) {
        char X = grammar.N[i];
        printf("%c: ", X);
        for (auto it = follow[X].begin(); it != follow[X].end(); it++) {
            printf("%c ", *it);
        }
        printf("\n");
    }
}
/* 把生成式插入到预测分析表对应的项中 */
void insertTOForecastAnalysisTable(char A, char a, Production &P)
{
    /* 根据A和a找到对应表项 */
    int i = isInN(A) - 1;
    int j = isInT(a) - 1;
    /* 把P.left->P.rights插入*/
    M[i][j].push_back(P.left);
    M[i][j].push_back('-');
    M[i][j].push_back('>');
    for (auto it = P.rigths.begin(); it != P.rigths.end(); it++) {
        M[i][j].push_back(*it);
    }
}
/* 取出预测分析表对应的项中的产生式 */
void getFromForecastAnalysisTable(char A, char a, vector<char> &s)
{
    /* 根据A和a找到对应表项 */
    int i = isInN(A) - 1;
    int j = isInT(a) - 1;
    /* 取出 */
    s.assign(M[i][j].begin(), M[i][j].end());
}
/* 构建预测分析表 */
void productForecastAnalysisTable()
{
    /* 枚举所有产生式 */
    for (int i = 0; i < grammar.prods.size(); i++) {
        /* 假设P为 A->alpha */
        Production &P = grammar.prods[i];
        set<char> FS;
        /* 对每个 a in FIRST(alpha) 把 A->alpha放入M[A, a]中 */
        getFirstByAlphaSet(P.rigths, FS);
        for (auto it = FS.begin(); it != FS.end(); it++) {
            insertTOForecastAnalysisTable(P.left, *it, P);
        }
        /* 如果alpha能推空,则把每个b in FOLLOW(A) 把 A->alpha放入M[A, b]中*/
        auto itt = FS.find('&');
        if (itt != FS.end()) {
            for (auto it = follow[P.left].begin(); it != follow[P.left].end(); it++) {
                insertTOForecastAnalysisTable(P.left, *it, P);
            }
        }
    }
    /* 输出预测分析表 */
    printf("forecast analysis table:\n");
    printf("\t");
    for (int i = 0; i < grammar.T.size(); i++) {
        printf("%c\t\t", grammar.T[i]);
    }
    printf("\n");
    for (int i = 0; i < grammar.N.size(); i++) {
        printf("%c\t", grammar.N[i]);
        for (int j = 0; j < grammar.T.size(); j++) {
            for(auto k = M[i][j].begin(); k != M[i][j].end(); k++) {
                printf("%c", *k);
            }
            printf("\t\t");
        }
        printf("\n");
    }
}
/* 读入并初始化语法 */
void initGrammar()
{
    printf("Please enter the num of production:\n");
    cin >> grammar.num;
    string s;
    printf("Please enter the production:\n");
    for (int i = 0; i < grammar.num; i++) {
        cin >> s;
        Production tmp;
        tmp.left = s[0];
        for (int j = 3; j < s.size(); j++) {
            tmp.rigths.push_back(s[j]);
        }
        grammar.prods.push_back(tmp);
    }
    printf("Please enter the non-terminators(end with #):\n");
    char ch;
    cin >> ch;
    while (ch != '#') {
        grammar.N.push_back(ch);
        cin >> ch;
    }
    printf("Please enter the terminators(end with #):\n");
    cin >> ch;
    while (ch != '#') {
        grammar.T.push_back(ch);
        cin >> ch;
    }
    /* 把$当作终结符 */
    grammar.T.push_back('$');
    /* 求FIRST集和FOLLOW集 */
    getFirstSet();
    getFollowSet();

    /* 生成预测分析表 */
    productForecastAnalysisTable();

    /* 读入待分析串并初始化分析栈 */
    printf("Please enter the String to be analyzed:\n");
    cin >> str;
    str += '$';
    ST.push('$');
    ST.push(grammar.N[0]);
}
/* 分析程序 */
void process()
{
    /* 指向当前字符 */
    int ip = 0;
    /* 栈顶符号X, 和当前输入符号a */
    char X, a;
    printf("The answer:\n");
    do{
        X = ST.top();
        a = str[ip];
        /* 如果是终结符或者$ */
        if (isInT(X)) {
            /* 如果栈顶符号和当前符号匹配,出栈,指针前移 */
            if (X == a) {
                ST.pop();
                ip = ip + 1;
            } else { /* 不匹配报错 */
                printf("error1\n");
            }
        } else {    //非终结符
            vector<char> s;
            /* 取出对应预测分析表的项 */
            getFromForecastAnalysisTable(X, a, s);
            /* 预测分析表项中有元素 */
            if (!s.empty()) {
                /* 弹栈并将右部符号串逆序入栈 */
                ST.pop();
                for (int i = s.size() - 1; i >= 3; i--) {
                    if (s[i] != '&') { // 为空时不入栈
                        ST.push(s[i]);
                    }
                }
                /* 输出产生式 */
                for (int i = 0; i < s.size(); i++) {
                        printf("%c", s[i]);
                }
                printf("\n");
            } else { // 空,报错
                printf("error2\n");
            }
        }
    } while (X != '$');
}

int main()
{
    initGrammar();
    process();
    return 0;
}

三、LR(0)

#include<iostream>
#include<vector>
#include<set>
#include<fstream> 
#include<sstream>
#include<algorithm>
#include<iomanip>
#define maxn 100
using namespace std;
struct G{
	char left;
	int dot=0;
	string right;
};
string Action[maxn][maxn];
int Goto[maxn][maxn];
vector<char> tmp_index[maxn];//第i个状态的全部首字母 
string Terminal="";
string NotTerminal="";
set<char> First[maxn];
int book[maxn]={0};
G g[maxn];
int flag=0;
int total;
vector<G> NotTerminal_closure[maxn];
vector<G> I[maxn];
vector<char> stack;
vector<char> input;
int hadFirst[maxn]={0};
int haveNone[maxn]={0};
void getFirst(char X)
{
	int index=NotTerminal.find(X);
	if(hadFirst[index]>total)return;
	else hadFirst[index]++;
	for(int i=0;i<total;i++)
	{
		if(g[i].left==X)
		{
			if(haveNone[index]) {
				First[index].insert('@');
				if(g[i].right[0]=='@'){
					continue;
				}	
			}
			//第一个为终结符 
			if(Terminal.find(g[i].right[0])!=string::npos)
				{
					First[index].insert(g[i].right[0]);
				}
			else{
			//第一个为非终结符 
				for(int j=0;j<g[i].right.length();j++)
				 {
				 	//直到找到终结符或者不能推出空串的非终结符才停止
					if(Terminal.find(g[i].right[j])!=string::npos)
					{
						First[index].insert(g[i].right[j]);	
						break;
					}else{
						int index_temp = NotTerminal.find(g[i].right[j]);
						getFirst(g[i].right[j]);
						set<char>::iterator iter;
						for(iter=First[index_temp].begin();iter!=First[index_temp].end();iter++)
						{
								First[index].insert(*iter);		
						} 
				 		if(!haveNone[index_temp])break;
				 }
				 
			}
		}
		}
	}
}

string getsearchFirst(string str){
	string temp_str="";
	for(int i=0;i<str.length();i++)
	{
		if(Terminal.find(str[i])!=string::npos)
		{
			temp_str+=str[i];
			break;
		}else{
			int index = NotTerminal.find(str[i]);
			set<char>::iterator iter;
			for(iter=First[index].begin();iter!=First[index].end();iter++)
			{
				temp_str+=(*iter);
			}
			if(!haveNone[index])break;
		}	
	}

	return temp_str;
}

void getAnalysis(string str)
{
	stack.push_back('#');
	stack.push_back(0);
	input.push_back('#');
	for(int i=str.length()-1;i>=0;i--) input.push_back(str[i]);
	cout<<setw(20)<<"分析栈"<<setw(20)<<"输入串"<<setw(20)<<"动作"<<endl;
	do{
		
		string output_str="";
		for(int i=0;i<stack.size();i++){
			if(i%2==0)
			 output_str+=stack[i];
			 else
			 {
			 	stringstream ss;
             	ss<<int(stack[i]);
             	output_str+=ss.str();
			 }
		}
		cout<<setw(20)<<output_str;
		output_str="";
		for(int i=input.size()-1;i>=0;i--) output_str+=input[i];
		cout<<setw(20)<<output_str; 
		int stack_top = stack[stack.size()-1];
		char in_top = input[input.size()-1];
		int input_top = Terminal.find(in_top);
		cout<<input_top;
		string output = Action[stack_top][input_top];
		cout<<setw(20)<<output<<endl;
		if(output[0]=='S') 
		{
			int move=0;
			for(int i=1;i<output.length();i++)
			move=move*10+(output[i]-'0');
			stack.push_back(in_top);
			stack.push_back(move);
			input.pop_back();
		}else if(output[0]=='r')
		{
		    int num=0;
			for(int i=1;i<output.length();i++)
			num+=num*10+(output[i]-'0');
			int p=g[num-1].right.length()-1;
			
			while(p>=0&&stack.size()>=2&&stack[stack.size()-2]==g[num-1].right[p--]){
				stack.pop_back();
				stack.pop_back();
			}
			
			int go_to_2 = NotTerminal.find(g[num-1].left);
			int go_to_1 = stack[(stack.size()-1)];
			int go_to = Goto[go_to_1][go_to_2];
			stack.push_back(g[num-1].left);
			stack.push_back(go_to);
		}else if(output=="acc"){
			//cout<<setw(20)<<"配对成功!"; 
			return;
		}	
	}while(true);
}



void getTable(G item,char X,int num)
{
	if(Terminal.find(X)!=string::npos){
        int t=Terminal.find(X);
        if(item.right.length()==item.dot){
           if(item.left==g[0].left){
            	Action[num][(Terminal.length()-1)]="acc";
			}else{
				stringstream ss;
             	ss<<(flag+1);
				Action[num][t]="S"+ss.str();
				for(int j=0;j<total;j++){
            	if(item.left==g[j].left&&item.right==g[j].right){
            		stringstream ss;
            		ss<<(j+1);
            		for(int k=0;k<=Terminal.length();k++)
					Action[(flag+1)][k]="r"+ss.str();;
            		break;
				}
				}
			}
            
		}else{
			stringstream ss;
             ss<<(flag+1);
			Action[num][t]="S"+ss.str();
			
			}
	}else{
		
		int t=NotTerminal.find(X);
		Goto[num][t]=flag+1;
		
		if(item.right.length()==item.dot){
			
			if(item.left==g[0].left)
			Action[(flag+1)][(Terminal.length()-1)]="acc";
			else{
            		for(int j=0;j<total;j++)
					if(item.left==g[j].left&&item.right==g[j].right){
            		stringstream ss;
            		ss<<(j+1);
            		for(int k=0;k<=Terminal.length();k++) 
					Action[(flag+1)][k]="r"+ss.str();;
            		break;
				}
			}
			
			
		}
					
	}
}

vector<G> go(vector<G> item,char X,int num)
{
	vector<G> tmp;
    for(int i=0;i<item.size();i++)
    {
    	if(item[i].right.length()!=item[i].dot)
            if(item[i].right[(item[i].dot)] == X){
            	//cout<<item[i].right<<"haha"<<endl;	
            	item[i].dot++;
            	getTable(item[i],X,num);
            	
                tmp.push_back(item[i]);
		}
	}
         
//	for(int i=0;i<tmp.size();i++)
//	  cout<<"tmpbegin   "<<tmp[i].left<<"->"<<tmp[i].right<<" "<<tmp[i].dot<<" "<<X<<tmp.empty()<<endl;
    int book[maxn]={0};
	if(!tmp.empty()){
    	for(int i=0;i<tmp.size();i++)
    	{
    		if(NotTerminal.find(tmp[i].right[(tmp[i].dot)])!=string::npos)
    		{
    			
				
    			int t=NotTerminal.find(tmp[i].right[(tmp[i].dot)]);
    			if(!book[t])
    			for(int j=0;j<NotTerminal_closure[t].size();j++)
    			{
    				G temp_g = NotTerminal_closure[t][j];
    			    tmp.push_back(temp_g);	
				}
				book[t]=1;
			}
		}
//		for(int i=0;i<tmp.size();i++)
//	  cout<<"tmpend   "<<tmp[i].left<<"->"<<tmp[i].right<<" "<<tmp[i].dot<<" "<<X<<tmp.empty()<<endl;
	}
	
	return tmp;
}
//求状态规范族 
void get_I()
{
	I[0].push_back(g[0]);
		//非终结符 
		int book[maxn]={0};
		for(int i=0;i<I[0].size();i++)
    	{
    		if(NotTerminal.find(I[0][i].right[(I[0][i].dot)])!=string::npos)
    		{
    			
    			int t=NotTerminal.find(I[0][i].right[(I[0][i].dot)]);
    			if(!book[t])
    			for(int j=0;j<NotTerminal_closure[t].size();j++)
    			{
    			   G temp_g = NotTerminal_closure[t][j];
				    I[0].push_back(temp_g);	
    			}
    			book[t]=1;
			}
		}
		tmp_index[0].push_back(g[0].right[0]);
		for(int i=0;i<=flag;i++)
		{
			for(int j=0;j<I[i].size();j++)
			{
				//if(!tmp_index.empty())
				if(I[i][j].dot<I[i][j].right.length()&&I[i][j].right[(I[i][j].dot)]!='@'&&find(tmp_index[i].begin(),tmp_index[i].end(),I[i][j].right[(I[i][j].dot)])==tmp_index[i].end())
				tmp_index[i].push_back(I[i][j].right[(I[i][j].dot)]);
			}
			for(int it=0;it<tmp_index[i].size();it++)
			{
				vector<G> temp=go(I[i],tmp_index[i][it],i);
				if(!temp.empty())
				I[++flag]=temp;
			}
		}
		
		for(int i=0;i<=flag;i++)
		{
			cout<<"I"<<i<<":"<<endl;
			for(int j=0;j<I[i].size();j++){
			 cout<<I[i][j].left<<"->"<<I[i][j].right.substr(0,I[i][j].dot)<<"."<<I[i][j].right.substr(I[i][j].dot,I[i][j].right.length()-I[i][j].dot)<<" "<<I[i][j].dot<<endl; 
		}
	}
	
}    




int main()
{
	ifstream read;
	read.open("LR(0)input.txt",ios::app);
	read>>total;
	for(int i=0;i<total;i++)
	{
		//getchar();
		read>>g[i].left>>g[i].right;
		cout<<g[i].left<<"->"<<g[i].right<<endl;
		g[i].dot=0;
		if(NotTerminal.find(g[i].left)==string::npos)
		{
			NotTerminal+=g[i].left;
		}
		for(int j=0;j<g[i].right.length();j++)
		{
			if(g[i].right[j]=='@'){
				int temp=NotTerminal.find(g[i].left);
				book[temp]=1;
			}
			else if(g[i].right[j]>='A'&&g[i].right[j]<='Z')
				{
					if(NotTerminal.find(g[i].right[j])==string::npos)
					{
					  NotTerminal+=g[i].right[j];
					 
					}
				}
			else if(Terminal.find(g[i].right[j])==string::npos)
				{
					Terminal+=g[i].right[j];
				}
			
		}
		NotTerminal_closure[NotTerminal.find(g[i].left)].push_back(g[i]);
	}
	for(int i=0;i<NotTerminal.length();i++)
	{
		getFirst(NotTerminal[i]);
		cout<<"First("<<NotTerminal[i]<<")={";
		set<char>::iterator iter;
		for(iter=First[i].begin();iter!=First[i].end();iter++)
		{
			cout<<(*iter)<<",";
		}
		cout<<"}"<<endl;
	}
	cout<<"终结符:"<<Terminal<<endl;
	cout<<"非终结符:"<<NotTerminal<<endl;
	for(int i=0;i<NotTerminal.length();i++)
	{
		cout<<NotTerminal_closure[i].size();
		for(int j=0;j<NotTerminal_closure[i].size();j++)
		cout<<NotTerminal_closure[i][j].left<<"->"<<NotTerminal_closure[i][j].right<<" ";
		cout<<endl;
	}
	Terminal+="#";
	get_I();
	for(int i=0;i<=flag;i++)
	{
		for(int j=0;j<=Terminal.length();j++)
		{
			if(!Action[i][j].empty())cout<<"i="<<i<<",j="<<j<<","<<Action[i][j]<<endl;
		}
	}
	for(int i=0;i<NotTerminal.length();i++)
	cout<<NotTerminal[i]<<" ";
	cout<<"#"<<endl;
	for(int i=0;i<=flag;i++)
	{
		for(int j=0;j<=NotTerminal.length();j++)
		cout<<Goto[i][j]<<" ";
		cout<<endl;
	}
	//getAnalysis("aedaec") ;
	getAnalysis("vi,i:r") ;
	return 0;
} 

四、LR(1)

#include <cstdio>
#include <vector>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <stack>
#include <queue>
using namespace std;

/* 产生式结构体,左部符号和右部符号串 */
struct Production {
    char left;
    vector<char> rigths;
    /* 重载== */
    bool operator==(Production& rhs) const {
        if (left != rhs.left)
            return false;
        for (int i = 0; i < rigths.size(); i++) {
            if (i >= rhs.rigths.size())
                return false;
            if (rigths[i] != rhs.rigths[i])
                return false;
        }
        return true;
    }
};

/* LR1项目 */
struct LR1Item {
    Production p;
    /* 点的位置 */
    int location;
    /* 向前看符号 */
    char next;
};

/* LR1项目集 */
struct LR1Items {
    vector<LR1Item> items;
};

/* LR1项目集规范族 */
struct CanonicalCollection {
    /* 项目集集合 */
    vector<LR1Items> items;
    /* 保存DFA的图,first为转移到的状态序号,second是经什么转移 */
    vector< pair<int, char> > g[100];
}CC;

/* 文法结构体 */
struct Grammar {
    int num;  // 产生式数量
    vector<char> T;   // 终结符
    vector<char> N;   // 非终结符
    vector<Production> prods;  //产生式
}grammar;

/* FIRST集和FOLLOW集 */
map<char, set<char> > first;
map<char, set<char> > follow;

/* DFA队列, 用于存储待转移的有效项目集 */
queue< pair<LR1Items, int> > Q;

/* action表和goto表 */
pair<int, int> action[100][100]; // first表示分析动作,0->ACC 1->S 2->R second表示转移状态或者产生式序号
int goton[100][100];

/* 待分析串 */
string str;
/* 分析栈 */
stack< pair<int, char> > ST; // first是state,second 是symble

/* 判断ch是否是终结符 */
int isInT(char ch)
{
    for (int i = 0; i < grammar.T.size(); i++) {
        if (grammar.T[i] == ch) {
            return i + 1;
        }
    }
    return 0;
}
/* 判断ch是否是非终结符 */
int isInN(char ch)
{
    for (int i = 0; i < grammar.N.size(); i++) {
        if (grammar.N[i] == ch) {
            return i + 1;
        }
    }
    return 0;
}
/* 求(T U N)的FIRST集 */
void getFirstSet()
{
    /* 终结符的FIRST集是其本身 */
    for (int i = 0; i < grammar.T.size(); i++) {
        char X = grammar.T[i];
        set<char> tmp;
        tmp.insert(X);
        first[X] = tmp;
    }
    /* 当非终结符的FIRST集发生变化时循环 */
    bool change = true;
    while (change) {
        change = false;
        /* 枚举每个产生式 */
        for (int i = 0; i < grammar.prods.size(); i++) {
            Production &P = grammar.prods[i];
            char X = P.left;
            set<char> &FX = first[X];
            /* 如果右部第一个符号是空或者是终结符,则加入到左部的FIRST集中 */
            if (isInT(P.rigths[0]) || P.rigths[0] == '&') {
                /* 查找是否FIRST集是否已经存在该符号 */
                auto it = FX.find(P.rigths[0]);
                /* 不存在 */
                if (it == FX.end()) {
                    change = true; // 标注FIRST集发生变化,循环继续
                    FX.insert(P.rigths[0]);
                }
            } else {
                /* 当前符号是非终结符,且当前符号可以推出空,则还需判断下一个符号 */
                bool next = true;
                /* 待判断符号的下标 */
                int idx = 0;
                while (next && idx < P.rigths.size()) {
                    next = false;
                    char Y = P.rigths[idx];
                    set<char> &FY = first[Y];
                    for (auto it = FY.begin(); it != FY.end(); it++) {
                        /* 把当前符号的FIRST集中非空元素加入到左部符号的FIRST集中 */
                        if (*it != '&') {
                            auto itt = FX.find(*it);
                            if (itt == FX.end()) {
                                change = true;
                                FX.insert(*it);
                            }
                        }
                    }
                    /* 当前符号的FIRST集中有空, 标记next为真,idx下标+1 */
                    auto it = FY.find('&');
                    if (it != FY.end()) {
                        next = true;
                        idx = idx + 1;
                    }
                }
                
            }
        }
    }
    
    printf("FIRST:\n");
    for (int i = 0; i < grammar.N.size(); i++) {
        char X = grammar.N[i];
        printf("%c: ", X);
        for (auto it = first[X].begin(); it != first[X].end(); it++) {
            printf("%c ", *it);
        }
        printf("\n");
    }
}
/* 产找alpha串的FIRST集, 保存到FS集合中 */
void getFirstByAlphaSet(vector<char> &alpha, set<char> &FS)
{
    /* 当前符号是非终结符,且当前符号可以推出空,则还需判断下一个符号 */
    bool next = true;
    int idx = 0;
    while (idx < alpha.size() && next) {
        next = false;
        /* 当前符号是终结符或空,加入到FIRST集中 */
        if (isInT(alpha[idx]) || alpha[idx] == '&') {
            /* 判断是否已经在FIRST集中 */
            auto itt = FS.find(alpha[idx]);
            if (itt == FS.end()) {
                FS.insert(alpha[idx]);
            }
        } else {
            char B = alpha[idx];
            set<char> &FB = first[B];
            for (auto it = first[B].begin(); it != first[B].end(); it++) {
                /* 当前符号FIRST集包含空,标记next为真,并跳过当前循环 */
                if (*it == '&') {
                    next = true;
                    continue;
                }
                /* 把非空元素加入到FIRST集中 */
                auto itt = FS.find(*it);
                if (itt == FS.end()) {
                    FS.insert(*it);
                }
            }
        }
        idx = idx + 1;
    }
    /* 如果到达产生式右部末尾next还为真,说明alpha可以推空,将空加入到FIRST集中 */
    if (next) {
        FS.insert('&');
    }
}

/* 判断是LR1项目t否在有效项目集I中 */
bool isInLR1Items(LR1Items &I, LR1Item &t)
{
    for (auto it = I.items.begin(); it != I.items.end(); it++) {
        LR1Item &item = *it;
        if (item.p == t.p && item.location == t.location && item.next == t.next)
            return true;
    }
    return false;
}

/* 打印某个项目集 */
void printLR1Items(LR1Items &I)
{
    for (auto it = I.items.begin(); it != I.items.end(); it++) {
        LR1Item &L = *it;
        printf("%c->", L.p.left);
        for (int i = 0; i < L.p.rigths.size(); i++) {
            if (L.location == i)
                printf(".");
            printf("%c", L.p.rigths[i]);
        }
        if (L.location == L.p.rigths.size())
            printf(".");
        printf(",%c   ", L.next);
    }
    printf("\n");
}

/* 求I的闭包 */
void closure(LR1Items &I)
{
    bool change =  true;
    while (change) {
        change = false;
        LR1Items J;
        /* 枚举每个项目 */
        J.items.assign(I.items.begin(), I.items.end());
        for (auto it = J.items.begin(); it != J.items.end(); it++) {
            LR1Item &L = *it;
            /* 非规约项目 */
            if (L.location < L.p.rigths.size()) {
                char B = L.p.rigths[L.location];
                if (isInN(B)) {
                    /* 把符合条件的LR1项目加入闭包中 */
                   
                    /* 先求出B后面的FIRST集 */
                    set<char> FS;
                    vector<char> alpha;
                    alpha.assign(L.p.rigths.begin() + L.location + 1, L.p.rigths.end());
                    alpha.push_back(L.next);
                    getFirstByAlphaSet(alpha, FS);

                    for (int i = 0; i < grammar.prods.size(); i++) {
                        Production &P = grammar.prods[i];
                        if (P.left == B) {
                            /* 枚举每个b in B后面的FIRST集 */
                            for (auto it = FS.begin(); it != FS.end(); it++) {
                                char b = *it;
                                LR1Item t;
                                t.location = 0;
                                t.next = b;
                                t.p.left = P.left;
                                t.p.rigths.assign(P.rigths.begin(), P.rigths.end());
                                if (!isInLR1Items(I, t)) {
                                    /* 标记改变 */
                                    change = true;
                                    I.items.push_back(t);
                                } 
                            }
                        } 
                    }
                }
            }
        }
    }
}
/* 判断是否在项目集规范族中,若在返回序号 */
int isInCanonicalCollection(LR1Items &I)
{
    for (int i = 0; i < CC.items.size(); i++) {
        LR1Items &J = CC.items[i];
        bool flag = true;
        if (J.items.size() != I.items.size()) {
            flag = false;
            continue;
        }
        /* 每个项目都在该项目集中,则认为这个两个项目集相等 */
        for (auto it = I.items.begin(); it != I.items.end(); it++) {
            LR1Item &t = *it;
            if (!isInLR1Items(J, t)) {
                flag = false;
                break;
            }
        }
        if (flag) {
            return i + 1;
        }
    }
    return 0;
}

/* 转移函数,I为当前的项目集,J为转移后的项目集, 经X转移 */
void go(LR1Items &I, char X, LR1Items &J)
{
    for (auto it = I.items.begin(); it != I.items.end(); it++) {
        LR1Item &L = *it;
        /* 非规约项目 */
        if (L.location < L.p.rigths.size()) {
            char B = L.p.rigths[L.location];
            /* 如果点后面是非终结符,且非终结符为X,点位置加1, 加入到转移项目集中*/
            if (B == X) {
                LR1Item t;
                t.location = L.location + 1;
                t.next = L.next;
                t.p.left = L.p.left;
                t.p.rigths.assign(L.p.rigths.begin(), L.p.rigths.end());
                J.items.push_back(t);
            }
        }
    }
    /* 若J中有项目,则求其闭包 */
    if (J.items.size() > 0) {
        closure(J);
    }
}

/* 构建DFA和项目集规范族 */
void DFA()
{
    /* 构建初始项目集 */
    LR1Item t;
    t.location = 0;
    t.next = '$';
    t.p.left = grammar.prods[0].left;
    t.p.rigths.assign(grammar.prods[0].rigths.begin(), grammar.prods[0].rigths.end());
    LR1Items I;
    I.items.push_back(t);
    closure(I);
    /* 加入初始有效项目集 */
    CC.items.push_back(I);
    /* 把新加入的有效项目集加入待扩展队列中 */
    Q.push(pair<LR1Items, int>(I, 0));
    while (!Q.empty()) {
        LR1Items &S = Q.front().first;
        int sidx = Q.front().second;
        /* 遍历每个终结符 */
        for (int i = 0; i  < grammar.T.size(); i++) {
            LR1Items D;
            go(S, grammar.T[i], D);
            int idx;
            /* 若不为空 */
            if (D.items.size() > 0) {
                /* 查找是否已经在有效项目集族里 */
                idx = isInCanonicalCollection(D); 
                if (idx > 0) {
                    idx = idx - 1;
                } else {
                    idx = CC.items.size();
                    CC.items.push_back(D);
                    /* 把新加入的有效项目集加入待扩展队列中 */
                    Q.push(pair<LR1Items, int>(D, idx));
                }
                /* 从原状态到转移状态加一条边,边上的值为转移符号 */
                CC.g[sidx].push_back(pair<char, int>(grammar.T[i], idx));
            }
        }
        /* 遍历每个非终结符 */
        for (int i = 0; i  < grammar.N.size(); i++) {
            LR1Items D;
            go(S, grammar.N[i], D);
            int idx;
            if (D.items.size() > 0) {
                /* 查找是否已经在有效项目集族里 */
                idx = isInCanonicalCollection(D); 
                if (idx != 0) {
                    idx = idx - 1;
                } else {
                    idx = CC.items.size();
                    CC.items.push_back(D);
                    /* 把新加入的有效项目集加入待扩展队列中 */
                    Q.push(pair<LR1Items, int>(D, idx));
                }
                /* 从原状态到转移状态加一条边,边上的值为转移符号 */
                CC.g[sidx].push_back(pair<char, int>(grammar.N[i], idx));
            }
        }
    /* 当前状态扩展完毕,移除队列*/
    Q.pop();
    }

    printf("CC size: %d\n", CC.items.size());
    for (int i = 0; i < CC.items.size(); i++) {
        printf("LR1Items %d:\n", i);
        printLR1Items(CC.items[i]);
        for (int j = 0; j < CC.g[i].size(); j++) {
            pair<char, int> p= CC.g[i][j];
            printf("to %d using %c\n", p.second, p.first);
        }
    }
}
/* 生成LR1分析表 */
void productLR1AnalysisTabel()
{
    for (int i = 0; i < CC.items.size(); i++) {
        LR1Items &LIt= CC.items[i];
        /* 构建action表 */
        for (auto it = LIt.items.begin(); it != LIt.items.end(); it++) {
            LR1Item &L = *it;
            /* 非规约项目 */
            if (L.location < L.p.rigths.size()) {
                char a = L.p.rigths[L.location];
                int j = isInT(a);
                /* a是终结符 */
                if (j > 0) {
                    j = j - 1;
                    /* 找到对应a的出边,得到其转移到的状态 */
                    for (int k = 0; k < CC.g[i].size(); k++) {
                        pair<char, int> p = CC.g[i][k];
                        if (p.first == a) {
                            action[i][j].first = 1; // 1->S
                            action[i][j].second = p.second;  //转移状态
                            break;
                        }
                    }
                }
            } else { // 规约项目
                /* 接受项目 */
                if (L.p.left == grammar.prods[0].left) {
                    if (L.next == '$')
                        action[i][grammar.T.size() - 1].first = 3;
                } else {
                    /* 终结符 */
                    int  j = isInT(L.next) - 1;
                    /* 找到产生式对应的序号 */
                    for (int k = 0; k < grammar.prods.size(); k++) {
                        if (L.p == grammar.prods[k]) {
                            action[i][j].first = 2;
                            action[i][j].second = k;
                            break;
                        }
                    }

                }
            }
        }
        /* 构建goto表 */
        for (int k = 0; k < CC.g[i].size(); k++) {
            pair<char, int> p = CC.g[i][k];
            char A = p.first;
            int j = isInN(A);
            /* 终结符 */
            if (j > 0) {
                j = j - 1;
                goton[i][j] = p.second; //转移状态
            }
        }
    }
    /* 打印LR1分析表 */
    for (int i = 0; i < grammar.T.size() / 2; i++)
        printf("\t");
    printf("action");
    for (int i = 0; i < grammar.N.size() / 2 + grammar.T.size() / 2 + 1; i++)
        printf("\t");
    printf("goto\n");
    printf("\t");
    for (int i = 0; i  < grammar.T.size(); i++) {
        printf("%c\t", grammar.T[i]);
    }
    printf("|\t");
    for (int i = 1; i  < grammar.N.size(); i++) {
        printf("%c\t", grammar.N[i]);
    }
    printf("\n");
    for (int i = 0; i < CC.items.size(); i++) {
        printf("%d\t", i);
        for (int j = 0; j < grammar.T.size(); j++) {
            if (action[i][j].first == 1) {
                printf("%c%d\t", 'S', action[i][j].second);
            } else if (action[i][j].first == 2) {
                printf("%c%d\t", 'R', action[i][j].second);
            } else if (action[i][j].first == 3) {
                printf("ACC\t");
            } else {
                printf("\t");
            }
        }
        printf("|\t");
        for (int j = 1; j < grammar.N.size(); j++) {
            if (goton[i][j]) {
                printf("%d\t", goton[i][j]);
            } else {
                printf("\t");
            }
            
        }
        printf("\n");
    }
}


void initGrammar()
{
    printf("Please enter the num of production:\n");
    cin >> grammar.num;
    string s;
    printf("Please enter the production:\n");
    for (int i = 0; i < grammar.num; i++) {
        cin >> s;
        Production tmp;
        tmp.left = s[0];
        for (int j = 3; j < s.size(); j++) {
            tmp.rigths.push_back(s[j]);
        }
        grammar.prods.push_back(tmp);
    }
    printf("Please enter the non-terminators(end with #):\n");
    char ch;
    cin >> ch;
    while (ch != '#') {
        grammar.N.push_back(ch);
        cin >> ch;
    }
    printf("Please enter the terminators(end with #):\n");
    cin >> ch;
    while (ch != '#') {
        grammar.T.push_back(ch);
        cin >> ch;
    }
    /* 把$当作终结符 */
    grammar.T.push_back('$');
    /* 求FIRST集 */
    getFirstSet();

    /* 构建DFA和SLR1预测分析表 */
    DFA();
    productLR1AnalysisTabel();
    
    /* 读入待分析串并初始化分析栈 */
    printf("Please enter the String to be analyzed:\n");
    cin >> str;
    str += '$';
    ST.push(pair<int, char>(0, '-'));
}
/* 分析程序 */
void process()
{
    int ip = 0;
    printf("The ans:\n");
    do {
        int s = ST.top().first;
        char a = str[ip];
        int j = isInT(a) - 1;
        /* 移进 */
        if (action[s][j].first == 1) {
            ST.push(pair<int, char>(action[s][j].second, a));
            ip = ip + 1;
        } else if (action[s][j].first == 2) { // 规约
            Production &P = grammar.prods[action[s][j].second];
            /* 弹出并输出产生式 */
            printf("%c->", P.left);
            for (int i = 0; i < P.rigths.size(); i++) {
                ST.pop();
                printf("%c", P.rigths[i]);
            }
            printf("\n");
            s = ST.top().first;
            char A = P.left;
            j = isInN(A) - 1;
            ST.push(pair<int, char>(goton[s][j], A));
        } else if (action[s][j].first == 3) {   //接受
            printf("ACC\n");
            return;
        } else {
            printf("error\n");
        }
    } while(1);
}
int main()
{
    initGrammar();
    process();
    return 0;
}

五、SLR(1)

#include <cstdio>
#include <vector>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <stack>
#include <queue>
using namespace std;

/* 产生式结构体,左部符号和右部符号串 */
struct Production {
    char left;
    vector<char> rigths;
    /* 重载== */
    bool operator==(Production& rhs) const {
        if (left != rhs.left)
            return false;
        for (int i = 0; i < rigths.size(); i++) {
            if (i >= rhs.rigths.size())
                return false;
            if (rigths[i] != rhs.rigths[i])
                return false;
        }
        return true;
    }
};

/* LR0项目 */
struct LR0Item {
    Production p;
    /* 点的位置 */
    int location;
};

/* LR0项目集 */
struct LR0Items {
    vector<LR0Item> items;
};

/* LR0项目集规范族 */
struct CanonicalCollection {
    /* 项目集集合 */
    vector<LR0Items> items;
    /* 保存DFA的图,first为转移到的状态序号,second是经什么转移 */
    vector< pair<int, char> > g[100];
}CC;

/* 文法结构体 */
struct Grammar {
    int num;  // 产生式数量
    vector<char> T;   // 终结符
    vector<char> N;   // 非终结符
    vector<Production> prods;  //产生式
}grammar;

/* FIRST集和FOLLOW集 */
map<char, set<char> > first;
map<char, set<char> > follow;

/* DFA队列, 用于存储待转移的有效项目集 */
queue< pair<LR0Items, int> > Q;

/* action表和goto表 */
pair<int, int> action[100][100]; // first表示分析动作,0->ACC 1->S 2->R second表示转移状态或者产生式序号
int goton[100][100];

/* 待分析串 */
string str;
/* 分析栈 */
stack< pair<int, char> > ST; // first是state,second 是symble

/* 判断ch是否是终结符 */
int isInT(char ch)
{
    for (int i = 0; i < grammar.T.size(); i++) {
        if (grammar.T[i] == ch) {
            return i + 1;
        }
    }
    return 0;
}
/* 判断ch是否是非终结符 */
int isInN(char ch)
{
    for (int i = 0; i < grammar.N.size(); i++) {
        if (grammar.N[i] == ch) {
            return i + 1;
        }
    }
    return 0;
}
/* 求(T U N)的FIRST集 */
void getFirstSet()
{
    /* 终结符的FIRST集是其本身 */
    for (int i = 0; i < grammar.T.size(); i++) {
        char X = grammar.T[i];
        set<char> tmp;
        tmp.insert(X);
        first[X] = tmp;
    }
    /* 当非终结符的FIRST集发生变化时循环 */
    bool change = true;
    while (change) {
        change = false;
        /* 枚举每个产生式 */
        for (int i = 0; i < grammar.prods.size(); i++) {
            Production &P = grammar.prods[i];
            char X = P.left;
            set<char> &FX = first[X];
            /* 如果右部第一个符号是空或者是终结符,则加入到左部的FIRST集中 */
            if (isInT(P.rigths[0]) || P.rigths[0] == '&') {
                /* 查找是否FIRST集是否已经存在该符号 */
                auto it = FX.find(P.rigths[0]);
                /* 不存在 */
                if (it == FX.end()) {
                    change = true; // 标注FIRST集发生变化,循环继续
                    FX.insert(P.rigths[0]);
                }
            } else {
                /* 当前符号是非终结符,且当前符号可以推出空,则还需判断下一个符号 */
                bool next = true;
                /* 待判断符号的下标 */
                int idx = 0;
                while (next && idx < P.rigths.size()) {
                    next = false;
                    char Y = P.rigths[idx];
                    set<char> &FY = first[Y];
                    for (auto it = FY.begin(); it != FY.end(); it++) {
                        /* 把当前符号的FIRST集中非空元素加入到左部符号的FIRST集中 */
                        if (*it != '&') {
                            auto itt = FX.find(*it);
                            if (itt == FX.end()) {
                                change = true;
                                FX.insert(*it);
                            }
                        }
                    }
                    /* 当前符号的FIRST集中有空, 标记next为真,idx下标+1 */
                    auto it = FY.find('&');
                    if (it != FY.end()) {
                        next = true;
                        idx = idx + 1;
                    }
                }
                
            }
        }
    }
    
    printf("FIRST:\n");
    for (int i = 0; i < grammar.N.size(); i++) {
        char X = grammar.N[i];
        printf("%c: ", X);
        for (auto it = first[X].begin(); it != first[X].end(); it++) {
            printf("%c ", *it);
        }
        printf("\n");
    }
}
/* 产找alpha串的FIRST集, 保存到FS集合中 */
void getFirstByAlphaSet(vector<char> &alpha, set<char> &FS)
{
    /* 当前符号是非终结符,且当前符号可以推出空,则还需判断下一个符号 */
    bool next = true;
    int idx = 0;
    while (idx < alpha.size() && next) {
        next = false;
        /* 当前符号是终结符或空,加入到FIRST集中 */
        if (isInT(alpha[idx]) || alpha[idx] == '&') {
            /* 判断是否已经在FIRST集中 */
            auto itt = FS.find(alpha[idx]);
            if (itt == FS.end()) {
                FS.insert(alpha[idx]);
            }
        } else {
            char B = alpha[idx];
            set<char> &FB = first[B];
            for (auto it = first[B].begin(); it != first[B].end(); it++) {
                /* 当前符号FIRST集包含空,标记next为真,并跳过当前循环 */
                if (*it == '&') {
                    next = true;
                    continue;
                }
                /* 把非空元素加入到FIRST集中 */
                auto itt = FS.find(*it);
                if (itt == FS.end()) {
                    FS.insert(*it);
                }
            }
        }
        idx = idx + 1;
    }
    /* 如果到达产生式右部末尾next还为真,说明alpha可以推空,将空加入到FIRST集中 */
    if (next) {
        FS.insert('&');
    }
}
/* 求非终结符的FOLLOW集 */
void getFollowSet()
{
    /* 初始化终结符的FOLLOW集为空集 */
    for (int i = 0; i < grammar.N.size(); i++) {
        char B = grammar.N[i];
        follow[B] = set<char>();
    }
    /* 将$加入到文法的开始符号的FOLLOW集中 */
    char S = grammar.N[0];
    follow[S].insert('$');

    bool change = true;
    while (change) {
        change = false;
        /* 枚举每个产生式 */
        for (int i = 0; i < grammar.prods.size(); i++) {
            Production &P = grammar.prods[i];
            for (int j = 0; j < P.rigths.size(); j++) {
                char B = P.rigths[j];
                /* 当前符号是非终结符 */
                if (isInN(B)) {
                    set<char> &FB = follow[B];
                    set<char> FS;
                    /* alpha是从当前符号下一个符号开始的符号串 */
                    vector<char> alpha(P.rigths.begin() + j + 1, P.rigths.end());
                    /* 求alpha的FIRST集,即FS */
                    getFirstByAlphaSet(alpha, FS);
                    // printf("%c:\n", B);
                    /* 将alpha的FIRST集中所有非空元素加入到当前符号的FOLLOW集中 */
                    for (auto it = FS.begin(); it != FS.end(); it++) {
                        // printf("%c ", *it);
                        if (*it == '&') {
                            continue;
                        }
                        auto itt = FB.find(*it);
                        if (itt == FB.end()) {
                            change = true;
                            FB.insert(*it);
                        }
                    }
                    // printf("\n");
                    /* 如果alpha能推空,或者当前符号是产生式右部末尾,则将文法左部符号的FOLLOW集加入到当前符号的FOLLOW集中 */
                    auto itt = FS.find('&');
                    if (itt != FS.end() || (j + 1) >= P.rigths.size()) {
                        char A = P.left;
                        for (auto it = follow[A].begin(); it != follow[A].end(); it++) {
                            auto itt = FB.find(*it);
                            if (itt == FB.end()) {
                                change = true;
                                FB.insert(*it);
                            }
                        }    
                    }
                }
            }
        }
    }

    printf("FOLLOW:\n");
    for (int i = 0; i < grammar.N.size(); i++) {
        char X = grammar.N[i];
        printf("%c: ", X);
        for (auto it = follow[X].begin(); it != follow[X].end(); it++) {
            printf("%c ", *it);
        }
        printf("\n");
    }
}
/* 判断是LR0项目t否在有效项目集I中 */
bool isInLR0Items(LR0Items &I, LR0Item &t)
{
    for (auto it = I.items.begin(); it != I.items.end(); it++) {
        LR0Item &item = *it;
        if (item.p == t.p && item.location == t.location) 
            return true;
    }
    return false;
}

/* 打印某个项目集 */
void printLR0Items(LR0Items &I)
{
    for (auto it = I.items.begin(); it != I.items.end(); it++) {
        LR0Item &L = *it;
        printf("%c->", L.p.left);
        for (int i = 0; i < L.p.rigths.size(); i++) {
            if (L.location == i)
                printf(".");
            printf("%c", L.p.rigths[i]);
        }
        if (L.location == L.p.rigths.size())
            printf(".");
        printf(" ");
    }
    printf("\n");
}

/* 求I的闭包 */
void closure(LR0Items &I)
{
    bool change =  true;
    while (change) {
        change = false;
        LR0Items J;
        /* 枚举每个项目 */
        J.items.assign(I.items.begin(), I.items.end());
        for (auto it = J.items.begin(); it != J.items.end(); it++) {
            LR0Item &L = *it;
            /* 非规约项目 */
            if (L.location < L.p.rigths.size()) {
                char B = L.p.rigths[L.location];
                if (isInN(B)) {
                    /* 把符合条件的LR0项目加入闭包中 */
                    for (int i = 0; i < grammar.prods.size(); i++) {
                        Production &P = grammar.prods[i];
                        if (P.left == B) {
                            LR0Item t;
                            t.location = 0;
                            t.p.left = P.left;
                            t.p.rigths.assign(P.rigths.begin(), P.rigths.end());
                            if (!isInLR0Items(I, t)) {
                                /* 标记改变 */
                                change = true;
                                I.items.push_back(t);
                            } 
                        } 
                    }
                }
            }
        }
    }
}
/* 判断是否在项目集规范族中,若在返回序号 */
int isInCanonicalCollection(LR0Items &I)
{
    for (int i = 0; i < CC.items.size(); i++) {
        LR0Items &J = CC.items[i];
        bool flag = true;
        if (J.items.size() != I.items.size()) {
            flag = false;
            continue;
        }
        /* 每个项目都在该项目集中,则认为这个两个项目集相等 */
        for (auto it = I.items.begin(); it != I.items.end(); it++) {
            LR0Item &t = *it;
            if (!isInLR0Items(J, t)) {
                flag = false;
                break;
            }
        }
        if (flag) {
            return i + 1;
        }
    }
    return 0;
}

/* 转移函数,I为当前的项目集,J为转移后的项目集, 经X转移 */
void go(LR0Items &I, char X, LR0Items &J)
{
    for (auto it = I.items.begin(); it != I.items.end(); it++) {
        LR0Item &L = *it;
        /* 非规约项目 */
        if (L.location < L.p.rigths.size()) {
            char B = L.p.rigths[L.location];
            /* 如果点后面是非终结符,且非终结符为X,点位置加1, 加入到转移项目集中*/
            if (B == X) {
                LR0Item t;
                t.location = L.location + 1;
                t.p.left = L.p.left;
                t.p.rigths.assign(L.p.rigths.begin(), L.p.rigths.end());
                J.items.push_back(t);
            }
        }
    }
    /* 若J中有项目,则求其闭包 */
    if (J.items.size() > 0) {
        closure(J);
    }
}

/* 构建DFA和项目集规范族 */
void DFA()
{
    /* 构建初始项目集 */
    LR0Item t;
    t.location = 0;
    t.p.left = grammar.prods[0].left;
    t.p.rigths.assign(grammar.prods[0].rigths.begin(), grammar.prods[0].rigths.end());
    LR0Items I;
    I.items.push_back(t);
    closure(I);
    /* 加入初始有效项目集 */
    CC.items.push_back(I);
    /* 把新加入的有效项目集加入待扩展队列中 */
    Q.push(pair<LR0Items, int>(I, 0));
    while (!Q.empty()) {
        LR0Items &S = Q.front().first;
        int sidx = Q.front().second;
        /* 遍历每个终结符 */
        for (int i = 0; i  < grammar.T.size(); i++) {
            LR0Items D;
            go(S, grammar.T[i], D);
            int idx;
            /* 若不为空 */
            if (D.items.size() > 0) {
                /* 查找是否已经在有效项目集族里 */
                idx = isInCanonicalCollection(D); 
                if (idx > 0) {
                    idx = idx - 1;
                } else {
                    idx = CC.items.size();
                    CC.items.push_back(D);
                    /* 把新加入的有效项目集加入待扩展队列中 */
                    Q.push(pair<LR0Items, int>(D, idx));
                }
                /* 从原状态到转移状态加一条边,边上的值为转移符号 */
                CC.g[sidx].push_back(pair<char, int>(grammar.T[i], idx));
            }
        }
        /* 遍历每个非终结符 */
        for (int i = 0; i  < grammar.N.size(); i++) {
            LR0Items D;
            go(S, grammar.N[i], D);
            int idx;
            if (D.items.size() > 0) {
                /* 查找是否已经在有效项目集族里 */
                idx = isInCanonicalCollection(D); 
                if (idx != 0) {
                    idx = idx - 1;
                } else {
                    idx = CC.items.size();
                    CC.items.push_back(D);
                    /* 把新加入的有效项目集加入待扩展队列中 */
                    Q.push(pair<LR0Items, int>(D, idx));
                }
                /* 从原状态到转移状态加一条边,边上的值为转移符号 */
                CC.g[sidx].push_back(pair<char, int>(grammar.N[i], idx));
            }
        }
    /* 当前状态扩展完毕,移除队列*/
    Q.pop();
    }

    printf("CC size: %d\n", CC.items.size());
    for (int i = 0; i < CC.items.size(); i++) {
        printf("LR0Items %d:\n", i);
        printLR0Items(CC.items[i]);
        for (int j = 0; j < CC.g[i].size(); j++) {
            pair<char, int> p= CC.g[i][j];
            printf("to %d using %c\n", p.second, p.first);
        }
    }
}
/* 生成SLR1分析表 */
void productSLR1AnalysisTabel()
{
    for (int i = 0; i < CC.items.size(); i++) {
        LR0Items &LIt= CC.items[i];
        /* 构建action表 */
        for (auto it = LIt.items.begin(); it != LIt.items.end(); it++) {
            LR0Item &L = *it;
            /* 非规约项目 */
            if (L.location < L.p.rigths.size()) {
                char a = L.p.rigths[L.location];
                int j = isInT(a);
                /* a是终结符 */
                if (j > 0) {
                    j = j - 1;
                    /* 找到对应a的出边,得到其转移到的状态 */
                    for (int k = 0; k < CC.g[i].size(); k++) {
                        pair<char, int> p = CC.g[i][k];
                        if (p.first == a) {
                            action[i][j].first = 1; // 1->S
                            action[i][j].second = p.second;  //转移状态
                            break;
                        }
                    }
                }
            } else { // 规约项目
                /* 接受项目 */
                if (L.p.left == grammar.prods[0].left) {
                    action[i][grammar.T.size() - 1].first = 3;
                } else {
                    char A = L.p.left;
                    for (auto a = follow[A].begin(); a != follow[A].end(); a++) {
                        int j = isInT(*a);
                        /* 终结符 */
                        if (j > 0) {
                            j = j - 1;
                            /* 找到产生式对应的序号 */
                            for (int k = 0; k < grammar.prods.size(); k++) {
                                if (L.p == grammar.prods[k]) {
                                    action[i][j].first = 2;
                                    action[i][j].second = k;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        /* 构建goto表 */
        for (int k = 0; k < CC.g[i].size(); k++) {
            pair<char, int> p = CC.g[i][k];
            char A = p.first;
            int j = isInN(A);
            /* 终结符 */
            if (j > 0) {
                j = j - 1;
                goton[i][j] = p.second; //转移状态
            }
        }
    }
    /* 打印SLR1分析表 */
    for (int i = 0; i < grammar.T.size() / 2; i++)
        printf("\t");
    printf("action");
    for (int i = 0; i < grammar.N.size() / 2 + grammar.T.size() / 2 + 1; i++)
        printf("\t");
    printf("goto\n");
    printf("\t");
    for (int i = 0; i  < grammar.T.size(); i++) {
        printf("%c\t", grammar.T[i]);
    }
    printf("|\t");
    for (int i = 1; i  < grammar.N.size(); i++) {
        printf("%c\t", grammar.N[i]);
    }
    printf("\n");
    for (int i = 0; i < CC.items.size(); i++) {
        printf("%d\t", i);
        for (int j = 0; j < grammar.T.size(); j++) {
            if (action[i][j].first == 1) {
                printf("%c%d\t", 'S', action[i][j].second);
            } else if (action[i][j].first == 2) {
                printf("%c%d\t", 'R', action[i][j].second);
            } else if (action[i][j].first == 3) {
                printf("ACC\t");
            } else {
                printf("\t");
            }
        }
        printf("|\t");
        for (int j = 1; j < grammar.N.size(); j++) {
            if (goton[i][j]) {
                printf("%d\t", goton[i][j]);
            } else {
                printf("\t");
            }
            
        }
        printf("\n");
    }
}


void initGrammar()
{
    printf("Please enter the num of production:\n");
    cin >> grammar.num;
    string s;
    printf("Please enter the production:\n");
    for (int i = 0; i < grammar.num; i++) {
        cin >> s;
        Production tmp;
        tmp.left = s[0];
        for (int j = 3; j < s.size(); j++) {
            tmp.rigths.push_back(s[j]);
        }
        grammar.prods.push_back(tmp);
    }
    printf("Please enter the non-terminators(end with #):\n");
    char ch;
    cin >> ch;
    while (ch != '#') {
        grammar.N.push_back(ch);
        cin >> ch;
    }
    printf("Please enter the terminators(end with #):\n");
    cin >> ch;
    while (ch != '#') {
        grammar.T.push_back(ch);
        cin >> ch;
    }
    /* 把$当作终结符 */
    grammar.T.push_back('$');
    /* 求FIRST集和FOLLOW集 */
    getFirstSet();
    getFollowSet();

    /* 构建DFA和SLR1预测分析表 */
    DFA();
    productSLR1AnalysisTabel();
    
    /* 读入待分析串并初始化分析栈 */
    printf("Please enter the String to be analyzed:\n");
    cin >> str;
    str += '$';
    ST.push(pair<int, char>(0, '-'));
}
/* 分析程序 */
void process()
{
    int ip = 0;
    printf("The ans:\n");
    do {
        int s = ST.top().first;
        char a = str[ip];
        int j = isInT(a) - 1;
        /* 移进 */
        if (action[s][j].first == 1) {
            ST.push(pair<int, char>(action[s][j].second, a));
            ip = ip + 1;
        } else if (action[s][j].first == 2) { // 规约
            Production &P = grammar.prods[action[s][j].second];
            /* 弹出并输出产生式 */
            printf("%c->", P.left);
            for (int i = 0; i < P.rigths.size(); i++) {
                ST.pop();
                printf("%c", P.rigths[i]);
            }
            printf("\n");
            s = ST.top().first;
            char A = P.left;
            j = isInN(A) - 1;
            ST.push(pair<int, char>(goton[s][j], A));
        } else if (action[s][j].first == 3) {   //接受
            printf("ACC\n");
            return;
        } else {
            printf("error\n");
        }
    } while(1);
}
int main()
{
    initGrammar();
    process();
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值