Skip to content

Commit

Permalink
Merge branch 'Ellested-dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
nblumhardt committed Apr 13, 2021
2 parents 886c160 + 5f48738 commit 21f53b2
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/Superpower/Parsers/Span.cs
Original file line number Diff line number Diff line change
Expand Up @@ -258,5 +258,37 @@ public static TextParser<TextSpan> MatchedBy<T>(TextParser<T> parser)
result.Remainder);
};
}

/// <summary>
/// Parse input until the <paramref name="text"/> string is present.
/// </summary>
/// <param name="text">The string to match until. The content of the <paramref name="text"/> is not included in the result.</param>
/// <returns>A parser that will match anything until the <paramref name="text"/> string argument is present in the Span.</returns>
/// <exception cref="ArgumentNullException">The <paramref name="text"/> is null.</exception>
public static TextParser<TextSpan> Except(string text)
{
if (text == null) throw new ArgumentNullException(nameof(text));

return (TextSpan input) =>
{
TextSpan remainder = input;
var matchIndex = 0;

while (remainder.Length>0)
{
var current = remainder.ConsumeChar();
remainder = current.Remainder;
if (current.Value != text[matchIndex++]) matchIndex = 0;
if (matchIndex == text.Length)
{
var foundPosition = remainder.Position.Absolute - input.Position.Absolute - text.Length;
var found = input.Skip(foundPosition);
return Result.Value(input.Until(found), found, found);
}
}

return Result.Empty<TextSpan>(input);
};
}
}
}
34 changes: 34 additions & 0 deletions test/Superpower.Tests/Parsers/SpanTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Superpower.Tests.Parsers
{
using System;
using System.Text.RegularExpressions;

public class SpanTests
Expand Down Expand Up @@ -83,5 +84,38 @@ public void RegexMatches()
var r = parser(input);
Assert.Equal("Foo", r.Value.ToStringValue());
}

[Theory]
[InlineData("STOP", "")]
[InlineData("123STOP", "123")]
[InlineData("STOP123", "")]
[InlineData("123STOP456STOP789", "123")]
public void ExceptMatchesUntilStopwordIsPresent(string text, string expected)
{
var result = Span.Except("STOP").Parse(text);
Assert.Equal(expected, result.ToStringValue());
}

[Theory]
[InlineData(null)]
public void ExceptFailsWhenArgumentIsNull(string text)
{
Assert.Throws<ArgumentNullException>(() => Span.Except(text).Parse(""));
}

[Theory]
[InlineData("Begin123STOPEnd")]
public void ExceptMatchesWhenTheInputAbsolutePositionIsNonZero(string text)
{
var test =
from begin in Span.EqualTo("Begin")
from value in Span.Except("STOP")
from stop in Span.EqualTo("STOP")
from end in Span.EqualTo("End")
select value;
var result = test.Parse(text).ToStringValue();

Assert.Equal("123", result);
}
}
}

0 comments on commit 21f53b2

Please sign in to comment.