文法类型判断,
正规文法转换为正规式:
转换规则1(A->xB,B->y--->A->xy)
转换规则2 (A->x,A|y--->A->x*(y))
转换规则3(A->x,A-y,--->A->x|y)
不确定的有限自动机(NFA): 一种数学模型
(1) 一个有限的状态集合S
(2) 一个输入符号集合∑(不包含ε)
(3) 一个转换函数move: S X (∑ U {ε}) -> P(S)
(4) 状态s0是唯一的开始状态
(5) 状态集合F是接受状态集合,S包含F
确定的有限自动机(DFA): 是NFA的特殊情况
(1) 任何状态都没有ε转换
(2) 对于任何状态s和任何输入符号a,最多只有一条标记为a的边离开,即转换函数move: S X ∑-> S可以是一个部分函数。
int inputn;
public struct production
{
public string left;
public string right;
};
public struct circle
{
public string name;
public int sit;
}
int n=10;//change()用
int np = 0;
int circlesit;
int proNumber = 0;
string[,]paint=new string[20,3];
string strings;
string shunxu;
string strLeft;
production[] p = new production[50];
circle[] c = new circle[10];
void chop(production[] p, int i)
{
int j;
for (j = 0; j < strings.Length; j++)
if (strings[j] == '>')
{
p[i].left = strings.Substring(0, j - 1);
p[i].right = strings.Substring(j + 1, strings.Length - j-1);
//cout<<"chop"<<endl;
// rtb_get.Text += "\n"+p[i].left +" "+ p[i].right ;
}
}
void getk(production[] p, int i)
{
paint[np,0] = p[i].left;
if (p[i].right.Length > 0)
{
if (p[i].right.Length == 1)
{
paint[np, 1] = "ε";
paint[np, 2] = "Z";
//rtb_get.Text += "这儿有一个空";
}
else
{
if (p[i].right[0] >= 'a' && p[i].right[0] <= 'z')
paint[np, 1] = p[i].right.Substring(0, 1);
if (p[i].right[1] >= 'A' && p[i].right[1] <= 'Z')
paint[np, 2] = p[i].right.Substring(1, 1);
//rtb_get.Text += " get paint" + i;
}
}
np++;
//rtb_output.Text += "做了吗?\n";
}
public bool three(production[] p)
{
int flag = 0, ti;
for (ti = 0; ti < inputn; ti++)
{
if (p[ti].right == "$")
flag++;
if (p[ti].left.Length <= p[ti].right.Length)//每个产生式均为|右|>=|左|
{
if ((p[ti].left.Length == 1) && (p[ti].left[0] >= 'A') && (p[ti].left[0] <= 'Z'))//产生式左边只有一个。且是非终结符
{
if (p[ti].right.Length == 1 && p[ti].right[0] >= 'a' && p[ti].right[0] <= 'z')//右部只有一个 终结符
flag++;
else if (p[ti].right.Length == 2 && p[ti].right[0] >= 'a' && p[ti].right[0] <= 'z' && p[ti].right[1] >= 'A' && p[ti].right[1] <= 'Z')
flag++;
else if (p[ti].right.Length== 2 && p[ti].right[1] >= 'a' && p[ti].right[1] <= 'z' && p[ti].right[0] >= 'A' && p[ti].right[0] <= 'Z')
flag++;
}
}
}
if (flag == ti)
return true;
else
return false;
}
public void changetest1(production[] p)
{
n = inputn;
production[] pc = p;
int j;
for (int i = 0; i < n; i++)
{
//转换规则3
for (j = 0; j < n; j++)
{
if (pc[i].left == pc[j].left && pc[i].right != pc[j].right)
{
pc[i].right = pc[i].right + "|" + pc[j].right;
pc[j].left = "";
pc[j].right = "";
rtb_output.Text += pc[i].left + "=" + pc[i].right + "\n";
}
///
}
}
//转换规则2
//形如(A->xA|y--->A->x*(y))
for (int i = 0; i < n; i++)
{//pc[i]=A->(a|d)A(a|d)
int l = 0;
if (pc[i].right.Length > 3)
for (int tstl = 0; tstl < pc[i].right.Length; tstl++)
{
if (pc[i].right[tstl] == '|')
{
l = tstl;
}
if (pc[i].left[0] == pc[i].right[tstl])
{
if (l > tstl)
pc[i].right = pc[i].right.Substring(tstl - 1, 1) + "*" + pc[i].right.Substring(l + 1);//A换成*,|去掉; (0,1)(1)
else
pc[i].right = pc[i].right.Substring(tstl - 1, 1) + "*" + pc[i].right.Substring(0, l);
//rtb_output.Text += "\n\n规则2\n" + pc[i].left + "=" + pc[i].right + "\n\n";
}
}
}
for(int sn=0;sn< n;sn++)
{
if (pc[sn].left.Length > 0)
{
rtb_output.Text += pc[sn].left + "=" + pc[sn].right+"\n";
}
}
//rtb_output.Text += "之前都是这样的\n\n";
int xs = shunxu.Length - 3;//除去Z和倒数第一个
for(xs = shunxu.Length - 3;xs>=0;xs--)
{
for (int i = 0; i < n; i++)
{ if (pc[i].left.Length>0 && shunxu[xs]==pc[i].left[0])//按name顺序找特定非终结符转换
{
int b = pc[i].right.Length;
for (int j1 = 0; j1 < b; j1++)//在pc[i]的右部
{
if ('A' <= pc[i].right[j1] && pc[i].right[j1] <= 'Z')//找非终结符
{
if (pc[i].left[0]== pc[i].right[j1])//右部非终结符是左部
{
pc[i].right = "("+pc[i].right.Substring(0, j1) + ")*"+ pc[i].right.Substring(j1+2);
rtb_output.Text += pc[i].left + "=" + pc[i].right + "\n";
b = pc[i].right.Length;
}
for (int k = 0; k < n; k++)
{
if (pc[k].left.Length > 0 && pc[k].left[0] == pc[i].right[j1])//找非终结符对应的子式
{
pc[i].right = pc[i].right.Substring(0, j1) + pc[k].right + pc[i].right.Substring(j1+1);//替换pc[i]的非终结符
rtb_output.Text += pc[i].left + "=" + pc[i].right+"\n";
b = pc[i].right.Length;
}
}
}
}
}
}
}
}
public void changezgs()
{
//strings = "b(ab)*ab*";
//strings = "b((ba)*ab*a)*";
//strings = "b((ab)*bb*a)*";
proNumber = 0;
int nutNumber = 0;
char[] zgs = strings.ToCharArray();
char[] nut = { 'A', 'B', 'C', 'D', 'E', 'F' };
rtb_output.Text += "\n以下为生成过程,结果在末尾\n";
//for (int i = strings.Length-1;i>0 ; i--)
for (int i = 0; i < strings.Length; i++)//只执行zgs时p[0].right 不知道怎么不见了
{
if ('a' <= strings[0] && strings[0] <= 'z')
{
//只需要转换成产生式即文法即可
p[proNumber].left = strLeft;
p[proNumber].right = strings.Substring(0,1)+nut[nutNumber];
strings = strings.Substring(1);
rtb_output.Text += strLeft + "->" + p[proNumber].right + "\n" + "现在右部是" + strings;
proNumber++;
}
if (strings[0] == '(')//不*用括号干什么
{
//rtb_output.Text += "有括号\n";
for (int j = strings.Length - 1; j > 0; j--)
{
if (strings[j] == '*')
{
if (strings[j - 1] == ')')
{
if (j == strings.Length - 1)
{
strings = strings.Substring(0, strings.Length - 2) + nut[nutNumber] + "|$";
rtb_output.Text += nut[nutNumber] + "->" + strings + "\n";
p[proNumber].left = nut[nutNumber].ToString();
p[proNumber].right = "$";
strings = strings.Substring(0, strings.Length - 2);
if (strings[1] == '(')
{
strings = strings.Substring(1);
j = strings.Length;
}
rtb_output.Text += p[proNumber].left +"->"+ p[proNumber].right + "\n" + "现在的右部是" + strings + "\n";
proNumber++;
}
else
{
strings = strings.Substring(0, j - 1) + nut[nutNumber] + "|" + strings.Substring(j + 1);
for (int d = j - 2; d > 0; d--)
{
if (strings[d] == '(')
{
rtb_output.Text += "有左括号\n";
}
}
rtb_output.Text += "\n" + "现在的右部是" + strings + "\n";
}
}
}
}
}
if (strings[i] == '*')
{
strings = strings.Substring(0, i) + nut[nutNumber] + "|" + strings.Substring(i + 1);
rtb_output.Text += "现在右部是" + strings + "\n";
}
}
//去掉未处理的左括号
if (strings[0] == '(')
strings = strings.Substring(1);
for(int i=0;i<strings.Length;i++)
{
if(strings[i]=='(')
{
strings = strings.Substring(0, i) + strings.Substring(i + 1);
}
}
//根据|分开
for (int i = 0; i < strings.Length; i++)
{
if (strings[i] == '|')
{
p[proNumber].left = nut[nutNumber].ToString();
p[proNumber].right = strings.Substring(0, i);
strings = strings.Substring(i + 1);
i = 0;
rtb_output.Text += p[proNumber].left +"->"+ p[proNumber].right + "\n" + "现在的右部是" + strings + "\n";
proNumber++;
}
}
if(strings.Length<=2)
{
p[proNumber].left = nut[nutNumber].ToString();
p[proNumber].right = strings;
strings = "";
rtb_output.Text += p[proNumber].left + "->" + p[proNumber].right + "\n" + "现在的右部是" + strings + "\n\n\n";
proNumber++;
}
//将右部大于2的生成式 根据规则1 转换
for(int i=0;i<proNumber;i++)
{
if(p[i].right.Length>2)
{
p[proNumber].left = nut[++nutNumber].ToString();
p[proNumber].right = p[i].right.Substring(p[i].right.Length - 2);
p[i].right = p[i].right.Substring(0, p[i].right.Length - 2)+nut[nutNumber];
rtb_output.Text += p[proNumber].left + "->" + p[proNumber].right + "\n" + "现在的p[i]右部是" +p[i].left+"->"+ p[i].right + "\n";
proNumber++;
}
}
}
public void zgs()
{
np = 0;
//production[] p = new production[50];
string[] str = rtb_get.Text.Split('=');
string test = str[1];
rtb_get.Text += "|"+test + "|";
if (rtb_get.Text == null)
{
rtb_get.Text += "啊我瞎了!!!一片空白亮瞎我的眼\n";
}
strLeft = str[0];
strings = str[1];
rtb_output.Text += strings;
changezgs();
rtb_output.Text += "\n\n该正规式文法为:";
for (int i=0;i<proNumber;i++)
{
rtb_output.Text +=p[i].left + "->" + p[i].right + ",";
}
inputn = proNumber;
for (int i = 0; i < proNumber; i++)
{
getk(p, i);
}
if (three(p))
{
drowcircle();
}
else
rtb_get.Text += "文法不是正规文法\n";
}
public void zgwf()
{
int i = 0,np=0, j;
string[] str = rtb_get.Text.Split(',');
if (rtb_get.Text == null)
{
rtb_get.Text += "啊我瞎了!!!一片空白亮瞎我的眼\n";
}
for (i = 0; i < 10; i++)
{
strings=str[i];
if (strings == "end")
{
inputn = i;
break;
}
chop(p, i);
getk(p, i);
}
if (three(p))
{
drowcircle();
changetest1(p);
}
else
rtb_get.Text += "文法不是正规文法\n";
}
public void zdj()
{
string[] zdjstr = rtb_get.Text.Split(',');
for (int i = 0; i < 10; i++)
{
if (zdjstr[i] == "end")
{
inputn = i;
break;
}
string[] bbb;
string[,] css=new string[20,3];
bbb = zdjstr[i].Split('>');//输入的自动机是S>a>B;的形式
p[i].left = bbb[0];
if (bbb[1] != "$" && zdjstr[i].Length > 4)
p[i].right = bbb[1] + bbb[2];//将其转换为S->aB chop后的形式
else
p[i].right = bbb[1];
getk(p, i);
}
if (three(p))
{
drowcircle();
changetest1(p);
// change(p);
}
else
rtb_get.Text += "文法不是正规文法\n";
}
主要算法如上述
其他为绘图及美化,主要绘图函数如下:
Pen p = new Pen(Color.Black, 3);
Graphics g = this.CreateGraphics();//g.DrawEllipse(p, 10, 60, 30, 30);//g.DrawString("S", this.Font, Brushes.Black, string_X ,72);
p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
g.DrawArc(p, arc_Xstart, 10, arc_endX - arc_Xstart, 100, -180, 180);//p,起点x坐标,起点y,宽,高,起点角度-180水平向左,终点角度
g.DrawString(paint[di, 1], this.Font, Brushes.Black, arc_Xstart + (arc_endX - arc_Xstart) / 2, 10);
实现了中等复杂的文法处理,并不完善,其他未设计相应算法的文法仍不能处理。