private static int OptimizeSets(ATN atn, bool preserveOrder)
{
if (preserveOrder)
{
// this optimization currently doesn't preserve edge order.
return 0;
}
int removedPaths = 0;
IList<DecisionState> decisions = atn.decisionToState;
foreach (DecisionState decision in decisions)
{
IntervalSet setTransitions = new IntervalSet();
for (int i = 0; i < decision.NumberOfOptimizedTransitions; i++)
{
Transition epsTransition = decision.GetOptimizedTransition(i);
if (!(epsTransition is EpsilonTransition))
{
continue;
}
if (epsTransition.target.NumberOfOptimizedTransitions != 1)
{
continue;
}
Transition transition = epsTransition.target.GetOptimizedTransition(0);
if (!(transition.target is BlockEndState))
{
continue;
}
if (transition is NotSetTransition)
{
// TODO: not yet implemented
continue;
}
if (transition is AtomTransition || transition is RangeTransition || transition is SetTransition)
{
setTransitions.Add(i);
}
}
if (setTransitions.Count <= 1)
{
continue;
}
IList<Transition> optimizedTransitions = new List<Transition>();
for (int i_1 = 0; i_1 < decision.NumberOfOptimizedTransitions; i_1++)
{
if (!setTransitions.Contains(i_1))
{
optimizedTransitions.Add(decision.GetOptimizedTransition(i_1));
}
}
ATNState blockEndState = decision.GetOptimizedTransition(setTransitions.MinElement).target.GetOptimizedTransition(0).target;
IntervalSet matchSet = new IntervalSet();
for (int i_2 = 0; i_2 < setTransitions.GetIntervals().Count; i_2++)
{
Interval interval = setTransitions.GetIntervals()[i_2];
for (int j = interval.a; j <= interval.b; j++)
{
Transition matchTransition = decision.GetOptimizedTransition(j).target.GetOptimizedTransition(0);
if (matchTransition is NotSetTransition)
{
throw new NotSupportedException("Not yet implemented.");
}
else
{
matchSet.AddAll(matchTransition.Label);
}
}
}
Transition newTransition;
if (matchSet.GetIntervals().Count == 1)
{
if (matchSet.Count == 1)
{
newTransition = new AtomTransition(blockEndState, matchSet.MinElement);
}
else
{
Interval matchInterval = matchSet.GetIntervals()[0];
newTransition = new RangeTransition(blockEndState, matchInterval.a, matchInterval.b);
}
}
else
{
newTransition = new SetTransition(blockEndState, matchSet);
}
ATNState setOptimizedState = new BasicState();
setOptimizedState.SetRuleIndex(decision.ruleIndex);
atn.AddState(setOptimizedState);
setOptimizedState.AddTransition(newTransition);
optimizedTransitions.Add(new EpsilonTransition(setOptimizedState));
removedPaths += decision.NumberOfOptimizedTransitions - optimizedTransitions.Count;
if (decision.IsOptimized)
{
while (decision.NumberOfOptimizedTransitions > 0)
{
decision.RemoveOptimizedTransition(decision.NumberOfOptimizedTransitions - 1);
}
}
foreach (Transition transition_1 in optimizedTransitions)
{
decision.AddOptimizedTransition(transition_1);
}
}
return removedPaths;
}