Skip to content

Commit

Permalink
Can now use Category for specifying what most of the lambda checkers …
Browse files Browse the repository at this point in the history
…were used for.
  • Loading branch information
Entomy committed May 29, 2021
1 parent 5798e39 commit a5eec90
Show file tree
Hide file tree
Showing 9 changed files with 370 additions and 339 deletions.
163 changes: 163 additions & 0 deletions Documentation/log.txt

Large diffs are not rendered by default.

65 changes: 65 additions & 0 deletions Stringier.Patterns/CategoryChecker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Traits;

namespace Stringier.Patterns {
internal sealed class CategoryChecker : Checker {
/// <summary>
/// The category to match.
/// </summary>
[DisallowNull, NotNull]
private readonly Category Category;

/// <summary>
/// Initializes a new <see cref="CategoryChecker"/>.
/// </summary>
/// <param name="category">The category to match.</param>
public CategoryChecker([DisallowNull] Category category) => Category = category;

/// <inheritdoc/>
protected internal override void Consume(ReadOnlyMemory<Char> source, ref Int32 location, [AllowNull, MaybeNull] out Exception exception, [AllowNull] IAdd<Capture> trace) => Consume(source.Span, ref location, out exception, trace);

/// <inheritdoc/>
protected internal override unsafe void Consume([DisallowNull] Char* source, Int32 length, ref Int32 location, [AllowNull, MaybeNull] out Exception exception, [AllowNull] IAdd<Capture> trace) => Consume(new ReadOnlySpan<Char>(source, length), ref location, out exception, trace);

/// <inheritdoc/>
protected internal override Boolean IsConsumeHeader(ReadOnlySpan<Char> source, Int32 location) => Category.Contains(source[location]);

/// <inheritdoc/>
protected internal override Boolean IsNeglectHeader(ReadOnlySpan<Char> source, Int32 location) => !Category.Contains(source[location]);

/// <inheritdoc/>
protected internal override void Neglect(ReadOnlyMemory<Char> source, ref Int32 location, [AllowNull, MaybeNull] out Exception exception, [AllowNull] IAdd<Capture> trace) => Neglect(source.Span, ref location, out exception, trace);

/// <inheritdoc/>
protected internal override unsafe void Neglect([DisallowNull] Char* source, Int32 length, ref Int32 location, [AllowNull, MaybeNull] out Exception exception, [AllowNull] IAdd<Capture> trace) => Neglect(new ReadOnlySpan<Char>(source, length), ref location, out exception, trace);

private void Consume(ReadOnlySpan<Char> source, ref Int32 location, [AllowNull, MaybeNull] out Exception exception, [AllowNull] IAdd<Capture> trace) {
if (location == source.Length) {
exception = AtEnd;
trace?.Add(exception, location);
} else if (Category.Contains(source[location])) {
trace?.Add(source[location], location);
location++;
exception = null;
} else {
exception = NoMatch;
trace?.Add(exception, location);
}
}

private void Neglect(ReadOnlySpan<Char> source, ref Int32 location, [AllowNull, MaybeNull] out Exception exception, [AllowNull] IAdd<Capture> trace) {
if (location == source.Length) {
exception = AtEnd;
trace?.Add(exception, location);
} else if (!Category.Contains(source[location])) {
trace?.Add(source[location], location);
location++;
exception = null;
} else {
exception = NoMatch;
trace?.Add(exception, location);
}
}
}
}
38 changes: 23 additions & 15 deletions Stringier.Patterns/Pattern.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,6 @@ namespace Stringier.Patterns {
/// Represents a textual pattern.
/// </summary>
public abstract partial class Pattern {
/// <summary>
/// Check for the end of the line.
/// </summary>
/// <remarks>
/// This checks for various OS line endings, properly handling Windows convention, not just single UNICODE line terminators.
/// </remarks>
[NotNull, DisallowNull]
public static readonly Pattern EndOfLine = new LineEndChecker();

/// <summary>
/// Check for the end of the source.
/// </summary>
[NotNull, DisallowNull]
public static readonly Pattern EndOfSource = new SourceEndChecker();

/// <summary>
/// Predefined <see cref="Exception"/> for when the end of the source was reached before finding a match.
/// </summary>
Expand All @@ -32,11 +17,27 @@ public abstract partial class Pattern {
/// Predefined <see cref="Exception"/> for when no match could be found.
/// </summary>
protected static readonly Exception NoMatch = new InvalidOperationException("The parser failed to find a match for the pattern in the source.");

/// <summary>
/// Initialize a new <see cref="Pattern"/>.
/// </summary>
protected Pattern() { }

/// <summary>
/// Check for the end of the line.
/// </summary>
/// <remarks>
/// This checks for various OS line endings, properly handling Windows convention, not just single UNICODE line terminators.
/// </remarks>
[NotNull, DisallowNull]
public static Pattern EndOfLine { get; } = new LineEndChecker();

/// <summary>
/// Check for the end of the source.
/// </summary>
[NotNull, DisallowNull]
public static Pattern EndOfSource { get; } = new SourceEndChecker();

#region Conversions
/// <summary>
/// Converts to a <see cref="Pattern"/> matching exactly the <paramref name="char"/>.
Expand Down Expand Up @@ -135,6 +136,13 @@ protected Pattern() { }
/// <param name="capture">A <see cref="ValueTuple{T1, T2}"/> of <see cref="Patterns.Capture"/> to match and <see cref="Case"/> comparison.</param>
[return: NotNull]
public static implicit operator Pattern((Capture, Case) capture) => new CaptureLiteral(capture.Item1, capture.Item2);

/// <summary>
/// Converts to a <see cref="Pattern"/> matching exactly the <paramref name="category"/>.
/// </summary>
/// <param name="category">The <see cref="Category"/> to match.</param>
[return: MaybeNull, NotNullIfNotNull("category")]
public static implicit operator Pattern([AllowNull] Category category) => category is not null ? new CategoryChecker(category) : null;
#endregion

#region Parse(Source, ref Int32)
Expand Down
36 changes: 36 additions & 0 deletions Tests.CSharp/Pattern_Tests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Text;
using Stringier;
using Stringier.Patterns;
using static Stringier.Patterns.Pattern;
using Xunit;
Expand Down Expand Up @@ -38,6 +39,41 @@ public void Alternator_String(String expected, String first, String second, Stri
Assert.Equal(expected.Length, i);
}

[Theory]
[InlineData("A", "A")]
[InlineData("A", "Abc")]
[InlineData("A", "ABC")]
public unsafe void CategoryChecker_Pointer(String expected, String source) {
Pattern ptn = Category.UppercaseLetter;
Int32 i = 0;
Capture? capture = null;
fixed (Char* src = source) {
capture = ptn.Parse(source, ref i);
Assert.Equal(expected, capture);
}
Assert.Equal(expected.Length, i);
}

[Theory]
[InlineData("A", "A", false)]
[InlineData("A", "Abc", false)]
[InlineData("A", "ABC", false)]
[InlineData("", "a", true)]
[InlineData("", "abc", true)]
public void CategoryChecker_String(String expected, String source, Boolean throws) {
Pattern ptn = Category.UppercaseLetter;
Int32 i = 0;
Capture? capture = null;
if (!throws) {
capture = ptn.Parse(source, ref i);
Assert.Equal(expected, capture);
} else {
_ = Assert.ThrowsAny<Exception>(() => capture = ptn.Parse(source, ref i));
Assert.Null(capture);
}
Assert.Equal(expected.Length, i);
}

[Theory]
[InlineData("one", "one", "two", "three", "one")]
[InlineData("two", "one", "two", "three", "two")]
Expand Down
2 changes: 1 addition & 1 deletion docs/api/Stringier.Patterns.Bias.html
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@

<h1 id="Stringier_Patterns_Bias" data-uid="Stringier.Patterns.Bias" class="text-break">Enum Bias
</h1>
<div class="markdown level0 summary"><p>Word letter bias, used by <span class="xref">Stringier.Patterns.WordChecker</span>.</p>
<div class="markdown level0 summary"><p>Word letter bias, used by <see cref="!:WordChecker"></see>.</p>
</div>
<div class="markdown level0 conceptual"></div>
<h6><strong>Namespace</strong>: <a class="xref" href="Stringier.Patterns.html">Stringier.Patterns</a></h6>
Expand Down
Loading

0 comments on commit a5eec90

Please sign in to comment.