Example #1
0
            public override TextParserResult GetSpans(string s, IComparer <LinePositionSpanInfo> comparer = null)
            {
                StringBuilder sb = StringBuilderCache.GetInstance(s.Length - TokensLength);

                var startPending = false;
                LinePositionInfo            start = default;
                Stack <LinePositionInfo>    stack = null;
                List <LinePositionSpanInfo> spans = null;

                int lastPos = 0;

                int line   = 0;
                int column = 0;

                int length = s.Length;

                int i = 0;

                while (i < length)
                {
                    switch (s[i])
                    {
                    case '\r':
                    {
                        if (PeekNextChar() == '\n')
                        {
                            i++;
                        }

                        line++;
                        column = 0;
                        i++;
                        continue;
                    }

                    case '\n':
                    {
                        line++;
                        column = 0;
                        i++;
                        continue;
                    }

                    case '[':
                    {
                        char nextChar = PeekNextChar();
                        if (nextChar == '|')
                        {
                            sb.Append(s, lastPos, i - lastPos);

                            var start2 = new LinePositionInfo(sb.Length, line, column);

                            if (stack != null)
                            {
                                stack.Push(start2);
                            }
                            else if (!startPending)
                            {
                                start        = start2;
                                startPending = true;
                            }
                            else
                            {
                                stack = new Stack <LinePositionInfo>();
                                stack.Push(start);
                                stack.Push(start2);
                                startPending = false;
                            }

                            i      += 2;
                            lastPos = i;
                            continue;
                        }
                        else if (nextChar == '[' &&
                                 PeekChar(2) == '|' &&
                                 PeekChar(3) == ']')
                        {
                            i++;
                            column++;
                            CloseSpan();
                            i      += 3;
                            lastPos = i;
                            continue;
                        }

                        break;
                    }

                    case '|':
                    {
                        if (PeekNextChar() == ']')
                        {
                            CloseSpan();
                            i      += 2;
                            lastPos = i;
                            continue;
                        }

                        break;
                    }
                    }

                    column++;
                    i++;
                }

                if (startPending ||
                    stack?.Count > 0)
                {
                    throw new InvalidOperationException();
                }

                sb.Append(s, lastPos, s.Length - lastPos);

                spans?.Sort(comparer ?? LinePositionSpanInfoComparer.Index);

                return(new TextParserResult(
                           StringBuilderCache.GetStringAndFree(sb),
                           spans?.ToImmutableArray() ?? ImmutableArray <LinePositionSpanInfo> .Empty));

                char PeekNextChar()
                {
                    return(PeekChar(1));
                }

                char PeekChar(int offset)
                {
                    return((i + offset >= s.Length) ? '\0' : s[i + offset]);
                }

                void CloseSpan()
                {
                    if (stack != null)
                    {
                        start = stack.Pop();
                    }
                    else if (startPending)
                    {
                        startPending = false;
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }

                    var end = new LinePositionInfo(sb.Length + i - lastPos, line, column);

                    var span = new LinePositionSpanInfo(start, end);

                    (spans ??= new List <LinePositionSpanInfo>()).Add(span);

                    sb.Append(s, lastPos, i - lastPos);
                }
            }
 public override bool Equals(LinePositionSpanInfo x, LinePositionSpanInfo y)
 {
     return(x.Start.Index == y.Start.Index);
 }
 public override int Compare(LinePositionSpanInfo x, LinePositionSpanInfo y)
 {
     return(x.Start.Index.CompareTo(y.Start.Index));
 }
 public override int Compare(LinePositionSpanInfo x, LinePositionSpanInfo y)
 {
     return(-base.Compare(x, y));
 }
 public override int GetHashCode(LinePositionSpanInfo obj)
 {
     return(obj.Start.Index.GetHashCode());
 }
Example #6
0
        public static (string, ImmutableArray <TextSpan>) FindSpansAndRemove(string text)
        {
            StringBuilder sb = StringBuilderCache.GetInstance(text.Length);

            var startPending = false;
            LinePositionInfo            start = default;
            Stack <LinePositionInfo>    stack = null;
            List <LinePositionSpanInfo> spans = null;

            int lastPos = 0;

            int line   = 0;
            int column = 0;

            int length = text.Length;

            int i = 0;

            while (i < length)
            {
                switch (text[i])
                {
                case '\r':
                {
                    if (PeekNextChar() == '\n')
                    {
                        i++;
                    }

                    line++;
                    column = 0;
                    i++;
                    continue;
                }

                case '\n':
                {
                    line++;
                    column = 0;
                    i++;
                    continue;
                }

                case '[':
                {
                    char nextChar = PeekNextChar();
                    if (nextChar == '|')
                    {
                        sb.Append(text, lastPos, i - lastPos);

                        var start2 = new LinePositionInfo(sb.Length, line, column);

                        if (stack != null)
                        {
                            stack.Push(start2);
                        }
                        else if (!startPending)
                        {
                            start        = start2;
                            startPending = true;
                        }
                        else
                        {
                            stack = new Stack <LinePositionInfo>();
                            stack.Push(start);
                            stack.Push(start2);
                            startPending = false;
                        }

                        i      += 2;
                        lastPos = i;
                        continue;
                    }
                    else if (nextChar == '[' &&
                             PeekChar(2) == '|' &&
                             PeekChar(3) == ']')
                    {
                        i++;
                        column++;
                        CloseSpan();
                        i      += 3;
                        lastPos = i;
                        continue;
                    }

                    break;
                }

                case '|':
                {
                    if (PeekNextChar() == ']')
                    {
                        CloseSpan();
                        i      += 2;
                        lastPos = i;
                        continue;
                    }

                    break;
                }
                }

                column++;
                i++;
            }

            if (startPending ||
                stack?.Count > 0)
            {
                throw new InvalidOperationException("Text span is invalid.");
            }

            sb.Append(text, lastPos, text.Length - lastPos);

            spans?.Sort(LinePositionSpanInfoComparer.Index);

            return(
                StringBuilderCache.GetStringAndFree(sb),
                spans?.Select(f => f.Span).ToImmutableArray() ?? ImmutableArray <TextSpan> .Empty);

            char PeekNextChar()
            {
                return(PeekChar(1));
            }

            char PeekChar(int offset)
            {
                return((i + offset >= text.Length) ? '\0' : text[i + offset]);
            }

            void CloseSpan()
            {
                if (stack != null)
                {
                    start = stack.Pop();
                }
                else if (startPending)
                {
                    startPending = false;
                }
                else
                {
                    throw new InvalidOperationException("Text span is invalid.");
                }

                var end = new LinePositionInfo(sb.Length + i - lastPos, line, column);

                var span = new LinePositionSpanInfo(start, end);

                (spans ??= new List <LinePositionSpanInfo>()).Add(span);

                sb.Append(text, lastPos, i - lastPos);
            }
        }