Compilation Principle - LL1 Analysis Program Experiment (C#)

LL(1) Purpose and Requirements of Analytical Program Experiment

  Compile a sentence (program) that can identify whether the sequence of word symbols given by lexical analysis is a correct sentence (program) of a given grammar, and output the analysis process of the input symbol string.

Experimental content

  For this experiment, the core content is the Process class. The class is a constructor with three parameters. Inject the initial analysis stack, the input sentence, and the predictive analysis table as parameters into this class, and call the BeginAnalyze() function for analysis. At the same time, the properties of Process itself change iteratively in the function loop, and its own properties represent the value of each analysis step. As a result, print it.

Experimental procedure

  • Main function content: first print out the given grammar and predictive analysis table, and then analyze the user input to construct a Process class.
  • Obtain the production or matching used for derivation: GetProductionRule()
    needs to call GetRowIndex(StackTop) and GetColIndex(Terminal) to obtain the content of the predictive analysis table based on the top element of the analysis stack and the first character of the input string.
  • Reverse string function Reverse(string s): This function is used to push the elements of the production into the stack in reverse order
            private string Reverse(string s)
            {
                char[] cs= s.ToCharArray();
                Array.Reverse(cs);
                return new string(cs);
            }

  It is worth mentioning that this program does not use the Stack data structure to complete, but uses the operation of the string instead of the Stack.

insert image description here
insert image description here

using System;
using System.Collections.Generic;
using static System.Console;

namespace LL1
{

    class Program
    {
        /// <summary>
        /// 文法
        /// </summary>
        static List<string> Grammar = new List<string>()
        {
            "E->TB","B->+TB|ε",
            "T->FY","Y->*FY|ε",
            "F->i|(E)"
        };
        /// <summary>
        /// 预测分析表
        /// </summary>
        /// <param name="args"></param>
        static string[,] predictTab =
        {
            {"  ",   "i",     "+",    "*",    "(",    ")",    "#" },
            {"E"   ,   "TB",   "NULL", "NULL", "TB",  "NULL", "NULL" },
            {"B"  ,   "NULL",  "+TB", "NULL", "NULL", "ε",   "ε"},
            {"T"   ,   "FY",   "NULL", "NULL", "FY",  "NULL", "NULL" },
            {"Y"  ,   "NULL",  "ε",   "*FY", "NULL", "ε",   "ε" },
            {"F"   ,   "i",     "NULL", "NULL", "(E)",  "NULL", "NULL" }
        };

        static void Main(string[] args)
        {
            DisplayG();
            DisplayTab();
            WriteLine("请输入要分析的串:");
            string inputString = ReadLine();
            WriteLine("--------------------------------------------------------------------------");
            string symbolStack = "#E";
            Process process = new Process(symbolStack, inputString, predictTab);
            process.BeginAnalyze();
        }


        /// <summary>
        /// 打印文法列表
        /// </summary>
        static void DisplayG()
        {
            WriteLine("文法列表  (将课件例题中的 E' 换成了 B , T' 换成了 Y)");
            foreach (string s in Grammar)
            {
                WriteLine(s);
            }
            WriteLine("--------------------------------------------------------------------------");
        }
        /// <summary>
        /// 打印预测分析表
        /// </summary>
        static void DisplayTab()
        {
            WriteLine("{0,35}", "预测分析表");
            for (int i = 0; i < predictTab.GetLength(0); i++)
            {
                for (int j = 0; j < predictTab.GetLength(1); j++)
                {
                    Write($"{predictTab[i, j],-10}");
                }
                WriteLine();
            }
            WriteLine("--------------------------------------------------------------------------");
        }

        class Process
        {
            public int index;//步骤
            public string symbolStack;//分析栈
            public string residueString;//剩余串
            public string productionRule;//产生式或匹配
            public string[,] predictTab;//预测表

            public Process(string symbolStack, string inputString, string[,] predictTab)
            {
                this.index = 1;
                this.symbolStack = symbolStack;
                this.residueString = inputString;
                this.predictTab = predictTab;
            }
            
            //当前输入符号
            public string Terminal
            {
                get
                {
                    return residueString.Substring(0, 1);
                }              
            }
            //分析栈栈顶元素
            public string StackTop
            {
                get
                {
                    return symbolStack.Substring(symbolStack.Length - 1, 1);
                }
            }
            //产生式首字符
            public string ruleTop
            {
                get
                {
                    return productionRule.Substring(0,1);
                }
            }
            /// <summary>
            /// LL(1) 分析
            /// </summary>
            public void BeginAnalyze()
            {                
                while (true)
                {
                    productionRule = GetProductionRule();
                    Display();
                    symbolStack = symbolStack.Substring(0, symbolStack.Length - 1);
                    if (productionRule== "ε")
                    {
                        index++;
                        continue;
                    }
                    if (ruleTop == Terminal)
                    {
                        if (residueString.Length == 1)
                        {
                            WriteLine("     分析完成,匹配成功!");
                            return;
                        }
                        else
                        {
                            residueString = residueString.Substring(1, residueString.Length-1);
                            if (productionRule.Length > 1)
                            {
                                symbolStack += Reverse(productionRule.Substring(1, productionRule.Length - 1));
                            }
                        }
                    }
                    else
                    {
                        residueString = residueString.Substring(0, residueString.Length);
                        symbolStack += Reverse(productionRule);
                    }
                    index++;
                }
            }

            /// <summary>
            /// 获取推导所用的产生式或匹配
            /// </summary>
            /// <returns></returns>
            private string GetProductionRule()
            {                
                int row = GetRowIndex(StackTop);
                int col = GetColIndex(Terminal);
                string rule = predictTab[row, col];
                if (rule == "NULL")
                {
                    Error();
                }               
                return rule;
            }

            /// <summary>
            /// 根据栈顶元素获取行号
            /// </summary>
            /// <param name="stackTop"></param>
            /// <returns></returns>
            private int GetRowIndex(string stackTop)
            {
                int index = -1;
                for(int i = 0; i < predictTab.GetLength(0); i++)
                {
                    if (predictTab[i, 0] == stackTop)
                    {
                        index = i;
                    }
                }
                if (index == -1)
                {
                    Error();
                }
                return index;
            }

            /// <summary>
            /// 根据当前终结符获取列号
            /// </summary>
            /// <param name="terminal"></param>
            /// <returns></returns>
            private int GetColIndex(string terminal)
            {
                int index = -1;
                for (int i = 0; i < predictTab.GetLength(1); i++)
                {
                    if (predictTab[0, i] == terminal)
                    {
                        index = i;
                    }
                }
                if (index == -1)
                {
                    Error();
                }
                return index;
            }

            /// <summary>
            /// 反转字符串
            /// </summary>
            /// <param name="s"></param>
            /// <returns></returns>
            private string Reverse(string s)
            {
                char[] cs= s.ToCharArray();
                Array.Reverse(cs);
                return new string(cs);
            }
            
            /// <summary>
            /// 打印当前步骤
            /// </summary>
            private void Display()
            {
                WriteLine($"{index,-20}{symbolStack,-20}{residueString,-20}{productionRule,-20}");
            }

            /// <summary>
            /// 出错处理程序
            /// </summary>
            private void Error()
            {
                WriteLine("!!!!!!!!!!!!!!  语句非法  !!!!!!!!!!!!!!");
                Environment.Exit(0);
            }

        }
        
    }
}

Guess you like

Origin blog.csdn.net/qq_40404477/article/details/100857120