示例#1
0
        public void Source_NextPhrase(
            string text,
            int offSet,
            SourceNextPhraseDelegate predicate,
            string expectedOutput,
            int expectedCursorPosition)
        {
            var source = new SourceText(text.AsMemory(), offSet);
            var result = source.NextPhrase(predicate);

            Assert.AreEqual(expectedOutput, result.ToString());
            Assert.AreEqual(expectedCursorPosition, source.Cursor);
        }
        /// <summary>
        /// Begins processing characters, building a span of text until the predicate condition is not met
        /// at which point the characters are returned and the cursor advanced to the character that did not meet the condition.
        /// The predicate will recieve the entire set of characters in the phrase on each iteration. The predicate should inspect
        /// the phrase then return true when it matches an expected condition. This will cause the phraser to
        /// cease processing and return the phrase that was created while advancing the cursor.
        /// </summary>
        /// <param name="predicate">The predicate which recieves the entire set of characters to be returned so far.</param>
        /// <returns>System.ReadOnlySpan&lt;System.Char&gt;.</returns>
        public ReadOnlySpan <char> NextPhrase(SourceNextPhraseDelegate predicate)
        {
            var length       = 1;
            var isProcessing = true;

            while (isProcessing && this.Cursor + length <= _sourceText.Length)
            {
                var result = predicate(this.Slice(this.Cursor, length));
                switch (result)
                {
                // keep adding characters to the phrase
                case NextPhraseResult.Continue:
                    break;

                // we're done, exit out and extract the string
                case NextPhraseResult.Complete:
                    isProcessing = false;
                    break;

                // we're done but the previous iteration was correct
                case NextPhraseResult.CompleteOnPrevious:
                    length       = length >= 1 ? length - 1 : 0;
                    isProcessing = false;
                    break;

                default:
                    throw new ArgumentOutOfRangeException($"{typeof(NextPhraseResult).Name} value not supported ('{result}')");
                }

                length += isProcessing ? 1 : 0;
            }

            // if while loop was exited because the end of the text is
            // reached, length will be one beyond where it should be
            length += isProcessing ? -1 : 0;

            var slice = this.Slice(this.Cursor, length);

            this.Cursor += length;
            return(slice);
        }