/// <summary>
        /// Inform about substrings.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="name">The name.</param>
        /// <param name="fakeChild">True if it's a fake child.</param>
        /// <param name="splitter">The <see cref="Splitter"/>.</param>
        private void InformSubstrings(ParserRuleContext ctx, string name, bool fakeChild, Splitter splitter)
        {
            var text   = AntlrUtils.GetSourceText(ctx);
            var path   = this.Inform(ctx, name, text, fakeChild);
            var ranges = this.analyzer.GetRequiredInformRanges(path);

            if (ranges.Count > 4)
            { // Benchmarks showed this to be the breakeven point. (see below)
                var splitList = splitter.CreateSplitList(text);
                foreach (var range in ranges)
                {
                    var value = splitter.GetSplitRange(text, splitList, range);
                    if (value != null)
                    {
                        this.Inform(ctx, ctx, name + range, value, true);
                    }
                }
            }
            else
            {
                foreach (var range in ranges)
                {
                    var value = splitter.GetSplitRange(text, range);
                    if (value != null)
                    {
                        this.Inform(ctx, ctx, name + range, value, true);
                    }
                }
            }
        }
        /// <summary>
        /// The RunSplitList
        /// </summary>
        /// <param name="splitter">The splitter<see cref="Splitter"/></param>
        /// <param name="ranges">The ranges<see cref="List{WordRangeVisitor.Range}"/></param>
        public void RunSplitList(Splitter splitter, List <WordRangeVisitor.Range> ranges)
        {
            IList <Tuple <int, int> > splitList = splitter.CreateSplitList(TEXT);

            foreach (WordRangeVisitor.Range range in ranges)
            {
                splitter.GetSplitRange(TEXT, splitList, range);
            }
        }
        public void TestSplitList()
        {
            string   value    = "one two/3 four-4 five(some more)";
            Splitter splitter = WordSplitter.GetInstance();

            IList <Tuple <int, int> > splitList = splitter.CreateSplitList(value);

            // Illegal values
            splitter.GetSplitRange(value, splitList, -5, 0).Should().BeNull();
            splitter.GetSplitRange(value, splitList, 0, -5).Should().BeNull();
            splitter.GetSplitRange(value, splitList, -5, -5).Should().BeNull();

            // Single word
            splitter.GetSplitRange(value, splitList, 0, 0).Should().BeNull();
            splitter.GetSplitRange(value, splitList, 1, 1).Should().Be("one");
            splitter.GetSplitRange(value, splitList, 2, 2).Should().Be("two");
            splitter.GetSplitRange(value, splitList, 3, 3).Should().Be("3");
            splitter.GetSplitRange(value, splitList, 4, 4).Should().Be("four");
            splitter.GetSplitRange(value, splitList, 5, 5).Should().Be("4");
            splitter.GetSplitRange(value, splitList, 6, 6).Should().Be("five");
            splitter.GetSplitRange(value, splitList, 7, 7).Should().BeNull();

            // First words
            splitter.GetSplitRange(value, splitList, 1, 1).Should().Be("one");
            splitter.GetSplitRange(value, splitList, 1, 2).Should().Be("one two");
            splitter.GetSplitRange(value, splitList, 1, 3).Should().Be("one two/3");
            splitter.GetSplitRange(value, splitList, 1, 4).Should().Be("one two/3 four");
            splitter.GetSplitRange(value, splitList, 1, 5).Should().Be("one two/3 four-4");
            splitter.GetSplitRange(value, splitList, 1, 6).Should().Be("one two/3 four-4 five");
            splitter.GetSplitRange(value, splitList, 1, 7).Should().BeNull();

            // Last words
            splitter.GetSplitRange(value, splitList, 1, -1).Should().Be("one two/3 four-4 five");
            splitter.GetSplitRange(value, splitList, 2, -1).Should().Be("two/3 four-4 five");
            splitter.GetSplitRange(value, splitList, 3, -1).Should().Be("3 four-4 five");
            splitter.GetSplitRange(value, splitList, 4, -1).Should().Be("four-4 five");
            splitter.GetSplitRange(value, splitList, 5, -1).Should().Be("4 five");
            splitter.GetSplitRange(value, splitList, 6, -1).Should().Be("five");
            splitter.GetSplitRange(value, splitList, 7, -1).Should().BeNull();

            // 2 word slices
            splitter.GetSplitRange(value, splitList, 0, 1).Should().BeNull();
            splitter.GetSplitRange(value, splitList, 1, 2).Should().Be("one two");
            splitter.GetSplitRange(value, splitList, 2, 3).Should().Be("two/3");
            splitter.GetSplitRange(value, splitList, 3, 4).Should().Be("3 four");
            splitter.GetSplitRange(value, splitList, 4, 5).Should().Be("four-4");
            splitter.GetSplitRange(value, splitList, 5, 6).Should().Be("4 five");
            splitter.GetSplitRange(value, splitList, 6, 7).Should().BeNull();

            // 3 word slices
            splitter.GetSplitRange(value, splitList, 0, 2).Should().BeNull();
            splitter.GetSplitRange(value, splitList, 1, 3).Should().Be("one two/3");
            splitter.GetSplitRange(value, splitList, 2, 4).Should().Be("two/3 four");
            splitter.GetSplitRange(value, splitList, 3, 5).Should().Be("3 four-4");
            splitter.GetSplitRange(value, splitList, 4, 6).Should().Be("four-4 five");
            splitter.GetSplitRange(value, splitList, 5, 7).Should().BeNull();

            // Edge cases
            splitter.GetSplitRange(value, splitList, 0, 0).Should().BeNull();
            splitter.GetSplitRange(value, splitList, 0, -1).Should().BeNull();
            splitter.GetSplitRange(value, splitList, -1, -1).Should().BeNull();
        }