基于DFA的词法分析(二):构造DFA

字符串预处理(加上&符号分隔)
中缀转后缀(结果仍然是string)
后缀转NFA:

定义一个存NFA的栈
定义一个NFA Ans用于保存最后的答案,下面提到的状态状态数等无特殊说明均指Ans的成员
一个循环:每次读取后缀表达式的一个字符,读完为止
然后根据读到的字符串的不同,可以分为以下几种情况处理:
对操作数的定义为:从正则表达式读取到的非操作符的字符,存在一个set(All_Char)内

  • –操作数:
    新建一个NFA(新建两个节点即状态(状态总数+2),然后NFA的头尾分别指向它们)
    修改关系:让n的头部指向的节点的出弧上的值为读到的字符,转换到的终点为尾指针指向状态的编号
    n进栈
  • –‘*’:
    新建一个NFA,N2(新建两个节点即状态(状态总数+2),然后NFA的头尾分别指向它们)
    出栈一个NFA称为N1,n1原有的结构保持不变
    连接以下内容:
    N2的头连接N1的头,N1的尾连接N2的尾
    N2的头连接N2的尾,N1的尾连接N1的头
    以上连接均是由空字符连接,(可以通过E_closure完成)
    n2进栈
  • –‘|’:
    出栈两个元素a,b。
    新建一个NFA,N(新建两个节点即状态(状态总数+2),然后NFA的头尾分别指向它们)
    做以下连接:
    N的头连接到a和b的头,a和b的尾连接到N的尾(a,b并联)
    以上连接均是由空字符连接,(可以通过E_closure完成)
    N进栈
  • –‘&’:
    出栈两个元素a,b。
    a的尾通过空字符连接到b的头(a,b串联)
    然后将a头b尾作为新NFA入栈即可

做完以上操作,栈大小就变为1,取栈顶的头尾赋给答案Ans再将其返回即可(不能直接返回栈顶因为其不含状态数等信息)

#pragma once

/*新建一个NFA(即从NFA状态数组中取出两个状态)*/
NFA creatNFA(int sum)
{
	NFA New_N ;

	New_N.head = &NFA_States[sum];
	New_N.tail = &NFA_States[sum + 1];

	return New_N;
}

/*在字符串s第n位后面插入字符ch*/
void insert_behind_n(string& s, int n, char ch)
{

	s += '#';

	for (int i = s.size() - 1; i > n; i--)
		s[i] = s[i - 1];//n后面的都向后挪一位

	s[n] = ch;
}

