c# 编译原理 正规文法,正规式,自动机(绘图)转换

文法类型判断,

正规文法转换为正规式:

转换规则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);

 

 

实现了中等复杂的文法处理,并不完善,其他未设计相应算法的文法仍不能处理。

 

 

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值