示例#1
0
        /// <summary>
        /// Lexes and parses the specified string.
        /// </summary>
        /// <param name="input">The <see cref="StringBuilder"/> to parse.</param>
        /// <param name="output">The parsed token stream.</param>
        /// <param name="options">A set of <see cref="TextParserOptions"/> values that specify how the text should be parsed.</param>
        public void Parse(StringBuilder input, TextParserTokenStream output, TextParserOptions options = TextParserOptions.None)
        {
            Contract.Require(input, nameof(input));
            Contract.Require(output, nameof(output));

            output.Clear();
            Parse(new StringBuilderSource(input), output, 0, input.Length, options);
        }
示例#2
0
        /// <summary>
        /// Lexes and parses the specified string.
        /// </summary>
        private void Parse <TSource>(TSource input, TextParserTokenStream output, Int32 index, Int32 count, TextParserOptions options = TextParserOptions.None)
            where TSource : ISegmentableStringSource
        {
            var bound = index + count;

            while (index < bound)
            {
                if (IsStartOfNewline(input, index))
                {
                    output.Add(ConsumeNewlineToken(input, options, ref index));
                    continue;
                }
                if (IsStartOfNonBreakingSpace(input, index))
                {
                    output.Add(ConsumeNonBreakingSpaceToken(input, options, ref index));
                    continue;
                }
                if (IsStartOfBreakingSpace(input, index))
                {
                    output.Add(ConsumeBreakingSpaceToken(input, options, ref index));
                    continue;
                }
                if (IsEscapedPipe(input, index, options))
                {
                    output.Add(ConsumeEscapedPipeToken(input, options, ref index));
                    continue;
                }
                if (IsStartOfCommand(input, index))
                {
                    output.Add(ConsumeCommandToken(input, options, ref index));
                    continue;
                }
                if (IsStartOfWord(input, index))
                {
                    output.Add(ConsumeWordToken(input, options, ref index));
                    continue;
                }
                index++;
            }

            output.SourceText    = input.CreateStringSegment();
            output.ParserOptions = options;
        }
示例#3
0
        /// <summary>
        /// Finds the index of the first and last tokens which are potentially affected by changes in the specified substring of the source text.
        /// </summary>
        private void FindTokensInfluencedBySubstring(TextParserTokenStream result, Int32 start, Int32 count, out Int32 ix1, out Int32 ix2)
        {
            var position = 0;
            var end      = start + count;

            var ix1Found = false;
            var ix2Found = false;

            ix1 = 0;
            ix2 = result.Count - 1;

            for (int i = 0; i < result.Count; i++)
            {
                var token      = result[i];
                var tokenStart = token.SourceOffset;
                var tokenEnd   = tokenStart + token.SourceLength;

                if (!ix1Found && (start >= tokenStart && start <= tokenEnd))
                {
                    ix1      = i;
                    ix1Found = true;
                }

                if (!ix2Found && (end >= tokenStart && end < tokenEnd))
                {
                    ix2      = i;
                    ix2Found = true;
                }

                if (ix1Found && ix2Found)
                {
                    break;
                }

                position += token.SourceLength;
            }
        }
示例#4
0
        /// <summary>
        /// Incrementally lexes and parses the specified string.
        /// </summary>
        /// <param name="input">The <see cref="StringBuilder"/> to parse.</param>
        /// <param name="start">The index of the first character that was changed.</param>
        /// <param name="count">The number of characters that were changed.</param>
        /// <param name="result">The parsed token stream.</param>
        /// <param name="options">A set of <see cref="TextParserOptions"/> values that specify how the text should be parsed.</param>
        /// <returns>An <see cref="IncrementalResult"/> structure that represents the result of the operation.</returns>
        /// <remarks>Incremental parsing provides a performance benefit when relatively small changes are being made
        /// to a large source text. Only tokens which are potentially influenced by changes within the specified substring
        /// of the source text are re-parsed by this operation.</remarks>
        public IncrementalResult ParseIncremental(StringBuilder input, Int32 start, Int32 count, TextParserTokenStream result, TextParserOptions options = TextParserOptions.None)
        {
            Contract.Require(input, nameof(input));
            Contract.Require(result, nameof(result));
            Contract.EnsureRange(start >= 0, nameof(start));
            Contract.EnsureRange(count >= 0 && start + count <= input.Length, nameof(count));

            return(ParseIncremental(new StringBuilderSource(input), start, count, result, options));
        }
示例#5
0
        /// <summary>
        /// Incrementally lexes and parses the specified string.
        /// </summary>
        private IncrementalResult ParseIncremental <TSource>(TSource input, Int32 start, Int32 count, TextParserTokenStream output, TextParserOptions options = TextParserOptions.None)
            where TSource : ISegmentableStringSource
        {
            var inputLengthOld  = output.SourceText.Length;
            var inputLengthNew  = input.Length;
            var inputLengthDiff = inputLengthNew - inputLengthOld;

            Int32 ix1, ix2;

            FindTokensInfluencedBySubstring(output, start, count - inputLengthDiff, out ix1, out ix2);

            var token1 = output[ix1];
            var token2 = output[ix2];

            var invalidatedTokenCount = 1 + (ix2 - ix1);

            output.RemoveRange(ix1, invalidatedTokenCount);

            var lexStart     = token1.SourceOffset;
            var lexCount     = inputLengthDiff + (token2.SourceOffset + token2.SourceLength) - lexStart;
            var parserBuffer = incrementalParserBuffer.Value;

            Parse(input, parserBuffer, lexStart, lexCount);

            output.SourceText = input.CreateStringSegment();
            output.InsertRange(ix1, parserBuffer);

            var affectedOffset = ix1;
            var affectedCount  = parserBuffer.Count;

            parserBuffer.Clear();

            return(new IncrementalResult(affectedOffset, affectedCount));
        }