Пример #1
0
        public Result <TextSpan, TextSpan> Parse(ParseText text, TextSpan span)
        {
            if (span.IsEmpty)
            {
                return(new Unmatched <TextSpan, TextSpan>(span));
            }

            if (span.Length == 2 && text[span.Start] == '"' && text[span.Start + 1] == '"')
            {
                return(new Success <TextSpan, TextSpan>(new TextSpan(span.Start, 2), TextSpan.FromBounds(span.Start + 2, span.End)));
            }

            var index = text.IndexOf(_settings.EscapeCharacter, span);

            if (index < 0)
            {
                return(new Success <TextSpan, TextSpan>(span, new TextSpan(span.End, 0)));
            }

            var builder = new StringBuilder(span.Length);

            int offset = span.Start;

            while ((index >= 0) && offset < span.End)
            {
                text.AppendTo(builder, TextSpan.FromBounds(offset, index - offset));

                offset = ParseEscapeSequence(builder, text, TextSpan.FromBounds(index, span.End));

                index = text.IndexOf(_settings.EscapeCharacter, TextSpan.FromBounds(offset, span.End));
            }

            if (offset < span.End)
            {
                text.AppendTo(builder, TextSpan.FromBounds(offset, span.End));
                offset = span.End;
            }

            return(new Success <TextSpan, TextSpan>(TextSpan.FromBounds(span.Start, offset), TextSpan.FromBounds(offset, span.End)));
        }
Пример #2
0
        int ParseEscapeSequence(StringBuilder builder, ParseText body, TextSpan span)
        {
            if (span.Length < 3)
            {
                body.AppendTo(builder, span);

                return(span.End);
            }

            char key     = body[span.Start + 1];
            char closing = body[span.Start + 2];

            if (closing == _settings.EscapeCharacter)
            {
                switch (key)
                {
                case 'F':
                    builder.Append(_settings.FieldSeparator);
                    break;

                case 'S':
                    builder.Append(_settings.ComponentSeparator);
                    break;

                case 'T':
                    builder.Append(_settings.SubComponentSeparator);
                    break;

                case 'R':
                    builder.Append(_settings.RepetitionSeparator);
                    break;

                case 'E':
                    builder.Append(_settings.EscapeCharacter);
                    break;

                case 'X':     // if we get empty hex data, skip it as well
                case 'Z':     // locally defined we pass through
                    break;

                case 'H':     // we don't translate highlighting, so just skip it
                case 'N':
                default:
                    body.AppendTo(builder, new TextSpan(span.Start, 3));
                    break;
                }

                return(span.Start + 3);
            }

            // while we could strip this out, it seems like there would be no other way to get
            // access to this data, so I think it makes sense to leave it in the text and let
            // the application deal with it since it may want to use it.
            if (key == 'X' || key == 'Z' || key == '.') // hexadecimal data or locally defined data
            {
                int end = body.IndexOf(_settings.EscapeCharacter, new TextSpan(span.Start + 2, span.Length - 2));
                if (end > 0)
                {
                    body.AppendTo(builder, TextSpan.FromBounds(span.Start, end + 1));

                    return(end + 1);
                }
            }

            body.AppendTo(builder, new TextSpan(span.Start, 1));
            return(span.Start + 1);
        }