72 lines
2.5 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|