using System.Text; namespace CompilerDesignIFlr1 { internal class LR1Table { internal List Rows = []; internal LR1Table(LR1Creator creator) { for (int i = 0; i < creator.Closures.Count; i++) { LR1Closure closure = creator.Closures[i]; Dictionary @goto = []; Dictionary action = []; foreach (var (by, nextIndex) in closure.Next) { if (creator.TokenUnit.ContainsKey(by)) action.Add(by, "s" + nextIndex); else @goto.Add(by, nextIndex); } foreach (var unit in closure.GetReduceUnits()) { foreach (string prospect in unit.Prospect) { if (action.ContainsKey(prospect)) throw new Exception("Reduce,Reduce/Reduce,Shift error occurred."); action.Add(prospect, "r" + unit.Id); } } Rows.Add(new Row(i, @goto, action)); } PrintRow(); return; } private void PrintRow() { foreach (Row row in Rows) { Console.WriteLine(row); } } } internal class Row { internal int Id; internal Dictionary GOTO; internal Dictionary ACTION; internal Row(int id, Dictionary @goto, Dictionary action) { Id = id; GOTO = @goto; ACTION = action; } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append(Id + " \n"); sb.Append("ACTION: \n"); foreach (var (key, value) in ACTION) sb.Append(key).Append(": ").Append(value).Append(", "); if(GOTO.Count != 0) sb.Append("\nGOTO: \n"); foreach (var (key, value) in GOTO) sb.Append(key).Append(": ").Append(value).Append(", "); sb.Append('\n'); return sb.ToString(); } public (string, int) Next(string name) { if (name == "StatementList" && Id == 0) return ("ACC", 0); if (GOTO.TryGetValue(name, out var result)) return ("GOTO", result); if (ACTION.TryGetValue(name, out var value)) if (value.StartsWith("s")) return ("GOTO", int.Parse(value.Substring(1))); else if (value.StartsWith("r")) return ("Reduce", int.Parse(value.Substring(1))); else throw new Exception($"Value can't be recognized. {value}"); throw new InvalidOperationException($"Code error in state {Id}: {name} not found"); } } }