public static Antlr4.Runtime.Misc.IntervalSet Subtract(Antlr4.Runtime.Misc.IntervalSet left, Antlr4.Runtime.Misc.IntervalSet right)
{
if (left == null || left.IsNil)
{
return new Antlr4.Runtime.Misc.IntervalSet();
}
Antlr4.Runtime.Misc.IntervalSet result = new Antlr4.Runtime.Misc.IntervalSet(left);
if (right == null || right.IsNil)
{
// right set has no elements; just return the copy of the current set
return result;
}
int resultI = 0;
int rightI = 0;
while (resultI < result.intervals.Count && rightI < right.intervals.Count)
{
Interval resultInterval = result.intervals[resultI];
Interval rightInterval = right.intervals[rightI];
// operation: (resultInterval - rightInterval) and update indexes
if (rightInterval.b < resultInterval.a)
{
rightI++;
continue;
}
if (rightInterval.a > resultInterval.b)
{
resultI++;
continue;
}
Interval? beforeCurrent = null;
Interval? afterCurrent = null;
if (rightInterval.a > resultInterval.a)
{
beforeCurrent = new Interval(resultInterval.a, rightInterval.a - 1);
}
if (rightInterval.b < resultInterval.b)
{
afterCurrent = new Interval(rightInterval.b + 1, resultInterval.b);
}
if (beforeCurrent != null)
{
if (afterCurrent != null)
{
// split the current interval into two
result.intervals[resultI] = beforeCurrent.Value;
result.intervals.Insert(resultI + 1, afterCurrent.Value);
resultI++;
rightI++;
continue;
}
else
{
// replace the current interval
result.intervals[resultI] = beforeCurrent.Value;
resultI++;
continue;
}
}
else
{
if (afterCurrent != null)
{
// replace the current interval
result.intervals[resultI] = afterCurrent.Value;
rightI++;
continue;
}
else
{
// remove the current interval (thus no need to increment resultI)
result.intervals.RemoveAt(resultI);
continue;
}
}
}
// If rightI reached right.intervals.size(), no more intervals to subtract from result.
// If resultI reached result.intervals.size(), we would be subtracting from an empty set.
// Either way, we are done.
return result;
}