Skip to content

Commit

Permalink
Fix OneOf parsers merge loosing SkipWhiteSpace
Browse files Browse the repository at this point in the history
Fixes #190
  • Loading branch information
sebastienros committed Jan 6, 2025
1 parent bc25c2e commit 938e61d
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/Parlot/Fluent/OneOf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public sealed class OneOf<T> : Parser<T>, ISeekable /*, ICompilable*/
public OneOf(Parser<T>[] parsers)
{
Parsers = parsers ?? throw new ArgumentNullException(nameof(parsers));
OriginalParsers = parsers;

// We can't build a lookup table if there is only one parser
if (Parsers.Count <= 1)
Expand Down Expand Up @@ -151,6 +152,11 @@ public OneOf(Parser<T>[] parsers)

public bool SkipWhitespace { get; }

/// <summary>
/// Gets the parsers before they get SkipWhitespace removed.
/// </summary>
public IReadOnlyList<Parser<T>> OriginalParsers { get; }

public IReadOnlyList<Parser<T>> Parsers { get; }

public override bool Parse(ParseContext context, ref ParseResult<T> result)
Expand Down
4 changes: 2 additions & 2 deletions src/Parlot/Fluent/Parsers.OneOf.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Parlot.Fluent;
namespace Parlot.Fluent;

// We don't care about the performance of these helpers since they are called only once
// during the parser tree creation
Expand All @@ -16,7 +16,7 @@ public static Parser<T> Or<T>(this Parser<T> parser, Parser<T> or)
if (parser is OneOf<T> oneOf)
{
// Return a single OneOf instance with this new one
return new OneOf<T>([.. oneOf.Parsers, or]);
return new OneOf<T>([.. oneOf.OriginalParsers, or]);
}
else
{
Expand Down
16 changes: 16 additions & 0 deletions test/Parlot.Tests/RewriteTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Parlot.Fluent;
using Parlot.Rewriting;
using System;
using System.Collections.Generic;
using System.Reflection;
using Xunit;
Expand Down Expand Up @@ -280,4 +281,19 @@ public void OneOfShouldFindNonSeekableWithSpace(bool compiled, bool skipWhiteSpa
Assert.Equal("c", p.Parse(" b"));
Assert.Equal("c", p.Parse(" c"));
}

[Theory]
[InlineData(" a ")]
[InlineData(" b ")]
[InlineData(" c ")]
public void MergingOneOfShouldRestoreSkipWhiteSpace(string input)
{
// The first two parsers are evaluated in a OneOf with SkipWhiteSpace stripped off. The second creation should
// restore these SkipWhiteSpace parsers for the lookup table to be re-created correctly.

var p = Terms.Char('a').Or(Terms.Char('b')).Or(Terms.Char('c'));

var result1 = p.TryParse(input, out _);
Assert.True(result1);
}
}

0 comments on commit 938e61d

Please # to comment.