Skip to content

Commit

Permalink
Fix sequence overload conflicts
Browse files Browse the repository at this point in the history
Fixes #108

Sequences would assume that a Parser<T1, T2> would be another sequence while it can be OneOf((T1, T2)). Then the copmilation would not be able to match the number or actual unique parser.
  • Loading branch information
sebastienros committed May 19, 2024
1 parent ebe4c46 commit 9e0d3ce
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 31 deletions.
24 changes: 19 additions & 5 deletions src/Parlot/Fluent/OneOf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,21 @@ namespace Parlot.Fluent
/// We then return the actual result of each parser.
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class OneOf<T> : Parser<T>, ICompilable
public sealed class OneOf<T> : Parser<T>, ICompilable, ISeekable
{
internal readonly Parser<T>[] _parsers;
internal readonly FrozenDictionary<char, List<Parser<T>>> _lookupTable;
internal readonly bool _skipWhiteSpace;

public OneOf(Parser<T>[] parsers)
{
_parsers = parsers ?? throw new ArgumentNullException(nameof(parsers));

// We can't build a lookup table if there is only one parser
if (_parsers.Length <= 1)
{
return;
}

// If all parsers are seekable we can build a lookup table
if (_parsers.All(x => x is ISeekable seekable && seekable.CanSeek))
{
Expand Down Expand Up @@ -53,7 +58,7 @@ public OneOf(Parser<T>[] parsers)
else if (_parsers.All(x => x is ISeekable seekable && seekable.SkipWhitespace))
{
// All parsers can start with white spaces
_skipWhiteSpace = true;
SkipWhitespace = true;
}
else if (_parsers.Any(x => x is ISeekable seekable && seekable.SkipWhitespace))
{
Expand All @@ -65,10 +70,19 @@ public OneOf(Parser<T>[] parsers)
if (lookupTable != null)
{
_lookupTable = lookupTable.ToFrozenDictionary();

CanSeek = true;
ExpectedChars = _lookupTable.Keys.ToArray();
}
}
}

public bool CanSeek { get; }

public char[] ExpectedChars { get; } = [];

public bool SkipWhitespace { get; }

public Parser<T>[] Parsers => _parsers;

public override bool Parse(ParseContext context, ref ParseResult<T> result)
Expand All @@ -79,7 +93,7 @@ public override bool Parse(ParseContext context, ref ParseResult<T> result)

if (_lookupTable != null)
{
if (_skipWhiteSpace)
if (SkipWhitespace)
{
var start = context.Scanner.Cursor.Position;

Expand Down Expand Up @@ -201,7 +215,7 @@ public CompilationResult Compile(CompilationContext context)
cases
);

if (_skipWhiteSpace)
if (SkipWhitespace)
{
var start = context.DeclarePositionVariable(result);

Expand Down
26 changes: 17 additions & 9 deletions src/Parlot/Fluent/Parsers.And.cs
Original file line number Diff line number Diff line change
@@ -1,37 +1,45 @@
using System;

namespace Parlot.Fluent
namespace Parlot.Fluent
{
public static partial class Parsers
{
/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively.
/// </summary>
public static Parser<ValueTuple<T1, T2>> And<T1, T2>(this Parser<T1> parser, Parser<T2> and) => new Sequence<T1, T2>(parser, and);
public static Sequence<T1, T2> And<T1, T2>(this Parser<T1> parser, Parser<T2> and) => new Sequence<T1, T2>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3>> And<T1, T2, T3>(this Parser<ValueTuple<T1, T2>> parser, Parser<T3> and) => new Sequence<T1, T2, T3>(parser, and);
public static Sequence<T1, T2, T3> And<T1, T2, T3>(this Sequence<T1, T2> parser, Parser<T3> and) => new Sequence<T1, T2, T3>(parser, and);
public static Sequence<T1, T3> And<T1, T2, T3>(this SequenceAndSkip<T1, T2> parser, Parser<T3> and) => new Sequence<T1, T3>(parser, and);
public static Sequence<T2, T3> And<T1, T2, T3>(this SequenceSkipAnd<T1, T2> parser, Parser<T3> and) => new Sequence<T2, T3>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3, T4>> And<T1, T2, T3, T4>(this Parser<ValueTuple<T1, T2, T3>> parser, Parser<T4> and) => new Sequence<T1, T2, T3, T4>(parser, and);
public static Sequence<T1, T2, T3, T4> And<T1, T2, T3, T4>(this Sequence<T1, T2, T3> parser, Parser<T4> and) => new Sequence<T1, T2, T3, T4>(parser, and);
public static Sequence<T1, T2, T4> And<T1, T2, T3, T4>(this SequenceAndSkip<T1, T2, T3> parser, Parser<T4> and) => new Sequence<T1, T2, T4>(parser, and);
public static Sequence<T1, T3, T4> And<T1, T2, T3, T4>(this SequenceSkipAnd<T1, T2, T3> parser, Parser<T4> and) => new Sequence<T1, T3, T4>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3, T4, T5>> And<T1, T2, T3, T4, T5>(this Parser<ValueTuple<T1, T2, T3, T4>> parser, Parser<T5> and) => new Sequence<T1, T2, T3, T4, T5>(parser, and);
public static Sequence<T1, T2, T3, T4, T5> And<T1, T2, T3, T4, T5>(this Sequence<T1, T2, T3, T4> parser, Parser<T5> and) => new Sequence<T1, T2, T3, T4, T5>(parser, and);
public static Sequence<T1, T2, T3, T5> And<T1, T2, T3, T4, T5>(this SequenceAndSkip<T1, T2, T3, T4> parser, Parser<T5> and) => new Sequence<T1, T2, T3, T5>(parser, and);
public static Sequence<T1, T2, T4, T5> And<T1, T2, T3, T4, T5>(this SequenceSkipAnd<T1, T2, T3, T4> parser, Parser<T5> and) => new Sequence<T1, T2, T4, T5>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3, T4, T5, T6>> And<T1, T2, T3, T4, T5, T6>(this Parser<ValueTuple<T1, T2, T3, T4, T5>> parser, Parser<T6> and) => new Sequence<T1, T2, T3, T4, T5, T6>(parser, and);
public static Sequence<T1, T2, T3, T4, T5, T6> And<T1, T2, T3, T4, T5, T6>(this Sequence<T1, T2, T3, T4, T5> parser, Parser<T6> and) => new Sequence<T1, T2, T3, T4, T5, T6>(parser, and);
public static Sequence<T1, T2, T3, T4, T6> And<T1, T2, T3, T4, T5, T6>(this SequenceAndSkip<T1, T2, T3, T4, T5> parser, Parser<T6> and) => new Sequence<T1, T2, T3, T4, T6>(parser, and);
public static Sequence<T1, T2, T3, T5, T6> And<T1, T2, T3, T4, T5, T6>(this SequenceSkipAnd<T1, T2, T3, T4, T5> parser, Parser<T6> and) => new Sequence<T1, T2, T3, T5, T6>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3, T4, T5, T6, T7>> And<T1, T2, T3, T4, T5, T6, T7>(this Parser<ValueTuple<T1, T2, T3, T4, T5, T6>> parser, Parser<T7> and) => new Sequence<T1, T2, T3, T4, T5, T6, T7>(parser, and);
public static Sequence<T1, T2, T3, T4, T5, T6, T7> And<T1, T2, T3, T4, T5, T6, T7>(this Sequence<T1, T2, T3, T4, T5, T6> parser, Parser<T7> and) => new Sequence<T1, T2, T3, T4, T5, T6, T7>(parser, and);
public static Sequence<T1, T2, T3, T4, T5, T7> And<T1, T2, T3, T4, T5, T6, T7>(this SequenceAndSkip<T1, T2, T3, T4, T5, T6> parser, Parser<T7> and) => new Sequence<T1, T2, T3, T4, T5, T7>(parser, and);
public static Sequence<T1, T2, T3, T4, T6, T7> And<T1, T2, T3, T4, T5, T6, T7>(this SequenceSkipAnd<T1, T2, T3, T4, T5, T6> parser, Parser<T7> and) => new Sequence<T1, T2, T3, T4, T6, T7>(parser, and);
}
}
26 changes: 19 additions & 7 deletions src/Parlot/Fluent/Parsers.AndSkip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,48 @@ public static partial class Parsers
/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<T1> AndSkip<T1, T2>(this Parser<T1> parser, Parser<T2> and) => new SequenceAndSkip<T1, T2>(parser, and);
public static SequenceAndSkip<T1, T2> AndSkip<T1, T2>(this Parser<T1> parser, Parser<T2> and) => new SequenceAndSkip<T1, T2>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<ValueTuple<T1, T2>> AndSkip<T1, T2, T3>(this Parser<ValueTuple<T1, T2>> parser, Parser<T3> and) => new SequenceAndSkip<T1, T2, T3>(parser, and);
public static SequenceAndSkip<T1, T2, T3> AndSkip<T1, T2, T3>(this Sequence<T1, T2> parser, Parser<T3> and) => new SequenceAndSkip<T1, T2, T3>(parser, and);
public static SequenceAndSkip<T1, T3> AndSkip<T1, T2, T3>(this SequenceAndSkip<T1, T2> parser, Parser<T3> and) => new SequenceAndSkip<T1, T3>(parser, and);
public static SequenceAndSkip<T2, T3> AndSkip<T1, T2, T3>(this SequenceSkipAnd<T1, T2> parser, Parser<T3> and) => new SequenceAndSkip<T2, T3>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3>> AndSkip<T1, T2, T3, T4>(this Parser<ValueTuple<T1, T2, T3>> parser, Parser<T4> and) => new SequenceAndSkip<T1, T2, T3, T4>(parser, and);
public static SequenceAndSkip<T1, T2, T3, T4> AndSkip<T1, T2, T3, T4>(this Sequence<T1, T2, T3> parser, Parser<T4> and) => new SequenceAndSkip<T1, T2, T3, T4>(parser, and);
public static SequenceAndSkip<T1, T2, T4> AndSkip<T1, T2, T3, T4>(this SequenceAndSkip<T1, T2, T3> parser, Parser<T4> and) => new SequenceAndSkip<T1, T2, T4>(parser, and);
public static SequenceAndSkip<T1, T3, T4> AndSkip<T1, T2, T3, T4>(this SequenceSkipAnd<T1, T2, T3> parser, Parser<T4> and) => new SequenceAndSkip<T1, T3, T4>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3, T4>> AndSkip<T1, T2, T3, T4, T5>(this Parser<ValueTuple<T1, T2, T3, T4>> parser, Parser<T5> and) => new SequenceAndSkip<T1, T2, T3, T4, T5>(parser, and);
public static SequenceAndSkip<T1, T2, T3, T4, T5> AndSkip<T1, T2, T3, T4, T5>(this Sequence<T1, T2, T3, T4> parser, Parser<T5> and) => new SequenceAndSkip<T1, T2, T3, T4, T5>(parser, and);
public static SequenceAndSkip<T1, T2, T3, T5> AndSkip<T1, T2, T3, T4, T5>(this SequenceAndSkip<T1, T2, T3, T4> parser, Parser<T5> and) => new SequenceAndSkip<T1, T2, T3, T5>(parser, and);
public static SequenceAndSkip<T1, T2, T4, T5> AndSkip<T1, T2, T3, T4, T5>(this SequenceSkipAnd<T1, T2, T3, T4> parser, Parser<T5> and) => new SequenceAndSkip<T1, T2, T4, T5>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3, T4, T5>> AndSkip<T1, T2, T3, T4, T5, T6>(this Parser<ValueTuple<T1, T2, T3, T4, T5>> parser, Parser<T6> and) => new SequenceAndSkip<T1, T2, T3, T4, T5, T6>(parser, and);
public static SequenceAndSkip<T1, T2, T3, T4, T5, T6> AndSkip<T1, T2, T3, T4, T5, T6>(this Sequence<T1, T2, T3, T4, T5> parser, Parser<T6> and) => new SequenceAndSkip<T1, T2, T3, T4, T5, T6>(parser, and);
public static SequenceAndSkip<T1, T2, T3, T4, T6> AndSkip<T1, T2, T3, T4, T5, T6>(this SequenceAndSkip<T1, T2, T3, T4, T5> parser, Parser<T6> and) => new SequenceAndSkip<T1, T2, T3, T4, T6>(parser, and);
public static SequenceAndSkip<T1, T2, T3, T5, T6> AndSkip<T1, T2, T3, T4, T5, T6>(this SequenceSkipAnd<T1, T2, T3, T4, T5> parser, Parser<T6> and) => new SequenceAndSkip<T1, T2, T3, T5, T6>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3, T4, T5, T6>> AndSkip<T1, T2, T3, T4, T5, T6, T7>(this Parser<ValueTuple<T1, T2, T3, T4, T5, T6>> parser, Parser<T7> and) => new SequenceAndSkip<T1, T2, T3, T4, T5, T6, T7>(parser, and);
public static SequenceAndSkip<T1, T2, T3, T4, T5, T6, T7> AndSkip<T1, T2, T3, T4, T5, T6, T7>(this Sequence<T1, T2, T3, T4, T5, T6> parser, Parser<T7> and) => new SequenceAndSkip<T1, T2, T3, T4, T5, T6, T7>(parser, and);
public static SequenceAndSkip<T1, T2, T3, T4, T5, T7> AndSkip<T1, T2, T3, T4, T5, T6, T7>(this SequenceAndSkip<T1, T2, T3, T4, T5, T6> parser, Parser<T7> and) => new SequenceAndSkip<T1, T2, T3, T4, T5, T7>(parser, and);
public static SequenceAndSkip<T1, T2, T3, T4, T6, T7> AndSkip<T1, T2, T3, T4, T5, T6, T7>(this SequenceSkipAnd<T1, T2, T3, T4, T5, T6> parser, Parser<T7> and) => new SequenceAndSkip<T1, T2, T3, T4, T6, T7>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3, T4, T5, T6, T7>> AndSkip<T1, T2, T3, T4, T5, T6, T7, T8>(this Parser<ValueTuple<T1, T2, T3, T4, T5, T6, T7>> parser, Parser<T8> and) => new SequenceAndSkip<T1, T2, T3, T4, T5, T6, T7, T8>(parser, and);
public static SequenceAndSkip<T1, T2, T3, T4, T5, T6, T7, T8> AndSkip<T1, T2, T3, T4, T5, T6, T7, T8>(this Sequence<T1, T2, T3, T4, T5, T6, T7> parser, Parser<T8> and) => new SequenceAndSkip<T1, T2, T3, T4, T5, T6, T7, T8>(parser, and);
public static SequenceAndSkip<T1, T2, T3, T4, T5, T6, T8> AndSkip<T1, T2, T3, T4, T5, T6, T7, T8>(this SequenceAndSkip<T1, T2, T3, T4, T5, T6, T7> parser, Parser<T8> and) => new SequenceAndSkip<T1, T2, T3, T4, T5, T6, T8>(parser, and);
public static SequenceAndSkip<T1, T2, T3, T4, T5, T7, T8> AndSkip<T1, T2, T3, T4, T5, T6, T7, T8>(this SequenceSkipAnd<T1, T2, T3, T4, T5, T6, T7> parser, Parser<T8> and) => new SequenceAndSkip<T1, T2, T3, T4, T5, T7, T8>(parser, and);
}
}
28 changes: 18 additions & 10 deletions src/Parlot/Fluent/Parsers.SkipAnd.cs
Original file line number Diff line number Diff line change
@@ -1,43 +1,51 @@
using System;

namespace Parlot.Fluent
namespace Parlot.Fluent
{
public static partial class Parsers
{

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<T2> SkipAnd<T1, T2>(this Parser<T1> parser, Parser<T2> and) => new SequenceSkipAnd<T1, T2>(parser, and);
public static SequenceSkipAnd<T1, T2> SkipAnd<T1, T2>(this Parser<T1> parser, Parser<T2> and) => new SequenceSkipAnd<T1, T2>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<ValueTuple<T1, T3>> SkipAnd<T1, T2, T3>(this Parser<ValueTuple<T1, T2>> parser, Parser<T3> and) => new SequenceSkipAnd<T1, T2, T3>(parser, and);
public static SequenceSkipAnd<T1, T2, T3> SkipAnd<T1, T2, T3>(this Sequence<T1, T2> parser, Parser<T3> and) => new SequenceSkipAnd<T1, T2, T3>(parser, and);
public static SequenceSkipAnd<T1, T3> SkipAnd<T1, T2, T3>(this SequenceAndSkip<T1, T2> parser, Parser<T3> and) => new SequenceSkipAnd<T1, T3>(parser, and);
public static SequenceSkipAnd<T2, T3> SkipAnd<T1, T2, T3>(this SequenceSkipAnd<T1, T2> parser, Parser<T3> and) => new SequenceSkipAnd<T2, T3>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<ValueTuple<T1, T2, T4>> SkipAnd<T1, T2, T3, T4>(this Parser<ValueTuple<T1, T2, T3>> parser, Parser<T4> and) => new SequenceSkipAnd<T1, T2, T3, T4>(parser, and);
public static SequenceSkipAnd<T1, T2, T3, T4> SkipAnd<T1, T2, T3, T4>(this Sequence<T1, T2, T3> parser, Parser<T4> and) => new SequenceSkipAnd<T1, T2, T3, T4>(parser, and);
public static SequenceSkipAnd<T1, T2, T4> SkipAnd<T1, T2, T3, T4>(this SequenceAndSkip<T1, T2, T3> parser, Parser<T4> and) => new SequenceSkipAnd<T1, T2, T4>(parser, and);
public static SequenceSkipAnd<T1, T3, T4> SkipAnd<T1, T2, T3, T4>(this SequenceSkipAnd<T1, T2, T3> parser, Parser<T4> and) => new SequenceSkipAnd<T1, T3, T4>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3, T5>> SkipAnd<T1, T2, T3, T4, T5>(this Parser<ValueTuple<T1, T2, T3, T4>> parser, Parser<T5> and) => new SequenceSkipAnd<T1, T2, T3, T4, T5>(parser, and);
public static SequenceSkipAnd<T1, T2, T3, T4, T5> SkipAnd<T1, T2, T3, T4, T5>(this Sequence<T1, T2, T3, T4> parser, Parser<T5> and) => new SequenceSkipAnd<T1, T2, T3, T4, T5>(parser, and);
public static SequenceSkipAnd<T1, T2, T3, T5> SkipAnd<T1, T2, T3, T4, T5>(this SequenceAndSkip<T1, T2, T3, T4> parser, Parser<T5> and) => new SequenceSkipAnd<T1, T2, T3, T5>(parser, and);
public static SequenceSkipAnd<T1, T2, T4, T5> SkipAnd<T1, T2, T3, T4, T5>(this SequenceSkipAnd<T1, T2, T3, T4> parser, Parser<T5> and) => new SequenceSkipAnd<T1, T2, T4, T5>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3, T4, T6>> SkipAnd<T1, T2, T3, T4, T5, T6>(this Parser<ValueTuple<T1, T2, T3, T4, T5>> parser, Parser<T6> and) => new SequenceSkipAnd<T1, T2, T3, T4, T5, T6>(parser, and);
public static SequenceSkipAnd<T1, T2, T3, T4, T5, T6> SkipAnd<T1, T2, T3, T4, T5, T6>(this Sequence<T1, T2, T3, T4, T5> parser, Parser<T6> and) => new SequenceSkipAnd<T1, T2, T3, T4, T5, T6>(parser, and);
public static SequenceSkipAnd<T1, T2, T3, T4, T6> SkipAnd<T1, T2, T3, T4, T5, T6>(this SequenceAndSkip<T1, T2, T3, T4, T5> parser, Parser<T6> and) => new SequenceSkipAnd<T1, T2, T3, T4, T6>(parser, and);
public static SequenceSkipAnd<T1, T2, T3, T5, T6> ASkipAndnd<T1, T2, T3, T4, T5, T6>(this SequenceSkipAnd<T1, T2, T3, T4, T5> parser, Parser<T6> and) => new SequenceSkipAnd<T1, T2, T3, T5, T6>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3, T4, T5, T7>> SkipAnd<T1, T2, T3, T4, T5, T6, T7>(this Parser<ValueTuple<T1, T2, T3, T4, T5, T6>> parser, Parser<T7> and) => new SequenceSkipAnd<T1, T2, T3, T4, T5, T6, T7>(parser, and);
public static SequenceSkipAnd<T1, T2, T3, T4, T5, T6, T7> SkipAnd<T1, T2, T3, T4, T5, T6, T7>(this Sequence<T1, T2, T3, T4, T5, T6> parser, Parser<T7> and) => new SequenceSkipAnd<T1, T2, T3, T4, T5, T6, T7>(parser, and);

/// <summary>
/// Builds a parser that ensure the specified parsers match consecutively. The last parser's result is then ignored.
/// </summary>
public static Parser<ValueTuple<T1, T2, T3, T4, T5, T6, T8>> SkipAnd<T1, T2, T3, T4, T5, T6, T7, T8>(this Parser<ValueTuple<T1, T2, T3, T4, T5, T6, T7>> parser, Parser<T8> and) => new SequenceSkipAnd<T1, T2, T3, T4, T5, T6, T7, T8>(parser, and);
public static SequenceSkipAnd<T1, T2, T3, T4, T5, T6, T7, T8> SkipAnd<T1, T2, T3, T4, T5, T6, T7, T8>(this Sequence<T1, T2, T3, T4, T5, T6, T7> parser, Parser<T8> and) => new SequenceSkipAnd<T1, T2, T3, T4, T5, T6, T7, T8>(parser, and);
public static SequenceSkipAnd<T1, T2, T3, T4, T5, T7> SkipAnd<T1, T2, T3, T4, T5, T6, T7>(this SequenceAndSkip<T1, T2, T3, T4, T5, T6> parser, Parser<T7> and) => new SequenceSkipAnd<T1, T2, T3, T4, T5, T7>(parser, and);
public static SequenceSkipAnd<T1, T2, T3, T4, T6, T7> SkipAnd<T1, T2, T3, T4, T5, T6, T7>(this SequenceSkipAnd<T1, T2, T3, T4, T5, T6> parser, Parser<T7> and) => new SequenceSkipAnd<T1, T2, T3, T4, T6, T7>(parser, and);
}
}
Loading

0 comments on commit 9e0d3ce

Please sign in to comment.