Purpose and Requirement of LL(1) Analysis Program Experiments
_Develop a sentence (program) that can identify whether the sequence of word symbols given by lexical analysis is the correct sentence (program) of a given grammar, and output the analysis process of input symbols.
Experimental content
_For this experiment, the core content is the Process class. This class is a constructor with three parameters. Initial analysis stack, input sentences and predictive analysis table are injected into this class as parameters. Begin Analyze () function is called for analysis. At the same time, the properties of Process itself change iteratively in the cycle of function. Its own properties represent the results of each analysis step, and printing is enough.
Experimental steps
- Main function content: First print out the given grammar, predict the analysis table, then input to the user, construct the Process class, and analyze.
- Get the production or matching used for derivation: GetProductionRule()
GetRowIndex(StackTop) and GetColIndex(Terminal) need to be invoked to retrieve the contents of the prediction analysis table based on the top element of the analysis stack and the first character of the input string. - Reverse string function: This function is used to reverse the production elements into the stack
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 Stack data structure to complete, but uses the operation of strings instead of Stack.
using System; using System.Collections.Generic; using static System.Console; namespace LL1 { class Program { /// <summary> //Grammar /// </summary> static List<string> Grammar = new List<string>() { "E->TB","B->+TB|ε", "T->FY","Y->*FY|ε", "F->i|(E)" }; /// <summary> /// Predictive analysis table /// </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("Please enter the string to be analyzed:"); string inputString = ReadLine(); WriteLine("--------------------------------------------------------------------------"); string symbolStack = "#E"; Process process = new Process(symbolStack, inputString, predictTab); process.BeginAnalyze(); } /// <summary> /// Print grammar lists /// </summary> static void DisplayG() { WriteLine("Grammar list (Examples of courseware E' Replaced B , T' Replaced Y)"); foreach (string s in Grammar) { WriteLine(s); } WriteLine("--------------------------------------------------------------------------"); } /// <summary> /// Print Predictive Analysis Table /// </summary> static void DisplayTab() { WriteLine("{0,35}", "Predictive analysis table"); 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;//step public string symbolStack;//Analysis stack public string residueString;//Residue string public string productionRule;//Production or Matching public string[,] predictTab;//Prediction table public Process(string symbolStack, string inputString, string[,] predictTab) { this.index = 1; this.symbolStack = symbolStack; this.residueString = inputString; this.predictTab = predictTab; } //Current input symbol public string Terminal { get { return residueString.Substring(0, 1); } } //Analysis of stack top elements public string StackTop { get { return symbolStack.Substring(symbolStack.Length - 1, 1); } } //Productive acronym public string ruleTop { get { return productionRule.Substring(0,1); } } /// <summary> /// LL(1) Analysis /// </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(" The analysis is completed and the matching is successful!"); 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> /// Obtain the production or matching used in derivation /// </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> /// Get the line number from the top element of the stack /// </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> /// Get the column number based on the current Terminator /// </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> /// Inversion string /// </summary> /// <param name="s"></param> /// <returns></returns> private string Reverse(string s) { char[] cs= s.ToCharArray(); Array.Reverse(cs); return new string(cs); } /// <summary> /// Print the current step /// </summary> private void Display() { WriteLine($"{index,-20}{symbolStack,-20}{residueString,-20}{productionRule,-20}"); } /// <summary> /// Error Handling Procedure /// </summary> private void Error() { WriteLine("!!!!!!!!!!!!!! Illegal statement !!!!!!!!!!!!!!"); Environment.Exit(0); } } } }