2024-12-27 01:25:50 +08:00
|
|
|
|
using System.Text;
|
2024-12-23 01:42:58 +08:00
|
|
|
|
|
|
|
|
|
namespace CompilerDesignIFlr1
|
|
|
|
|
{
|
|
|
|
|
internal class LR1Table
|
|
|
|
|
{
|
|
|
|
|
internal List<Row> Rows = [];
|
|
|
|
|
|
|
|
|
|
internal LR1Table(LR1Creator creator)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < creator.Closures.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
LR1Closure closure = creator.Closures[i];
|
|
|
|
|
Dictionary<string, int> @goto = [];
|
|
|
|
|
Dictionary<string, string> 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<string, int> GOTO;
|
|
|
|
|
internal Dictionary<string, string> ACTION;
|
|
|
|
|
|
|
|
|
|
internal Row(int id, Dictionary<string, int> @goto, Dictionary<string, string> 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(", ");
|
2024-12-27 01:25:50 +08:00
|
|
|
|
if(GOTO.Count != 0)
|
|
|
|
|
sb.Append("\nGOTO: \n");
|
2024-12-23 01:42:58 +08:00
|
|
|
|
foreach (var (key, value) in GOTO)
|
|
|
|
|
sb.Append(key).Append(": ").Append(value).Append(", ");
|
2024-12-27 01:25:50 +08:00
|
|
|
|
sb.Append('\n');
|
2024-12-23 01:42:58 +08:00
|
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|