编译原理——算符优先分析

【目的】 设计一个算符优先分析器,理解优先分析方法的原理。

【要求】 使用算符优先分析算法分析下面的文法:

E → #E#

E → E+T | T

T → T*F | F

F → P^F | P

P → (E) | i

其中i可以看作是一个终结符,无需作词法分析。具体要求如下:

1. 如果输入符号串为正确句子,显示分析步骤,包括分析栈中的内容、优先关系、输入符号串的变化情况;

2. 如果输入符号串不是正确句子,则指示出错位置。

【方法】 首先构造算符优先关系表,然后根据算符优先分析算法编写程序。

【实验环境和工具】 本实验使用的是C#。

说明:本程序输入的目标字符串要以#开头和结尾。

本程序的运行环境是visual studio 2005.net,选择的是控制台应用程序。

源程序代码:

/////文件【program.cs】

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //显示产生式的内容
            Console.WriteLine("产生式为:=====================================================");
            Class1 cs1 = new Class1();
            cs1.generate = new Generate[9];
            cs1.InitGenerate(cs1.generate);
            cs1.Display(cs1.generate);
            Console.WriteLine("");
            Console.WriteLine();
            cs1.DispTable();

            //开始分析句子
            Console.WriteLine();
            Console.WriteLine("===============================================================");
            Console.WriteLine("请输入目标句子(以#开头和结尾):");
            Class1.strWhole = Console.ReadLine();
          
             cs1.process();
         
            Console.ReadLine();
        }
    }
}

