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<System.Char>.</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); }