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

📄 regexptonfa.cpp

📁 编译原理中的表达失转换为NFA
💻 CPP
📖 第 1 页 / 共 2 页
字号:
}
//获取表达式
void RegularExpToNFA::GetExpression()
{
	char temp[40];
	bool c;
	int length=0;
	cout<<"\n 请你输入一个正则表达式(字母表只包括0,1,e)";
	do
	{
		cout<<"\n 表达式: ";
        cin>>exp;
		length = strlen(exp);
		for (int i=0; i<length; i++)
		{
			if (exp[i]!='0' && exp[i]!='1' && exp[i]!='(' && exp[i]!=')' && exp[i]!='|' && exp[i]!='*' && exp[i]!='e' && exp[i]!='.')
			{
				cout << "\n 输入中包含错误的字符! 请重新输入" << endl;
				c = true;
				break;
			}
			else
				c = false;
		}
	}while(c);
	for(int i=0,j=0;i<length;i++,j++)
	{
		temp[j] = exp[i];
		if (exp[i] == '0'||exp[i] == '1'||exp[i] == ')'||exp[i] == '*')
		{
			if (exp[i+1] == '0'||exp[i+1] == '1'||exp[i+1] == '(')
			{
				temp[j+1] = '.';
				j++;
			}
		}
	}
	temp[j] = '\0';
	strcpy(exp,temp);
	cout<<"\n 你输入的正则表达式为:";
	cout<<exp<<endl;	
}

//定义symbol的优先级
int RegularExpToNFA::Precedence(char symbol)
{
	int priority;
	switch (symbol)
	{
	case '|': priority = 1; break;
	case '.': priority = 2; break;
	case '*': priority = 3; break;
	default:  priority = 0; break;
	}
	return priority;
}

// 将正则式转为后缀表达式
void RegularExpToNFA::ExpToPostFix()
{
	int i = 0, j = 0;
	char ch, cl;
	stack<char> *st = new stack<char>(0);
	strcpy(post, "\0");
	st->clear();
	st->push('#');
	ch = exp[i];
	//转化过程
	while (ch != '\0')
	{
		if (ch == '(')
		{
			st->push(ch);
			ch = exp[++i];
		}
		else if (ch == ')')
		{
			while ( st->GetTop()!= '(')
			{
				post[j++] = st->pop();
			}
            st->pop();
			ch = exp[++i];
		}
		else if ((ch == '|') || (ch == '*') || (ch == '.'))
		{
	    	cl = st->GetTop();
		   	while (Precedence(cl) >= Precedence(ch))
			{
		    	post[j++] = cl;
		    	st->pop();
		    	cl = st->GetTop();
			}
			st->push(ch);
			ch = exp[++i];
		}
		else if ((ch == '0') || (ch == '1') || (ch == 'e'))
		{
			post[j++] = ch;
			ch = exp[++i];
		}
	}
	ch = st->pop(); 
	while ((ch == '|') || (ch == '*') || (ch == '.'))
	{
		post[j++] = ch;
     	ch = st->pop();
	}
	post[j] = '\0';
	st->clear();
	cout<<"\n 正则式转为后缀表达式式为:";
	cout<< post <<endl;
}/*
void RegularExpToNFA::Compute()
{
	int i = 0;
	st = new stack<char>(0);
	st->clear();
	st->push('#');
	ss = new stack<int>(0);
	ss->clear();
	while (post[i]!='\0')
	{
		switch (post[i])
		{
 		case '1':	case '0':	case 'e':
			st->push(post[i]);
			break;
 		case '|':	case '*':	case '.':
			FormNFA(post[i]);
			break;
		default:
			break;
		}
	}
}

//NFA子结构的生成
void RegularExpToNFA::FormNFA(char op)
{
	int i=0,j=0,count = 0 ;
	char left,right;
	bool flag = true;
	if (st->IsEmpty())
	{
		cout<<"\n 栈已空!";
		flag = false;
	}
	right = st->pop();
	if (st->IsEmpty())
	{
	    cout<<"\n 栈已空!";
		flag = false;
	}
	left = st->pop();
	if (flag)
	{
		switch (op)
		{
		case '*':
			break;
		case '|':
			break;	
		case '.': 
			break;
		default: 	
			break;
		}
	}
	else
		st->clear();
}*/
// 用Thompson法构造NFA
int RegularExpToNFA::ThompsonMethod()
{
	int i=0, len = strlen(post);
	char ch;
	int s1, s2;
	stack<char> *ls = new stack<char>(0);
	stack<int> *state = new stack<int>(0);
	ls->clear();
	ls->push('#');
	state->clear();
	if (len < 0)
	{
		cerr << "No Valid Regular Expression Found!" << endl;
		getch();
		exit(1);
	}
	for (i=len-1; i>=0; i--)
	{
		ls->push(post[i]);
	}
	table->SetValue(0, 0);
	i = 1;
	ch = ls->pop();
    while (1)
	{
		if ((ch == '0') || (ch == '1') || (ch == 'e'))
		{
			table->InsertVertex(i);
			table->InsertVertex(i+1);
			table->InsertEdgeByValue(i, i+1, ch);
			s1 = i;
			s2 = i+1;
			state->push(s1);
			state->push(s2);
			i += 2;
		}
		else if (ch == '.')
		{
			s2 = state->pop();
			int temp1 = state->pop();
			int temp2 = state->pop();
			s1 = state->pop();
			table->InsertEdgeByValue(temp2, temp1, 'e');
			state->push(s1);
			state->push(s2);
		}
		else if (ch == '|')
		{
			s2 = state->pop();
			int temp1 = state->pop();
			int temp2 = state->pop();
			s1 = state->pop();
			table->InsertVertex(i);
			table->InsertVertex(i+1);
			table->InsertEdgeByValue(i, s1, 'e');
			table->InsertEdgeByValue(i, temp1, 'e');
			table->InsertEdgeByValue(temp2, i+1, 'e');
			table->InsertEdgeByValue(s2, i+1, 'e');
			s1 = i;
			s2 = i+1;
			state->push(s1);
			state->push(s2);
			i += 2;
		}
		else if (ch == '*')
		{
			s2 = state->pop();
			s1 = state->pop();
			table->InsertVertex(i);
			table->InsertVertex(i+1);
			table->InsertEdgeByValue(i, i+1, 'e');
			table->InsertEdgeByValue(s2, s1, 'e');
			table->InsertEdgeByValue(i, s1, 'e');
			table->InsertEdgeByValue(s2, i+1, 'e');
			s1 = i;
			s2 = i+1;
			state->push(s1);
			state->push(s2);
			i += 2;
		}
		ch = ls->pop();
		if (ch == '#')
		{
			break;
		}
	}
	s2 = state->pop();
	s1 = state->pop();
	table->InsertEdgeByValue(0, s1, 'e');
	ls->clear();
	state->clear();
	return s2;
}

