正规式转NFA
1、正规式和NFA
定义(参考编译原理教材)
2、转换思想
1.使用一个首尾栈来存储表达式首尾节点组的集。
2.使用一个边栈来存储边的集。
3.利用后缀表达式,利用首尾栈对表达式做运算并将生成的边加入边栈。
3、转换步骤
接下来以正规表达式a*b(b|a)*构造与之等价的ε-NFA来演示
(1)转换规则
<1>基础
<2> 归纳
(2)转成后缀表达式
a*b.ba|*.
(3)运算
(1)遇到“a”
(2)遇到“*”
(3)遇到“b”
(4)遇到“.”
(5)遇到“b”
(6)遇到“a”
(7)遇到“|”
(8)遇到“*”
(9)遇到“.”
(10)程序执行完毕,首尾中的唯一首尾组即NFA的开始状态和终结状态;边栈中的边集合即NFA。
结果展示:
C# 代码:
链接:https://pan.baidu.com/s/1kdKZoOD4OyWs-8Wuxn6uJw
提取码:p57w
//Forms1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace practice__2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void dFAToolStripMenuItem_Click(object sender, EventArgs e)
{
NFA_DFA_MFA f = new NFA_DFA_MFA();
f.ShowDialog();
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
//Forms2.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Collections;
namespace practice__2
{
public partial class NFA_DFA_MFA : Form
{
public NFA_DFA_MFA()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void label1_Click(object sender, EventArgs e)
{
}
private void groupBox1_Enter(object sender, EventArgs e)
{
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
Regex r = new Regex("[\\(|\\)|\\*|\\||[a-z]|\\d#949]+");
string a= textBox1.Text;
bool t = r.IsMatch(a);
if (t == false)
{
MessageBox.Show("表达式错误", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
MessageBox.Show("正确", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private String addConnect(String s)
{ // 为表达式加上连接符
Stack stack = new Stack();
char[] chr = s.ToCharArray();
int point = 0;
Console.WriteLine(s);
Console.WriteLine("ZZ");
Console.WriteLine(chr.Length);
//a*b(b|a)*
//a*.b.(b|a)*
//a*b.ba|*.
while (point != chr.Length)
{
Regex r = new Regex("[\\(|\\)|\\*|\\||[a-z]]+");
Regex r1 = new Regex("[a-z]");
// 对*[a-z]的情况在中间加上连接符后入栈
if (chr[point] == '*' && point != chr.Length - 1
&& r1.IsMatch(chr[point + 1] + ""))
{
stack.push(chr[point]);
stack.push('.');
}
else if (chr[point] == '(' && point != 0 && chr[point - 1] != '|')
{
// 对)(、*(、[a-z](的情况在中间加上连接符后入栈
stack.push('.');
stack.push('(');
}
else if (point != 0 && r1.IsMatch(chr[point] + "")
&& (r1.IsMatch(chr[point - 1] + "") || chr[point - 1] == ')'))
{
stack.push('.');
stack.push(chr[point]);
}
else
{
stack.push(chr[point]);
Console.WriteLine("ttt");
}
point++;
}
Console.WriteLine(stack.getString());
return stack.getString();
}
private String change(String s)
{ // 生成后缀表达式
char[] chr = s.ToCharArray();
int point = 0;
Stack stack = new Stack();
String str = "";
while (point != chr.Length)
{
switch (chr[point])
{
case '(':
stack.push(chr[point]);
point++;
break;
case ')':
while (stack.peek() != '(' && !stack.isEmpty())
{
str += stack.pop();
}
if (!stack.isEmpty() && stack.peek() == '(')
stack.pop();
point++;
break;
case '*':
str += chr[point];
point++;
break;
case '|':
case '.':
while (!stack.isEmpty() && stack.peek() != '('
&& stack.peek() != ')'
&& !compare(chr[point], stack.peek()))
{
str += stack.pop();
}
stack.push(chr[point]);
point++;
break;
default:
str += chr[point];
point++;
break;
}
}
while (!stack.isEmpty())
{
if (stack.peek() == ')' || stack.peek() == ')')
return "";
else
str += stack.pop();
}
Console.WriteLine(str);
return str;
}
private bool compare(char a, char b)
{ //比较操作符的优先级
if (a == b)
return false;
if (a == '*')
return true;
if (a == '.')
{
if (b == '*')
return false;
else
return true;
}
return false;
}
private bool check(String str)
{ // 对后缀表达式做消除运算
Stack stack = new Stack();
Stack result = new Stack();
char[] chr = str.ToCharArray();
Regex r1 = new Regex("[a-z]");
for (int i = chr.Length - 1; i >= 0; i--)
stack.push(chr[i]);
while (!stack.isEmpty())
{
switch (stack.peek())
{
case '*':
if (!r1.IsMatch(result.peek() + ""))
return false;
stack.pop();
break;
case '.':
case '|':
if (result.length() < 2 || !r1.IsMatch(result.pop() + "")
|| !r1.IsMatch(result.peek() + ""))
return false;
stack.pop();
break;
default:
result.push(stack.peek());
stack.pop();
break;
}
}
return result.length() == 1 && r1.IsMatch(result.peek() + "");
}
int x = 1;
Stack<int[]> list = new Stack<int[]>();
Stack<string[]> res = new Stack<string[]>();
Stack<string[]> res_T = new Stack<string[]>();
private int getFacoter()
{
int s = x;
x++;
return s;
}
public int[] getElement(Stack<int[]> stack, int position)
{
int[] result = stack.Pop();
if (stack.Count == position)
{
return result;
}
else
{
int[] element = getElement(stack, position);
stack.Push(element);
return element;
}
}
public int[] getfactor()
{
return getElement(list, 0);
}
public Stack<String[]> getlist()
{
return res;
}
public void ToNFA(String str)
{
// TODO Auto-generated constructor stub
char[] chr = str.ToCharArray();
for(int i=0;i<chr.Length;i++)
{
char ch = chr[i];
int[] a = new int[2];
int[] b = new int[2];
int[] c = new int[2];
switch (ch)
{
case '.':
String[] st = new String[3];
// 取出list中上面的两个关系
a = list.Peek();
Console.WriteLine(a);
list.Pop();
b = list.Peek();
Console.WriteLine(b);
list.Pop();
// 创建新的关系
c = new int[2];
c[0] = b[0];
c[1] = a[1];
// 将上面的两个关系替换成新的关系
list.Push(c);
// 添加新的NFA项
st[0] = b[1] + "";
st[1] = "#";
st[2] = a[0] + "";
res.Push(st);
break;
case '|':
c[0] = getFacoter();
c[1] = getFacoter();
a = list.Peek();
list.Pop();
b = list.Peek();
list.Pop();
list.Push(c);
String[] st1 = new String[3];
String[] st2 = new String[3];
String[] st3 = new String[3];
String[] st4 = new String[3];
st1[0] = c[0] + "";
st1[1] = "#";
st1[2] = a[0] + "";
res.Push(st1);
st2[0] = c[0] + "";
st2[1] = "#";
st2[2] = b[0] + "";
res.Push(st2);
st3[0] = a[1] + "";
st3[1] = "#";
st3[2] = c[1] + "";
res.Push(st3);
st4[0] = b[1] + "";
st4[1] = "#";
st4[2] = c[1] + "";
res.Push(st4);
break;
case '*':
String[] st5 = new String[3];
String[] st6 = new String[3];
String[] st7 = new String[3];
String[] st8 = new String[3];
c[0] = getFacoter();
c[1] = getFacoter();
a = list.Peek();
list.Pop();
list.Push(c);
st5[0] = c[0] + "";
st5[1] = "#";
st5[2] = c[1] + "";
res.Push(st5);
st6[0] = c[0] + "";
st6[1] = "#";
st6[2] = a[0] + "";
res.Push(st6);
st7[0] = a[1] + "";
st7[1] = "#";
st7[2] = a[0] + "";
res.Push(st7);
st8[0] = a[1] + "";
st8[1] = "#";
st8[2] = c[1] + "";
res.Push(st8);
break;
default:
String[] st9 = new String[3];
c[0] = getFacoter();
c[1] = getFacoter();
list.Push(c);
st9[0] = c[0] + "";
st9[1] = ch + "";
st9[2] = c[1] + "";
res.Push(st9);
break;
}
}
}
private void button4_Click(object sender, EventArgs e)
{
Console.WriteLine("AAA");
string st = textBox1.Text;
string ss = addConnect(st);
Console.WriteLine(ss);
string ss1 = change(ss);
string ss2;
if (check(ss1))
{
ss2 = ss1;
}
else
{
ss2 = "";
}
//a*b(b|a)*
//a*b.ba|*.
Console.WriteLine("BBB");
Console.WriteLine(ss2);
Console.WriteLine("CCC");
ToNFA(ss2);
foreach(string[] ch in res)
{
String[] st_t = new String[3];
st_t[0] = ch[0];
st_t[1] = ch[1];
st_t[2] = ch[2];
res_T.Push(st_t);
}
foreach (string[] ch in res_T)
{
Console.WriteLine(ch[0] + " " + ch[1] + " " + ch[2] + " ");
ListViewItem item = new ListViewItem();
item.Text = ch[0];
item.SubItems.Add(ch[1]);
item.SubItems.Add(ch[2]);
listView1.Items.Add(item);
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void button9_Click(object sender, EventArgs e)
{
string st = textBox1.Text;
string ss = addConnect(st);
textBox2.Text = ss;
}
private void button10_Click(object sender, EventArgs e)
{
string st = textBox1.Text;
string ss = addConnect(st);
string ss1 = change(ss);
textBox3.Text = ss1;
}
private void button2_Click(object sender, EventArgs e)
{
System.Environment.Exit(0);
}
}
}
public class Stack
{
private int maxSize;// 栈的大小
private int top;
private char[] arr;
public Stack()
{
maxSize = 30;
top = -1;
arr = new char[maxSize];
}
public void push(char value)
{ // 压入数据
arr[++top] = value;
}
public char pop()
{ // 弹出数据
return arr[top--];
}
public char peek()
{ // 访问栈顶元素
return arr[top];
}
public bool isFull()
{ // 栈是否满了
return maxSize - 1 == top;
}
public bool isEmpty()
{ // 栈是否为空
return top == -1;
}
public int length()
{
return top + 1;
}
public String getString()
{
if (top == -1)
return "";
String s = "";
int point = 0;
while (point <= top)
{
s += arr[point];
point++;
}
return s;
}
}