public void Setup()
 {
     _mapping = new ReferenceInt[N];
     for (int i = 0; i < _mapping.Length; i++)
     {
         _mapping[i] = new ReferenceInt(i);
     }
     _hashTable = ImmutableHashTable <ReferenceInt, int> .Empty;
     for (var i = 0; i < N; i++)
     {
         _hashTable = _hashTable.Add(_mapping[i], i);
     }
 }
        private void ParseLiteralInline(ParsingContext context)
        {
            var inline = context.Object as Inline;

            ReferenceInt lastIndex = GetLastIndex(context);

            if (inline.Span.Start < lastIndex)
            {
                return;
            }

            bool isImage   = false;
            bool firstForm = false;
            int  start;

            if (inline.Parent is LinkDelimiterInline linkDelimiter)
            {
                // Second-Form = [abc][def]
                isImage = linkDelimiter.IsImage;
                start   = linkDelimiter.Span.Start;
                if (linkDelimiter.FirstChild.Span.Start < lastIndex)
                {
                    return;
                }
                inline = linkDelimiter.FirstChild;
            }
            else
            {
                // First-Form = [abc] (could be just '[abc')
                var literal = inline as LiteralInline;
                if (literal.Content.Length == 2 && literal.Content.CurrentChar == '!' && literal.Content.NextChar() == '[')
                {
                    isImage = true;
                }
                else if (literal.Content.Length != 1 || literal.Content.CurrentChar != '[')
                {
                    return;
                }
                inline    = inline.NextSibling;
                start     = inline?.Span.Start ?? 0;
                firstForm = true;
            }

            bool lineBreaks = false;

            if (!TryExtractReferencePart(ref inline, context.Source.Text, out string name, out SourceSpan nameSpan, out bool canBeUrl, ref lineBreaks))
            {
                return;
            }

            // Update the processed index to avoid parsing the same literals multiple times
            lastIndex.Value = inline.Span.End;

            if (!TryCleanPart(context, ref name, nameSpan, start, firstForm) && firstForm)
            {
                return;
            }

            if (firstForm)
            {
                context.TryAddReference(name, nameSpan, inline.Line, image: isImage, cleanUrl: canBeUrl, namedReferenceLink: true);
            }
            else
            {
                // The form is [abc][def]
                if (inline.NextSibling is null)
                {
                    context.ReportWarning(
                        WarningIDs.InvalidReferenceNesting,
                        start, lastIndex,
                        string.Empty,
                        "Invalid [] nesting");
                    return;
                }
                if (inline.NextSibling is LineBreakInline newLine)
                {
                    inline     = newLine.NextSibling;
                    lineBreaks = true;

                    if (inline.NextSibling is null)
                    {
                        return;
                    }
                }
                inline = inline.NextSibling.NextSibling;

                int targetStart = inline?.Span.Start ?? 0;
                if (!TryExtractReferencePart(ref inline, context.Source.Text, out string target, out SourceSpan targetSpan, out canBeUrl, ref lineBreaks))
                {
                    return;
                }

                SourceSpan entireSpan = new SourceSpan(start, targetSpan.End);

                // Update the processed index to avoid parsing the same literals multiple times
                lastIndex.Value = inline.Span.End;

                if (TryCleanPart(context, ref target, targetSpan, targetStart, true))
                {
                    if (target.Equals(name, StringComparison.OrdinalIgnoreCase))
                    {
                        context.ReportWarning(
                            WarningIDs.SameLabelAndTargetReference,
                            entireSpan,
                            string.Empty,
                            "You can use `[{0}]` instead of `[{0}][{1}]`",
                            name,
                            target);
                    }
                    context.TryAddReference(target, targetSpan, inline.Line, image: isImage, cleanUrl: canBeUrl, namedReferenceLink: true, label: name);
                }
            }

            if (lineBreaks)
            {
                context.ReportWarning(
                    WarningIDs.ReferenceContainsLineBreak,
                    start, lastIndex,
                    string.Empty,
                    "Ugly :'( Remove those damn line breaks from references!");
            }
        }