// 用邻接表形式输出构造的NFA
void RegularExpToNFA::OutputNFA(int end)
{	
	int len = strlen(post);
	cout<<"\n ━━━━━━━━━━━━━━━━━━━━";
	cout<<"\n 下面是从正则表达式转化成的 NFA :";
	cout<<"\n 1. 字  母  表:"<<"0, 1";
	cout<<"\n 2. 状  态  集:";
	for (int i=0;i<table->GetVertexNumber();i++)
	{
		cout<<i<<",";
	}
	cout<<'\b';
	cout<<"\n 3. 初始  状态:0";
	cout<<"\n 4. 接收状态集:";
	cout<<end;
	for(i=0;i<0;i++)
	{
		cout<<endState[i]<<",";
	}
	cout<<"\n 5. 转化函数表:\n";
	cout<<"\n ━━━┯━━━━━━━━━━━━━━━━";
	cout<<"\n       │   输入字母 ";
	cout<<"\n  状态 ┝━━━━┯━━━━━┯━━━━━";
	cout<<"\n       │  0     │   1      │   e";
	cout<<"\n ━━━┿━━━━┿━━━━━┿━━━━━";
	cout<<endl;	
	table->Output();
	cout<<endl;
	table->Clear();
}
//整个处理总流程
void RegularExpToNFA::Run()
{
	//输入表达式
	GetExpression();
	//将正则式转为后缀表达式
	ExpToPostFix();
	// 用Thompson法构造NFA并返回接收状态
	int end = ThompsonMethod();
	// 用邻接表形式输出NFA
	OutputNFA(end);
}

///////////////////////////
//Main Function
void main()
{
	RegularExpToNFA con;
	con.Run();
	cout<<"\n 按任意键退出....";
	cout<<endl;
	getch();
}