/*对字符串s进行预处理,在第一位是操作数、‘*’或‘)’且第二位是操作数或‘(’之间加入连接符‘&’*/
void pre_process(string& s)
{

	int i = 0, length = s.size();

	while (i < length)
	{
		int in_all_1 = 0, in_all_2 = 0;
		set<char>::iterator it;
		for (it = All_Char.begin(); it != All_Char.end(); it++) {
			if (s[i] == *it)
				in_all_1 = 1;
			if (s[i + 1] == *it)
				in_all_2 = 1;
		}

		//if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] == '*') || (s[i] == ')'))
		if (in_all_1 || (s[i] == '*') || (s[i] == ')'))
			if (in_all_2 || s[i + 1] == '(')
			{
				insert_behind_n(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)
{

	pre_process(s);			/*对字符串进行预处理*/

	string str;				/*要输出的后缀字符串*/
	stack<char> oper;		/*运算符栈*/



	for (unsigned int i = 0; i < s.size(); i++)
	{
		int in_all = 0;
		set<char>::iterator it;
		for (it = All_Char.begin(); it != All_Char.end(); it++)
			if (s[i] == *it)
				in_all = 1;



		if (in_all)	/*如果是操作数直接输出*/
		{
			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 str_To_Nfa(string s)
{
	s = infixToSuffix(s);		/*将中缀表达式转换为后缀表达式*/

	stack<NFA> NfaStack;		/*定义一个NFA栈*/
	NFA Ans;

	for (unsigned int i = 0; i < s.size(); i++)		/*读取后缀表达式,每次读一个字符*/
	{
		//if(i==83)	cout << "测试信息" << i << endl;

		int in_all = 0; 
		set<char>::iterator it;
		for (it = All_Char.begin(); it != All_Char.end(); it++)
			if (s[i] == *it)
				in_all = 1;
	
		if (in_all)		/*遇到操作数*/
		{

			NFA n = creatNFA(Ans.N_StateNum);		/*新建一个NFA*/
			Ans.N_StateNum += 2;					/*NFA状态总数加2*/

			//add(n.head, n.tail, s[i]);			/*NFA的头指向尾,弧上的值为s[i]*/
			n.head->get_value = s[i]; 
			n.head->Trans_to = n.tail->state_id;
			
	/*		
			n.head->get_value = s[i];
			n.head->Trans_to = n.tail->state_id;*/


			NfaStack.push(n);					/*将该NFA入栈*/
		}

		else if (s[i] == '*')		/*遇到闭包运算符*/
		{

			NFA n2 = creatNFA(Ans.N_StateNum );		/*新建一个NFA*/
			Ans.N_StateNum += 2;					/*NFA状态总数加2*/

			NFA n1 = 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的尾*/

			n1.tail->E_closure_to.insert(n2.head->state_id);				/*n2的尾通过ε指向n1的头*/
			n1.tail->E_closure_to.insert(n2.tail->state_id);				/*n2的尾通过ε指向n1的尾*/
			n2.head->E_closure_to.insert(n1.head->state_id);				/*n1的头通过ε指向n2的头*/
			n2.head->E_closure_to.insert(n2.tail->state_id);				/*n1的头通过ε指向n1的尾*/

			NfaStack.push(n2);					/*最后将新生成的NFA入栈*/
		}

		else if (s[i] == '|')		/*遇到或运算符*/
		{

			NFA n1, n2;							/*从栈中弹出两个NFA,栈顶为n2,次栈顶为n1*/
			n2 = NfaStack.top();
			NfaStack.pop();

			n1 = NfaStack.top();
			NfaStack.pop();

			NFA n = creatNFA(Ans.N_StateNum );		/*新建一个NFA*/
			Ans.N_StateNum += 2;					/*NFA状态总数加2*/

			n.head->E_closure_to.insert(n1.head->state_id);				/*n的头通过ε指向n1的头*/
			n.head->E_closure_to.insert(n2.head->state_id);				/*n的头通过ε指向n2的头*/
			n1.tail->E_closure_to.insert(n.tail->state_id);				/*n1的尾通过ε指向n的尾*/
			n2.tail->E_closure_to.insert(n.tail->state_id);				/*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的尾*/
			n1.tail->E_closure_to.insert(n2.head->state_id);
			/*set<int> t= n1.tail->E_closure;
			t.insert(n2.head->ID);
			n1.tail.E_closure = t;*/


			n.head = n1.head;					/*n的头为n1的头*/
			n.tail = n2.tail;					/*n的尾为n2的尾*/

			NfaStack.push(n);					/*最后将新生成的NFA入栈*/
		}
	}

	Ans.head = NfaStack.top().head;
	Ans.tail = NfaStack.top().tail;
	return Ans;		/*最后的栈顶元素即为生成好的NFA*/
}

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

	cout << "***************     NFA     ***************" << endl << endl;
	cout << "NFA总共有" << n.N_StateNum << "个状态," << endl;
	cout << "初态为" << n.head->state_id << ",终态为" << n.tail->state_id << "。" << endl << endl << "转移函数为:" << endl;

	for (int i = 0; i < n.N_StateNum; i++)		/*遍历NFA状态数组*/
	{

		if (NFA_States[i].get_value != '#')			/*如果弧上的值不是初始时的‘#’则输出*/
		{
			cout << NFA_States[i].state_id << "-->'" << NFA_States[i].get_value << "'-->" << NFA_States[i].Trans_to << '\t';
		}

		set<int>::iterator it;					/*输出该状态经过ε到达的状态*/
		for (it = NFA_States[i].E_closure_to.begin(); it != NFA_States[i].E_closure_to.end(); it++)
		{
			cout << NFA_States[i].state_id << "-->'" << ' ' << "'-->" << *it << '\t';
		}

		cout << endl;
	}
}
  • 定义一个DFA Ans用于保存最后的答案,接受参数NFA n作为读入数据
    Ans的初态为0
    初态0的E_closure就等于n的E_closure
    判断初态是否为终态
    dfa数量加一

  • 定义一个存DFA状态(int类型)的栈:把dfa的初态存入栈,只要栈不为空,就一直循环:
    栈顶元素出栈
    遍历有穷字母表计算每个字母的ε-cloure(move(ch))
    如果求出来的状态集不为空且与之前求出来的状态集不同,则增加一个新DFA状态
    将新求出来的状态集加入到状态集合中
    该状态弧的输入即为当前终结符
    弧转移到的状态为最后一个DFA状态
    该状态弧的数目加一,更新转移矩阵
    判断是否为终态
    将新的状态号加入栈中
    DFA状态总数加一
    求出来的状态集在之前求出的某个状态集相同,不增加状态,只增加该状态的弧
    遍历之前求出来的状态集合,找到与该集合相同的DFA状态
    该状态弧的输入即为当前终结符
    该弧转移到的状态即为i
    该状态弧的数目加一,更新转移矩阵,

  • 遍历Ans的所有状态 ,如果该状态是NFA的终态,则将该状态号加入到Ans的终态集中
    转换结束。

  • 状态转移矩阵的含义:
    状态1通过接收字母b到达状态二,表示为:
    Ans.trans[1][(int)b-(int)*All_Char.begin()] == 2;
    重点是trans的第二维的意义,由于其是int类型所以只能用ascii码来表示,
    故用(int)将char类型强制类型转换成对应的ascii码,
    但是由于有穷字母表一般不能包含所有ascii码表,所以会造成一定的空间的浪费(最小的ascii码前面的所有空间都被浪费)
    所以我们实际上采用的是某个字符对应有穷字母表内ascii码最小字符的相对位置来判断的
    所以字符b在转移矩阵中的位置应该是(int)b-(int)*All_Char.begin()

#pragma once



/*求一个状态集的ε-cloure*/
set<int> epcloure(set<int> s, NFA  &n)
{

	stack<int> epStack;		/*(此处栈和队列均可)*/

	set<int>::iterator it;
	for (it = s.begin(); it != s.end(); it++)
		epStack.push(*it);			/*将该状态集中的每一个元素都压入栈中*/


	while (!epStack.empty())			/*只要栈不为空*/
	{
		int temp = epStack.top();		/*从栈中弹出一个元素*/
		epStack.pop();

		set<int>::iterator iter;
		for (iter = NFA_States[temp].E_closure_to.begin(); iter != NFA_States[temp].E_closure_to.end(); iter++)
		{
			if (!s.count(*iter))				/*遍历它通过ε能转换到的状态集*/
			{								/*如果当前元素没有在集合中出现*/
				s.insert(*iter);			/*则把它加入集合中*/
				epStack.push(*iter);		/*同时压入栈中*/
			}
		}
	}

	return s;		/*最后的s即为ε-cloure*/
}

/*求一个状态集s的ε-cloure(move(ch))*/
set<int> moveEpCloure(set<int> s, char ch, NFA &n)
{

	set<int> temp;

	set<int>::iterator it;
	for (it = s.begin(); it != s.end(); it++)		/*遍历当前集合s中的每个元素*/
	{
		if (NFA_States[*it].get_value == ch)				/*如果对应转换弧上的值为ch*/
		{
			temp.insert(NFA_States[*it].Trans_to);		/*则把该弧通过ch转换到的状态加入到集合temp中*/
		}
	}

	temp = epcloure(temp ,n);			/*最后求temp的ε闭包*/
	return temp;
}

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

	return false;		/*如果不包含,则不是终态,返回false*/
}

/*nfa转dfa主函数*/
DFA Nfa_To_Dfa(NFA n)		/*参数为nfa和后缀表达式*/
{


	cout << "***************     DFA     ***************" << endl << endl;

	int i;
	DFA Ans;//转化成的DFA(结果)
	set<set<int>> states;		/*定义一个存储整数集合的集合,用于判断求出一个状态集s的ε-cloure(move(ch))后是否出现新状态*/
	set<int> tempSet;

	Ans.Letter_List = All_Char;/*把操作数加入到dfa的有穷字母表中*/
	Ans.Beg_State = 0;		/*dfa的初态为0*/

		
	tempSet.insert(n.head->state_id);		/*将nfa的初态加入到集合中*/
	Ans.DFA_States[0].E_closure_to = epcloure(tempSet,n);		/*求dfa的初态*/
	Ans.DFA_States[0].isEnd = IsEnd(n, Ans.DFA_States[0].E_closure_to);		/*判断初态是否为终态*/

	Ans.D_StateNum++;			/*dfa数量加一*/

	stack <int> q;
	q.push(Ans.Beg_State);		/*把dfa的初态存入栈中*/

	while (!q.empty())		/*只要栈不为空,就一直循环*/
	{

		int num = q.top();				/*出去栈顶元素*/
		q.pop();

		set<char>::iterator it;
		for (it = Ans.Letter_List.begin(); it != Ans.Letter_List.end(); it++)		/*遍历有穷字母表*/
		{

			set<int> temp = moveEpCloure(Ans.DFA_States[num].E_closure_to, *it ,n);		/*计算每个终结符的ε-cloure(move(ch))*/

			if (!states.count(temp) && !temp.empty())	/*如果求出来的状态集不为空且与之前求出来的状态集不同,则新建一个DFA状态*/
			{

				states.insert(temp);				/*将新求出来的状态集加入到状态集合中*/

				Ans.DFA_States[Ans.D_StateNum].E_closure_to = temp;

				Ans.DFA_States[num].Edges[Ans.DFA_States[num].Edge_Num].get_value = *it;				/*该状态弧的输入即为当前终结符*/
				Ans.DFA_States[num].Edges[Ans.DFA_States[num].Edge_Num].Trans_to = Ans.D_StateNum;		/*弧转移到的状态为最后一个DFA状态*/
				Ans.DFA_States[num].Edge_Num++;												/*该状态弧的数目加一*/

				//d.trans[num][*it - 'a'] = dfaStateNum;		/*更新转移矩阵*/
				Ans.trans[num][*it - (int)*All_Char.begin()] = Ans.D_StateNum;		/*更新转移矩阵*/

				Ans.DFA_States[Ans.D_StateNum].isEnd = IsEnd(n, Ans.DFA_States[Ans.D_StateNum].E_closure_to);	/*判断是否为终态*/

				q.push(Ans.D_StateNum);		/*将新的状态号加入队列中*/

				Ans.D_StateNum++;		/*DFA状态总数加一*/
			}
			else			/*求出来的状态集在之前求出的某个状态集相同*/
			{
				for (i = 0; i < Ans.D_StateNum; i++)		/*遍历之前求出来的状态集合*/
				{
					if (temp == Ans.DFA_States[i].E_closure_to)		/*找到与该集合相同的DFA状态*/
					{

						Ans.DFA_States[num].Edges[Ans.DFA_States[num].Edge_Num].get_value = *it;		/*该状态弧的输入即为当前终结符*/
						Ans.DFA_States[num].Edges[Ans.DFA_States[num].Edge_Num].Trans_to = i;			/*该弧转移到的状态即为i*/
						Ans.DFA_States[num].Edge_Num++;										/*该状态弧的数目加一*/

						//d.trans[num][*it - 'a'] = i;		/*更新转移矩阵*/
						Ans.trans[num][*it - (int)*All_Char.begin()] = i;		/*更新转移矩阵*/

						break;
					}
				}
			}
		}
	}

	/*计算dfa的终态集*/
	for (i = 0; i < Ans.D_StateNum; i++)	/*遍历dfa的所有状态*/
		if (Ans.DFA_States[i].isEnd == true)		/*如果该状态是终态*/
			Ans.End_States.insert(i);		/*则将该状态号加入到dfa的终态集中*/
		
	return Ans;
}

/*打印dfa函数*/
void printDFA(DFA &d)
{

	int i, j;
	cout << "DFA总共有" << d.D_StateNum << "个状态," << "初态为" << d.Beg_State << endl << endl;

	cout << "有穷字母表为{ ";
	set<char>::iterator it;
	for (it = d.Letter_List.begin(); it != d.Letter_List.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << '}' << endl << endl;

	cout << "终态集为{ ";
	set<int>::iterator iter;
	for (iter = d.End_States.begin(); iter != d.End_States.end(); iter++)
	{
		cout << *iter << ' ';
	}
	cout << '}' << endl << endl;

	cout << "转移函数为:" << endl;
	for (i = 0; i < d.D_StateNum; i++)
	{
		for (j = 0; j < d.DFA_States[i].Edge_Num; j++)
		{

			if (d.DFA_States[d.DFA_States[i].Edges[j].Trans_to].isEnd == true)
			{
				cout << d.DFA_States[i].state_id << "-->'" << d.DFA_States[i].Edges[j].get_value;
				cout << "'--><" << d.DFA_States[i].Edges[j].Trans_to << ">\t";
			}
			else
			{
				cout << d.DFA_States[i].state_id << "-->'" << d.DFA_States[i].Edges[j].get_value;
				cout << "'-->" << d.DFA_States[i].Edges[j].Trans_to << '\t';
			}
		}
		cout << endl;
	}

	cout << endl << "转移矩阵为:" << endl << "     ";
	set<char>::iterator t;
	for (t = d.Letter_List.begin(); t != d.Letter_List.end(); t++)
	{
		cout << *t << "   ";
	}
	cout << endl;

	for (i = 0; i < d.D_StateNum; i++)
	{

		if (d.End_States.count(i))
		{
			cout << '<' << i << ">  ";
		}
		else
		{
			cout << ' ' << i << "   ";
		}

		int n = (int)*All_Char.begin();
		int m = (int)*(--All_Char.end());

		for (j = 0; j < m + 2; j++)
			//for (j = 0; j < 26; j++)
		{
			//if (d.terminator.count(j + 'a'))
			if (d.Letter_List.count(j + n))
			{
				if (d.trans[i][j] != -1)
				{
					cout << d.trans[i][j] << "   ";
				}
				else
				{
					cout << "    ";
				}
			}
		}

		cout << endl;
	}
}

DFA最小化:

#pragma once

set<int> s[MAX];					/*划分出来的集合数组*/

struct stateSet			/*划分状态集*/
{
	int index;			/*该状态集所能转换到的状态集标号*/
	set<int> 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 min_DFA(DFA &d)
{

	int i, j;
	cout << endl << "*************     minDFA     **************" << endl << endl;

	DFA minDfa;
	minDfa.Letter_List = d.Letter_List;		/*把dfa的终结符集赋给minDfa*/

	memset(minDfa.trans, -1, sizeof(minDfa.trans));		/*初始化minDfa转移矩阵*/

	/*做第一次划分,即将终态与非终态分开*/
	bool endFlag = true;					/*判断dfa的所有状态是否全为终态的标志*/
	for (i = 0; i < d.D_StateNum; i++)	/*遍历dfa状态数组*/
	{
		if (d.DFA_States[i].isEnd == false)			/*如果该dfa状态不是终态*/
		{

			endFlag = false;						/*标志应为false*/
			minDfa.D_StateNum = 2;						/*第一次划分应该有两个集合*/

			s[1].insert(d.DFA_States[i].state_id);		/*把该状态的状态号加入s[1]集合中*/
		}
		else									/*如果该dfa状态是终态*/
		{
			s[0].insert(d.DFA_States[i].state_id);		/*把该状态的状态号加入s[0]集合中*/
		}
	}

	if (endFlag)					/*如果标志为真,则所有dfa状态都是终态*/
		minDfa.D_StateNum = 1;			/*第一次划分结束应只有一个集合*/


	bool cutFlag = true;		/*上一次是否产生新的划分的标志*/
	while (cutFlag)				/*只要上一次产生新的划分就继续循环*/
	{

		int cutCount = 0;			/*需要产生新的划分的数量*/
		for (i = 0; i < minDfa.D_StateNum; i++)			/*遍历每个划分集合*/
		{

			set<char>::iterator it;
			for (it = d.Letter_List.begin(); it != d.Letter_List.end(); it++)		/*遍历dfa的终结符集*/
			{

				int setNum = 0;				/*当前缓冲区中的状态集个数*/
				stateSet temp[20];			/*划分状态集“缓冲区”*/

				set<int>::iterator iter;
				for (iter = s[i].begin(); iter != s[i].end(); iter++)		/*遍历集合中的每个状态号*/
				{

					bool epFlag = true;			/*判断该集合中是否存在没有该终结符对应的转换弧的状态*/
					for (j = 0; j < d.DFA_States[*iter].Edge_Num; j++)		/*遍历该状态的所有边*/
					{

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

							epFlag = false;			/*则标志为false*/

							/*计算该状态转换到的状态集的标号*/
							int transNum = findSetNum(minDfa.D_StateNum, d.DFA_States[*iter].Edges[j].Trans_to);

							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组划分留在原集合中*/
					{

						set<int>::iterator t;
						for (t = temp[j].s.begin(); t != temp[j].s.end(); t++)
						{

							s[i].erase(*t);						/*在原来的状态集中删除该状态*/
							s[minDfa.D_StateNum].insert(*t);		/*在新的状态集中加入该状态*/
						}

						minDfa.D_StateNum++;		/*最小化DFA状态总数加一*/
					}
				}
			}
		}

		if (cutCount == 0)		/*如果需要划分的次数为0,表示本次不需要进行划分*/
		{
			cutFlag = false;
		}
	}

	/*遍历每个划分好的状态集*/
	for (i = 0; i < minDfa.D_StateNum; i++)
	{

		set<int>::iterator y;
		for (y = s[i].begin(); y != s[i].end(); y++)		/*遍历集合中的每个元素*/
		{

			if (*y == d.Beg_State)			/*如果当前状态为dfa的初态,则该最小化DFA状态也为初态*/
			{
				minDfa.Beg_State = i;
			}

			if (d.End_States.count(*y))		/*如果当前状态是终态,则该最小化DFA状态也为终态*/
			{

				minDfa.DFA_States[i].isEnd = true;
				minDfa.End_States.insert(i);		/*将该最小化DFA状态加入终态集中*/
			}

			for (j = 0; j < d.DFA_States[*y].Edge_Num; j++)		/*遍历该DFA状态的每条弧,为最小化DFA创建弧*/
			{

				/*遍历划分好的状态集合,找出该弧转移到的状态现在属于哪个集合*/
				for (int t = 0; t < minDfa.D_StateNum; t++)
				{
					if (s[t].count(d.DFA_States[*y].Edges[j].Trans_to))
					{

						bool haveEdge = false;		/*判断该弧是否已经创建的标志*/
						for (int l = 0; l < minDfa.DFA_States[i].Edge_Num; l++)	/*遍历已创建的弧*/
						{					/*如果该弧已经存在*/
							if ((minDfa.DFA_States[i].Edges[l].get_value == d.DFA_States[*y].Edges[j].get_value) && (minDfa.DFA_States[i].Edges[l].Trans_to == t))
							{
								haveEdge = true;		/*标志为真*/
							}
						}

						if (!haveEdge)		/*如果该弧不存在,则创建一条新的弧*/
						{

							minDfa.DFA_States[i].Edges[minDfa.DFA_States[i].Edge_Num].get_value = d.DFA_States[*y].Edges[j].get_value;	/*弧的值与DFA的相同*/
							minDfa.DFA_States[i].Edges[minDfa.DFA_States[i].Edge_Num].Trans_to = t;	/*该弧转移到的状态为这个状态集的标号*/

							//minDfa.trans[i][DfaStates[*y].Edges[j].input - 'a'] = t;	/*更新转移矩阵*/
							minDfa.trans[i][d.DFA_States[*y].Edges[j].get_value - (int)*All_Char.begin()] = t;	/*更新转移矩阵*/

							minDfa.DFA_States[i].Edge_Num++;		/*该状态的弧的数目加一*/
						}

						break;
					}
				}
			}
		}
	}

	for (i = 0; i < minDfa.D_StateNum; i++)
		for (j = 0; j < minDfa.DFA_States[i].Edge_Num; j++) {
			if (minDfa.DFA_States[i].state_id == minDfa.Beg_State)
				Beg.insert(minDfa.DFA_States[i].Edges[j].get_value);//构造首字母表
			if (minDfa.End_States.find(minDfa.DFA_States[i].Edges[j].Trans_to) != minDfa.End_States.end())
				End.insert(minDfa.DFA_States[i].Edges[j].get_value);//构造尾字母表
		}
			

	return minDfa;
}

void printMinDFA(DFA d)
{

	int i, j;
	cout << "minDFA总共有" << d.D_StateNum << "个状态," << "初态为" << d.Beg_State << endl << endl;

	cout << "有穷字母表为{ ";
	set<char>::iterator it;
	for (it = d.Letter_List.begin(); it != d.Letter_List.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << '}' << endl << endl;

	cout << "终态集为{ ";
	set<int>::iterator iter;
	for (iter = d.End_States.begin(); iter != d.End_States.end(); iter++)
	{
		cout << *iter << ' ';
	}
	cout << '}' << endl << endl;

	cout << "转移函数为:" << endl;
	for (i = 0; i < d.D_StateNum; i++)
	{
		for (j = 0; j < d.DFA_States[i].Edge_Num; j++)
		{

			if (d.DFA_States[d.DFA_States[i].Edges[j].Trans_to].isEnd == true)
			{
				cout << d.DFA_States[i].state_id << "-->'" << d.DFA_States[i].Edges[j].get_value;
				cout << "'--><" << d.DFA_States[i].Edges[j].Trans_to << ">\t";
			}
			else
			{
				cout << d.DFA_States[i].state_id << "-->'" << d.DFA_States[i].Edges[j].get_value;
				cout << "'-->" << d.DFA_States[i].Edges[j].Trans_to << '\t';
			}
			//if (minDfaStates[i].index == d.startState)
			//	Beg.insert(minDfaStates[i].Edges[j].input);			
			
		}
		cout << endl;
	}

	cout << endl << "转移矩阵为:" << endl << "     ";
	set<char>::iterator t;
	for (t = d.Letter_List.begin(); t != d.Letter_List.end(); t++)
	{
		cout << *t << "   ";
	}
	cout << endl;

	for (i = 0; i < d.D_StateNum; i++)
	{

		if (d.End_States.count(i))
		{
			cout << '<' << i << ">  ";
		}
		else
		{
			cout << ' ' << i << "   ";
		}

		int n = (int)*All_Char.begin();
		int m = (int)*(--All_Char.end());

		for (j = 0; j < m + 2; j++)
			//for (j = 0; j < 26; j++)
		{
			//if (d.terminator.count(j + 'a'))
			if (d.Letter_List.count(j + n))			
				if (d.trans[i][j] != -1)				
					cout << d.trans[i][j] << "   ";				
				else				
					cout << "    ";
		
		}

		cout << endl;
	}
	cout << endl << "*******************************************";
}

得到由正则表达式转换而来的最小DFA之后,我们就可以利用这个DFA来识别我们的源程序,具体已经在前一篇文章中给出。
基于DFA的词法分析(一):程序框架及数据结构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cheney822

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值