CompilerDesignIFLR1/CompilerDesignIflr1/StateMachine.cs

72 lines
2.5 KiB
C#

namespace CompilerDesignIFlr1
{
internal class StateMachine
{
internal LR1Table Table;
internal LexicalAnalysis AnalysisResult;
internal LR1Creator Creator;
internal List<(LR1Unit, int)> _Stack = [(new LR1Unit("End","#"),0)];
internal Stack<LR1Unit> Tokens;
internal SemanticAnalysis SemanticAnalysis;
internal StateMachine(LR1Table table, LexicalAnalysis analysis, LR1Creator creator, SemanticAnalysis semanticAnalysis)
{
Table = table;
AnalysisResult = analysis;
Creator = creator;
Tokens = AnalysisResult.GetStack();
SemanticAnalysis = semanticAnalysis;
Compute();
}
internal void Compute()
{
try
{
while (true)
{
if (ComputeOnce(Tokens.Pop()))
break;
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Environment.Exit(1);
}
}
internal bool ComputeOnce(LR1Unit unit)
{
var (action, destination) = Table.Rows[_Stack[^1].Item2].Next(unit.Name);
switch (action)
{
case "GOTO":
_Stack.Add((unit, destination));
SemanticAnalysis.ShiftAnalysis(unit);
break;
case "Reduce":
var reduceUnit = Creator.UnitIndex[destination];
if (reduceUnit.CanReduce(_Stack.Select(x => x.Item1).ToList()))
{
var vals = _Stack.Skip(_Stack.Count - reduceUnit.Grammar.Count).Take(reduceUnit.Grammar.Count).Select(x=>x.Item1) .ToList();
reduceUnit = SemanticAnalysis.Analysis(vals, reduceUnit.Clone());
_Stack.RemoveRange(_Stack.Count - reduceUnit.Grammar.Count, reduceUnit.Grammar.Count);
}
else
throw new Exception("Reduce not allow.");
Console.WriteLine(reduceUnit);
Tokens.Push(unit);
Tokens.Push(reduceUnit);
break;
case "ACC":
Console.WriteLine(Creator.UnitIndex[destination]);
return true;
default:
throw new Exception("Action is not recognized.");
}
return false;
}
}
}