/////////////////////////////////////////
/*/下面是测试的正则表达式(0或1)和结果

(1)1(01|1) 输出的结果如下:

 请你输入一个正则表达式(字母表只包括0,1,e)
 表达式: 1(01|1)

 你输入的正则表达式为:1.(0.1|1)

 正则式转为后缀表达式式为:101.1|.

 ━━━━━━━━━━━━━━━━━━━━
 下面是从正则表达式转化成的 NFA :
 1. 字  母  表:0, 1
 2. 状  态  集:0,1,2,3,4,5,6,7,8,9,10,
 3. 初始  状态:0
 4. 接收状态集:10
 5. 转化函数表:

 ━━━┯━━━━━━━━━━━━━━━━
       │   输入字母
  状态 ┝━━━━┯━━━━━┯━━━━━
       │  0     │   1      │   e
 ━━━┿━━━━┿━━━━━┿━━━━━
  0    │  --    │   --     │   1
  1    │  --    │   2      │   --
  2    │  --    │   --     │   9
  3    │  4     │   --     │   --
  4    │  --    │   --     │   5
  5    │  --    │   6      │   --
  6    │  --    │   --     │   10
  7    │  --    │   8      │   --
  8    │  --    │   --     │   10
  9    │  --    │   --     │   3 7
  10   │  end   │   --     │   --


 按任意键退出....


(2)1(01|1)* 输出的结果如下:

 
 请你输入一个正则表达式(字母表只包括0,1,e)
 表达式: 1(01|1)*

 你输入的正则表达式为:1.(0.1|1)*

 正则式转为后缀表达式式为:101.1|*.

 ━━━━━━━━━━━━━━━━━━━━
 下面是从正则表达式转化成的 NFA :
 1. 字  母  表:0, 1
 2. 状  态  集:0,1,2,3,4,5,6,7,8,9,10,11,12,
 3. 初始  状态:0
 4. 接收状态集:12
 5. 转化函数表:

 ━━━┯━━━━━━━━━━━━━━━━
       │   输入字母
  状态 ┝━━━━┯━━━━━┯━━━━━
       │  0     │   1      │   e
 ━━━┿━━━━┿━━━━━┿━━━━━
  0    │  --    │   --     │   1
  1    │  --    │   2      │   --
  2    │  --    │   --     │   11
  3    │  4     │   --     │   --
  4    │  --    │   --     │   5
  5    │  --    │   6      │   --
  6    │  --    │   --     │   10
  7    │  --    │   8      │   --
  8    │  --    │   --     │   10
  9    │  --    │   --     │   3 7
  10   │  --    │   --     │   9 12
  11   │  --    │   --     │   12 9
  12   │  end   │   --     │   --


 按任意键退出....



(3) 1(01|1)*|1*00  输出的结果如下:


 请你输入一个正则表达式(字母表只包括0,1,e)
 表达式: 1(01|1)*|1*00

 你输入的正则表达式为:1.(0.1|1)*|1*.0.0

 正则式转为后缀表达式式为:101.1|*.1*0.0.|

 ━━━━━━━━━━━━━━━━━━━━
 下面是从正则表达式转化成的 NFA :
 1. 字  母  表:0, 1
 2. 状  态  集:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,
 3. 初始  状态:0
 4. 接收状态集:22
 5. 转化函数表:

 ━━━┯━━━━━━━━━━━━━━━━
       │   输入字母
  状态 ┝━━━━┯━━━━━┯━━━━━
       │  0     │   1      │   e
 ━━━┿━━━━┿━━━━━┿━━━━━
  0    │  --    │   --     │   21
  1    │  --    │   2      │   --
  2    │  --    │   --     │   11
  3    │  4     │   --     │   --
  4    │  --    │   --     │   5
  5    │  --    │   6      │   --
  6    │  --    │   --     │   10
  7    │  --    │   8      │   --
  8    │  --    │   --     │   10
  9    │  --    │   --     │   3 7
  10   │  --    │   --     │   9 12
  11   │  --    │   --     │   12 9
  12   │  --    │   --     │   22
  13   │  --    │   14     │   --
  14   │  --    │   --     │   13 16
  15   │  --    │   --     │   16 13
  16   │  --    │   --     │   17
  17   │  18    │   --     │   --
  18   │  --    │   --     │   19
  19   │  20    │   --     │   --
  20   │  --    │   --     │   22
  21   │  --    │   --     │   1 15
  22   │  end   │   --     │   --


 按任意键退出....

/////////////////////////////////////////*/ 

⌨️ 快捷键说明

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