/// <summary> /// Prints the list of character and label ranges. /// </summary> /// <param name="characters">The collection of characters; or <see langword="null"/>.</param> /// <param name="labels">The collection of labels; or <see langword="null"/>.</param> /// <returns>A list of terms.</returns> private IListTerm PrintCharacterRangesAndLabels(IEnumerable<CodePoint> characters, IEnumerable<LabelRef> labels) { #region Contract Contract.Ensures(Contract.Result<IListTerm>() != null); #endregion // Put all characters and labels in one set (that tracks ranges). var set = new OrderedRangedSet<int>(); if (characters != null) { var codePoints = characters as CodePoint[] ?? characters.ToArray(); set.AddAll(codePoints.Where(c => !c.IsEof).Select(c => unchecked((int)c.Value))); // If the range contains the 16-bit Eof, add the 8-bit Eof. if (codePoints.Any(c => c.IsEof)) set.Add(256); } if (labels != null) set.AddAll(labels.Select(l => l.Index + SpoofaxParseTableFormat.LabelBase)); // Turn each range into a term. List<ITerm> result = new List<ITerm>(); foreach(var range in set.GetRanges()) { if (range.IsEmpty) // ReSharper disable once RedundantJumpStatement continue; else if (range.Start == range.End - 1) result.Add(factory.Int(range.Start)); else result.Add(factory.Cons("range", factory.Int(range.Start), factory.Int(range.End - 1))); } return factory.List(result); }