/////[文件class1.cs]
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    public struct Generate //用结构体存储产生式
    {
        public char left;//左部
        public string right;//右部

    }
    class Class1
    {
       public  static string strWhole = "";//句子字符串
        static char tempChar = ' ';//当前字符
        static int p = 1;//剩余字符串的当前位置
        static int top = 1;//栈顶
        static int j = 1;
        static char[] stack = new char[30];
        public Generate[] generate;
        char[] VT;//存储非终结符的数组
        static char[] VN = new char[] { 'S', 'E', 'E', 'T', 'T', 'F', 'F', 'P', 'P' };
        static char[,] priority = new char[7, 7];//存储算符优先关系的数组
        public Class1()
        {
            stack[0] = ' ';
            stack[1] = '#';
            this.VT = new char[7] { '+', '*', '^', '(', ')', 'i', '#' };

        }
        //先初始化产生式并存入数组
        public void InitGenerate(Generate[] generate)
        {
            generate[0].left = 'S';
            generate[0].right = "#E#";
            generate[1].left = 'E';
            generate[1].right = "E+T";
            generate[2].left = 'E';
            generate[2].right = "T";
            generate[3].left = 'T';
            generate[3].right = "T*F";
            generate[4].left = 'T';
            generate[4].right = "F";
            generate[5].left = 'F';
            generate[5].right = "P^F";
            generate[6].left = 'F';
            generate[6].right = "P";
            generate[7].left = 'P';
            generate[7].right = "(E)";
            generate[8].left = 'P';
            generate[8].right = "i";
        }
        //将产生式进行显示
        public void Display(Generate[] generate)
        {
            for (int i = 0; i < 9; i++)
            {
                Console.WriteLine("/t" + generate[i].left + "->" + generate[i].right);
            }
        }
        public void DispTable()
        {
            //先将优先关系初始化为N
            for (int i = 0; i < 7; i++)
                for (int j = 0; j < 7; j++)
                {
                    priority[i, j] = 'N';
                }
            //存储FIRSTVT集合
            char[] FS = new char[] { '#' };
            char[] FE = new char[] { '+', '*', '^', '(', 'i' };
            char[] FT = new char[] { '*', '^', '(', 'i' };
            char[] FF = new char[] { '^', '(', 'i' };

            priority[6, 6] = '=';//# = #
            priority[3, 4] = '=';//( = )
            //#            for (int i = 0; i <= 6; i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    if (VT[i] == FE[j])
                    {
                        priority[3, i] = '<'; //(                         priority[6, i] = '<';
                    }
                }
            }
            //+            for (int i = 0; i < 7; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    if (VT[i] == FT[j])
                        priority[0, i] = '<';
                }
            }
            //*            for (int i = 0; i < 7; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (VT[i] == FF[j])
                    {
                        priority[1, i] = '<';
                        priority[2, i] = '<';
                    }
                }
            }
            //存储LASTVT集合
            char[] LE = new char[] { '+', '*', '^', ')', 'i' };
            char[] LT = new char[] { '*', '^', ')', 'i' };
            char[] LP = new char[] { ')', 'i' };
            for (int i = 0; i < 7; i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    if (VT[i] == LE[j])
                    {
                        priority[i, 6] = '>';//LASTVT(E)> #
                        priority[i, 0] = '>';//LASTVT(E)> +
                        priority[i, 4] = '>';//LASTVT(E)> ')'
                    }
                }
            }
            //LASTVT(T)> *

            for (int i = 0; i < 7; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    if (VT[i] == LT[j])
                        priority[i, 1] = '>';
                }
            }
            //LASTVT(P)> '^'
            for (int i = 0; i < 7; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    if (VT[i] == LP[j])
                        priority[i, 2] = '>';
                }
            }
            //显示算府优先关系表
            Console.WriteLine("算符优先关系表为:");
            Console.WriteLine("/t+/t*/t^/t(/t)/ti/t#/t");
            Console.WriteLine("----------------------------------------------------------");
            for (int i = 0; i < 7; i++)
            {
                Console.Write(VT[i] + "/t");
                for (int j = 0; j < 7; j++)
                    Console.Write(priority[i, j].ToString() + "/t");

                Console.WriteLine();
            }
           


        }
        public void process()
        {
            char result = ' ';
            char Q = ' ';
            string str="";
          
            //确保以#开头和结尾
            while (strWhole.Substring(0, 1) != "#" || strWhole.Substring(strWhole.Length - 1, 1) != "#")
            {
                Console.WriteLine("请重新输入,以#开头和结尾:");
                strWhole = Console.ReadLine();
            }
            Console.WriteLine("栈         当前符号       剩余字符串    操作");
            readNext();
                Display();
            while (true )
            {
             
              
                if (isMemVT(stack[top],this .VT ))
                    j = top;
                else
                    j = top - 1;
                result = CompareChar(stack[j], tempChar, this.VT);
              
                if (result == '>')
                {
                    Q = stack[j];
                   while (CompareChar(stack[j], Q, this.VT) != '<')
                    {
                        Q = stack[j];
                        if (isMemVT(stack[j - 1], this.VT))
                            j = j - 1;
                        else j = j - 2;
                    }
                    for (int i = j + 1; i <= top; i++)
                    {
                        str += stack[i];
                    }
                     Console.Write(  "/t归约"+"/n");
                    top = j + 1;
                    stack[top] = 'N';
                    Display();
                  
                   
                }
                else if (result == '<')
                { Console.Write(" /t" + "移进" + "/n");
                    top = top + 1;
                    stack[top] = tempChar;
                    readNext();
                    Display();
                  
                 
                }
                else if (result == '=')
                {
                    if (stack[j] == '#')
                    {
                        if (p == strWhole.Length - 1)
                        {
                            Console.WriteLine();
                            Console.WriteLine("分析成功!");
                            break;
                        }
                        else
                        {
                            Console.WriteLine("出错!");
                            break;
                        }
                    }
                    else
                    {
                        Console.Write("/t移进/n");
                        top = top + 1;
                        stack[top] = tempChar;
                        readNext();
                        Display();
                    }
                }
                else
                {
                Console .WriteLine ("出错!");
                break;
                }
            }
        

        }
        static void Display()
        {
            for (int i = 1; i <= top; i++)
            {
                Console.Write(stack[i]);
            }
            Console.Write("/t/t" + tempChar.ToString()+"/t/t");
            if (tempChar == '#')   Console.Write("");
            else
            {
                for (int i = p; i <= strWhole.Length - 1; i++)
                {
                    Console.Write(strWhole[i]);
                }
            }
           
        }
        static bool isMemVT(char c, char[] VT)
        {
            bool r = false;
            for (int i = 0; i <=VT.Length - 1; i++)
            {
                if (c == VT[i])
                {
                    r = true;
                    break;
                }
                   
            }
            return r;
        }

        static void readNext()
        {
            tempChar = strWhole [p];
            if (p <= strWhole.Length - 2)
                p += 1;
            else p = strWhole.Length - 1;
        }
        static char CompareChar(char c1, char c2, char[] VT)
        {

            int a = 0, b = 0;
            for (int i = 0; i < 7; i++)
            {
                if (VT[i] == c1) a = i;
                if (VT[i] == c2) b = i;

            }
            return priority[a, b];
        }
       public  static void clear()
        {
            top = 1;
            p = 1;
            j = 1;
            strWhole = "";
            tempChar =' ';
            strWhole="";
            char []stack = new char[30];
        }
    }
}

你可能感兴趣的:(编译原理——算符优先分析)