fix: Using covariant interface for IParser and IParseResult.
Rename CanonSharp.Common to CanonSharp.Pascal.
This commit is contained in:
		@@ -1,49 +0,0 @@
 | 
			
		||||
namespace CanonSharp.Combinator.Abstractions;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 失败解析结果基类
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">解析结果类型</typeparam>
 | 
			
		||||
public abstract class FailedResult<TToken, T> : ParseResult<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    public override T Value => throw Exception;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 当前读取到的状态
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public abstract IReadState<TToken> State { get; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 解析失败的消息
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public abstract string Message { get; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 解析失败的异常
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public virtual ParseException Exception => new(ToString());
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 转换该失败结果的类型
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <typeparam name="TNext">转换之后的结果类型</typeparam>
 | 
			
		||||
    /// <returns>转换之后的失败解析类型</returns>
 | 
			
		||||
    public abstract FailedResult<TToken, TNext> Convert<TNext>();
 | 
			
		||||
 | 
			
		||||
    internal override ParseResult<TToken, TResult> Next<TNext, TResult>(Func<T, Parser<TToken, TNext>> nextParser,
 | 
			
		||||
        Func<ParseResult<TToken, TNext>, ParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        => continuation(Convert<TNext>());
 | 
			
		||||
 | 
			
		||||
    public override ParseResult<TToken, TResult> Map<TResult>(Func<T, TResult> map)
 | 
			
		||||
        => Convert<TResult>();
 | 
			
		||||
 | 
			
		||||
    public override TResult CaseOf<TResult>(Func<SuccessfulResult<TToken, T>, TResult> successfulHandler,
 | 
			
		||||
        Func<FailedResult<TToken, T>, TResult> failedHandler)
 | 
			
		||||
        => failedHandler(this);
 | 
			
		||||
 | 
			
		||||
    public override string ToString()
 | 
			
		||||
    {
 | 
			
		||||
        return $"Parse Failed: {Message}.";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								CanonSharp.Combinator/Abstractions/IFailedResult.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								CanonSharp.Combinator/Abstractions/IFailedResult.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
namespace CanonSharp.Combinator.Abstractions;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 失败解析结果基类
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">解析结果类型</typeparam>
 | 
			
		||||
public interface IFailedResult<TToken, out T> : IParseResult<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    T IParseResult<TToken, T>.Value => throw Exception;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 当前读取到的状态
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public IReadState<TToken> State { get; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 解析失败的消息
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string Message { get; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 解析失败的异常
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public ParseException Exception => new(ToString());
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 转换该失败结果的类型
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <typeparam name="TNext">转换之后的结果类型</typeparam>
 | 
			
		||||
    /// <returns>转换之后的失败解析类型</returns>
 | 
			
		||||
    public IFailedResult<TToken, TNext> Convert<TNext>();
 | 
			
		||||
 | 
			
		||||
    IParseResult<TToken, TResult> IParseResult<TToken, T>.Next<TNext, TResult>(
 | 
			
		||||
        Func<T, IParser<TToken, TNext>> nextParser,
 | 
			
		||||
        Func<IParseResult<TToken, TNext>, IParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        => continuation(Convert<TNext>());
 | 
			
		||||
 | 
			
		||||
    IParseResult<TToken, TResult> IParseResult<TToken, T>.Map<TResult>(Func<T, TResult> map)
 | 
			
		||||
        => Convert<TResult>();
 | 
			
		||||
 | 
			
		||||
    TResult IParseResult<TToken, T>.CaseOf<TResult>(Func<ISuccessfulResult<TToken, T>, TResult> successfulHandler,
 | 
			
		||||
        Func<IFailedResult<TToken, T>, TResult> failedHandler)
 | 
			
		||||
        => failedHandler(this);
 | 
			
		||||
 | 
			
		||||
    string IParseResult<TToken, T>.ToString() => $"Parse Failed: {Message}";
 | 
			
		||||
}
 | 
			
		||||
@@ -5,12 +5,12 @@ namespace CanonSharp.Combinator.Abstractions;
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">实际结果类型</typeparam>
 | 
			
		||||
public abstract class ParseResult<TToken, T>
 | 
			
		||||
public interface IParseResult<TToken, out T>
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 实际结果对象
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public abstract T Value { get; }
 | 
			
		||||
    public T Value { get; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 在当前结果上应用下一个解析器
 | 
			
		||||
@@ -20,8 +20,8 @@ public abstract class ParseResult<TToken, T>
 | 
			
		||||
    /// <typeparam name="TNext">下一个解析器函数返回的解析结果类型</typeparam>
 | 
			
		||||
    /// <typeparam name="TResult">最终的解析结果类型</typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    internal abstract ParseResult<TToken, TResult> Next<TNext, TResult>(Func<T, Parser<TToken, TNext>> nextParser,
 | 
			
		||||
        Func<ParseResult<TToken, TNext>, ParseResult<TToken, TResult>> continuation);
 | 
			
		||||
    internal IParseResult<TToken, TResult> Next<TNext, TResult>(Func<T, IParser<TToken, TNext>> nextParser,
 | 
			
		||||
        Func<IParseResult<TToken, TNext>, IParseResult<TToken, TResult>> continuation);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 映射结果
 | 
			
		||||
@@ -29,7 +29,7 @@ public abstract class ParseResult<TToken, T>
 | 
			
		||||
    /// <param name="map">映射结果的函数</param>
 | 
			
		||||
    /// <typeparam name="TResult">映射结果函数返回解析结果的类型</typeparam>
 | 
			
		||||
    /// <returns>最终的解析结果</returns>
 | 
			
		||||
    public abstract ParseResult<TToken, TResult> Map<TResult>(Func<T, TResult> map);
 | 
			
		||||
    public IParseResult<TToken, TResult> Map<TResult>(Func<T, TResult> map);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 在成功或者失败解析结果上应用不同的后继函数
 | 
			
		||||
@@ -38,6 +38,8 @@ public abstract class ParseResult<TToken, T>
 | 
			
		||||
    /// <param name="failedHandler">在失败解析结构上应用的函数</param>
 | 
			
		||||
    /// <typeparam name="TResult">最后返回解析结果的类型</typeparam>
 | 
			
		||||
    /// <returns>最后的解析结果</returns>
 | 
			
		||||
    public abstract TResult CaseOf<TResult>(Func<SuccessfulResult<TToken, T>, TResult> successfulHandler,
 | 
			
		||||
        Func<FailedResult<TToken, T>, TResult> failedHandler);
 | 
			
		||||
    public TResult CaseOf<TResult>(Func<ISuccessfulResult<TToken, T>, TResult> successfulHandler,
 | 
			
		||||
        Func<IFailedResult<TToken, T>, TResult> failedHandler);
 | 
			
		||||
 | 
			
		||||
    public string ToString();
 | 
			
		||||
}
 | 
			
		||||
@@ -7,7 +7,7 @@ namespace CanonSharp.Combinator.Abstractions;
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">解析结果类型</typeparam>
 | 
			
		||||
public abstract class Parser<TToken, T>
 | 
			
		||||
public interface IParser<TToken, out T>
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 解析器运行函数
 | 
			
		||||
@@ -17,16 +17,16 @@ public abstract class Parser<TToken, T>
 | 
			
		||||
    /// <typeparam name="TState">输入流状态类型</typeparam>
 | 
			
		||||
    /// <typeparam name="TResult">后继函数运行之后的解析结果类型</typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    internal abstract ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
 | 
			
		||||
    internal IParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<IParseResult<TToken, T>, IParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        where TState : IReadState<TToken, TState>;
 | 
			
		||||
 | 
			
		||||
    public ParseResult<TToken, T> Parse<TState>(TState state) where TState : IReadState<TToken, TState>
 | 
			
		||||
    public IParseResult<TToken, T> Parse<TState>(TState state) where TState : IReadState<TToken, TState>
 | 
			
		||||
    {
 | 
			
		||||
        return Run(state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private ParseResult<TToken, T> Run<TState>(TState state) where TState : IReadState<TToken, TState>
 | 
			
		||||
    private IParseResult<TToken, T> Run<TState>(TState state) where TState : IReadState<TToken, TState>
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
@@ -38,6 +38,6 @@ public abstract class Parser<TToken, T>
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Parser<TToken, T> operator |(Parser<TToken, T> a, Parser<TToken, T> b)
 | 
			
		||||
    public static IParser<TToken, T> operator |(IParser<TToken, T> a, IParser<TToken, T> b)
 | 
			
		||||
        => a.Alternative(b);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								CanonSharp.Combinator/Abstractions/ISuccessfulResult.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								CanonSharp.Combinator/Abstractions/ISuccessfulResult.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
namespace CanonSharp.Combinator.Abstractions;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 成功解析结果基类
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">实际的解析结果类型</typeparam>
 | 
			
		||||
public interface ISuccessfulResult<TToken,out T> : IParseResult<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 运行下一个解析器
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="parser">下一个解析器</param>
 | 
			
		||||
    /// <param name="continuation">处理解析结果的后继函数</param>
 | 
			
		||||
    /// <typeparam name="TNext">下一个解析器返回的结果类型</typeparam>
 | 
			
		||||
    /// <typeparam name="TResult">最终的结果类型</typeparam>
 | 
			
		||||
    /// <returns>最终的结果</returns>
 | 
			
		||||
    protected IParseResult<TToken, TResult> RunNext<TNext, TResult>(IParser<TToken, TNext> parser,
 | 
			
		||||
        Func<IParseResult<TToken, TNext>, IParseResult<TToken, TResult>> continuation);
 | 
			
		||||
 | 
			
		||||
    IParseResult<TToken, TResult> IParseResult<TToken, T>.Next<TNext, TResult>(
 | 
			
		||||
        Func<T, IParser<TToken, TNext>> nextParser,
 | 
			
		||||
        Func<IParseResult<TToken, TNext>, IParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        => RunNext(nextParser(Value), continuation);
 | 
			
		||||
 | 
			
		||||
    TResult IParseResult<TToken, T>.CaseOf<TResult>(Func<ISuccessfulResult<TToken, T>, TResult> successfulHandler,
 | 
			
		||||
        Func<IFailedResult<TToken, T>, TResult> failedHandler)
 | 
			
		||||
        => successfulHandler(this);
 | 
			
		||||
 | 
			
		||||
    string IParseResult<TToken, T>.ToString() => Value?.ToString() ?? string.Empty;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,33 +0,0 @@
 | 
			
		||||
namespace CanonSharp.Combinator.Abstractions;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 成功解析结果基类
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <param name="value">实际的解析结果</param>
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">实际的解析结果类型</typeparam>
 | 
			
		||||
public abstract class SuccessfulResult<TToken, T>(T value) : ParseResult<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    public override T Value => value;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 运行下一个解析器
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="parser">下一个解析器</param>
 | 
			
		||||
    /// <param name="continuation">处理解析结果的后继函数</param>
 | 
			
		||||
    /// <typeparam name="TNext">下一个解析器返回的结果类型</typeparam>
 | 
			
		||||
    /// <typeparam name="TResult">最终的结果类型</typeparam>
 | 
			
		||||
    /// <returns>最终的结果</returns>
 | 
			
		||||
    protected abstract ParseResult<TToken, TResult> RunNext<TNext, TResult>(Parser<TToken, TNext> parser,
 | 
			
		||||
        Func<ParseResult<TToken, TNext>, ParseResult<TToken, TResult>> continuation);
 | 
			
		||||
 | 
			
		||||
    internal override ParseResult<TToken, TResult> Next<TNext, TResult>(Func<T, Parser<TToken, TNext>> nextParser,
 | 
			
		||||
        Func<ParseResult<TToken, TNext>, ParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        => RunNext(nextParser(Value), continuation);
 | 
			
		||||
 | 
			
		||||
    public override TResult CaseOf<TResult>(Func<SuccessfulResult<TToken, T>, TResult> successfulHandler,
 | 
			
		||||
        Func<FailedResult<TToken, T>, TResult> failedHandler)
 | 
			
		||||
        => successfulHandler(this);
 | 
			
		||||
 | 
			
		||||
    public override string ToString() => Value?.ToString() ?? string.Empty;
 | 
			
		||||
}
 | 
			
		||||
@@ -19,7 +19,7 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Alternative<TToken, T>(this Parser<TToken, T> first, Parser<TToken, T> second)
 | 
			
		||||
    public static IParser<TToken, T> Alternative<TToken, T>(this IParser<TToken, T> first, IParser<TToken, T> second)
 | 
			
		||||
        => new AlternativeParser<TToken, T>(first, second);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -32,8 +32,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Alternative<TToken, T>(this Parser<TToken, T> parser,
 | 
			
		||||
        Func<FailedResult<TToken, T>, Parser<TToken, T>> resume)
 | 
			
		||||
    public static IParser<TToken, T> Alternative<TToken, T>(this IParser<TToken, T> parser,
 | 
			
		||||
        Func<IFailedResult<TToken, T>, IParser<TToken, T>> resume)
 | 
			
		||||
        => new ResumeParser<TToken, T>(parser, resume);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -46,8 +46,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TResult"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TResult> Bind<TToken, T, TResult>(this Parser<TToken, T> parser,
 | 
			
		||||
        Func<T, Parser<TToken, TResult>> next)
 | 
			
		||||
    public static IParser<TToken, TResult> Bind<TToken, T, TResult>(this IParser<TToken, T> parser,
 | 
			
		||||
        Func<T, IParser<TToken, TResult>> next)
 | 
			
		||||
        => new BindParser<TToken, T, TResult>(parser, next);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -60,7 +60,7 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TResult"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TResult> Map<TToken, T, TResult>(this Parser<TToken, T> parser, Func<T, TResult> map)
 | 
			
		||||
    public static IParser<TToken, TResult> Map<TToken, T, TResult>(this IParser<TToken, T> parser, Func<T, TResult> map)
 | 
			
		||||
        => new MapParser<TToken, T, TResult>(parser, map);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -73,7 +73,7 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TResult"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TResult> Map<TToken, T, TResult>(this Parser<TToken, T> parser, TResult result)
 | 
			
		||||
    public static IParser<TToken, TResult> Map<TToken, T, TResult>(this IParser<TToken, T> parser, TResult result)
 | 
			
		||||
        => parser.Map(_ => result);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -87,9 +87,9 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TResult"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TResult> Next<TToken, T, TResult>(this Parser<TToken, T> parser,
 | 
			
		||||
        Func<T, Parser<TToken, TResult>> next,
 | 
			
		||||
        Func<FailedResult<TToken, T>, Parser<TToken, TResult>> failedNext)
 | 
			
		||||
    public static IParser<TToken, TResult> Next<TToken, T, TResult>(this IParser<TToken, T> parser,
 | 
			
		||||
        Func<T, IParser<TToken, TResult>> next,
 | 
			
		||||
        Func<IFailedResult<TToken, T>, IParser<TToken, TResult>> failedNext)
 | 
			
		||||
        => new NextParser<TToken, T, TResult>(parser, next, failedNext);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -103,8 +103,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TResult"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TResult> Next<TToken, T, TResult>(this Parser<TToken, T> parser,
 | 
			
		||||
        Func<T, Parser<TToken, TResult>> next, Func<FailedResult<TToken, T>, TResult> failedHandler)
 | 
			
		||||
    public static IParser<TToken, TResult> Next<TToken, T, TResult>(this IParser<TToken, T> parser,
 | 
			
		||||
        Func<T, IParser<TToken, TResult>> next, Func<IFailedResult<TToken, T>, TResult> failedHandler)
 | 
			
		||||
        => parser.Next(next, failedResult => Pure<TToken, TResult>(failedHandler(failedResult)));
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -118,8 +118,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TResult"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TResult> Next<TToken, T, TResult>(this Parser<TToken, T> parser,
 | 
			
		||||
        Func<T, Parser<TToken, TResult>> next, TResult failedResult)
 | 
			
		||||
    public static IParser<TToken, TResult> Next<TToken, T, TResult>(this IParser<TToken, T> parser,
 | 
			
		||||
        Func<T, IParser<TToken, TResult>> next, TResult failedResult)
 | 
			
		||||
        => parser.Next(next, _ => Pure<TToken, TResult>(failedResult));
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -133,8 +133,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TResult"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TResult> Next<TToken, T, TResult>(this Parser<TToken, T> parser,
 | 
			
		||||
        Func<T, TResult> nextResult, Func<FailedResult<TToken, T>, Parser<TToken, TResult>> failedResume)
 | 
			
		||||
    public static IParser<TToken, TResult> Next<TToken, T, TResult>(this IParser<TToken, T> parser,
 | 
			
		||||
        Func<T, TResult> nextResult, Func<IFailedResult<TToken, T>, IParser<TToken, TResult>> failedResume)
 | 
			
		||||
        => parser.Next(x => Pure<TToken, TResult>(nextResult(x)), failedResume);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -148,8 +148,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TResult"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TResult> Next<TToken, T, TResult>(this Parser<TToken, T> parser,
 | 
			
		||||
        Func<T, TResult> nextResult, Func<FailedResult<TToken, T>, TResult> failedResult)
 | 
			
		||||
    public static IParser<TToken, TResult> Next<TToken, T, TResult>(this IParser<TToken, T> parser,
 | 
			
		||||
        Func<T, TResult> nextResult, Func<IFailedResult<TToken, T>, TResult> failedResult)
 | 
			
		||||
        => new SuccessfulMapParser<TToken, T, TResult>(parser, nextResult, failedResult);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -163,7 +163,7 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TResult"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TResult> Next<TToken, T, TResult>(this Parser<TToken, T> parser,
 | 
			
		||||
    public static IParser<TToken, TResult> Next<TToken, T, TResult>(this IParser<TToken, T> parser,
 | 
			
		||||
        Func<T, TResult> successfulHandler, TResult failedResult)
 | 
			
		||||
        => parser.Next(successfulHandler, _ => failedResult);
 | 
			
		||||
 | 
			
		||||
@@ -181,8 +181,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Do<TToken, T>(this Parser<TToken, T> parser, Action<T> successfulAction,
 | 
			
		||||
        Action<FailedResult<TToken, T>> failedAction)
 | 
			
		||||
    public static IParser<TToken, T> Do<TToken, T>(this IParser<TToken, T> parser, Action<T> successfulAction,
 | 
			
		||||
        Action<IFailedResult<TToken, T>> failedAction)
 | 
			
		||||
        => new DoParser<TToken, T>(parser, successfulAction, failedAction);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -194,7 +194,7 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Do<TToken, T>(this Parser<TToken, T> parser, Action<T> successfulAction)
 | 
			
		||||
    public static IParser<TToken, T> Do<TToken, T>(this IParser<TToken, T> parser, Action<T> successfulAction)
 | 
			
		||||
        => parser.Do(successfulAction, _ => { });
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -206,7 +206,7 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> LookAhead<TToken, T>(this Parser<TToken, T> parser)
 | 
			
		||||
    public static IParser<TToken, T> LookAhead<TToken, T>(this IParser<TToken, T> parser)
 | 
			
		||||
        => new LookAheadParser<TToken, T>(parser);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -219,7 +219,7 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Not<TToken, TIgnore, T>(this Parser<TToken, TIgnore> parser, T result)
 | 
			
		||||
    public static IParser<TToken, T> Not<TToken, TIgnore, T>(this IParser<TToken, TIgnore> parser, T result)
 | 
			
		||||
        => new ReverseParser<TToken, TIgnore, T>(parser, result);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -231,21 +231,21 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TIgnore"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, Unit> Not<TToken, TIgnore>(this Parser<TToken, TIgnore> parser)
 | 
			
		||||
    public static IParser<TToken, Unit> Not<TToken, TIgnore>(this IParser<TToken, TIgnore> parser)
 | 
			
		||||
        => parser.Not(Unit.Instance);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Try<TToken, T>(this Parser<TToken, T> parser,
 | 
			
		||||
        Func<FailedResult<TToken, T>, T> resume)
 | 
			
		||||
    public static IParser<TToken, T> Try<TToken, T>(this IParser<TToken, T> parser,
 | 
			
		||||
        Func<IFailedResult<TToken, T>, T> resume)
 | 
			
		||||
        => new TryParser<TToken, T>(parser, resume);
 | 
			
		||||
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Try<TToken, T>(this Parser<TToken, T> parser, T result)
 | 
			
		||||
    public static IParser<TToken, T> Try<TToken, T>(this IParser<TToken, T> parser, T result)
 | 
			
		||||
        => parser.Try(_ => result);
 | 
			
		||||
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, bool> Try<TToken, T>(this Parser<TToken, T> parser)
 | 
			
		||||
    public static IParser<TToken, bool> Try<TToken, T>(this IParser<TToken, T> parser)
 | 
			
		||||
        => parser.Next(_ => true, false).Try(false);
 | 
			
		||||
 | 
			
		||||
    #endregion
 | 
			
		||||
@@ -262,8 +262,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TRight"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TLeft> Left<TToken, TLeft, TRight>(this Parser<TToken, TLeft> left,
 | 
			
		||||
        Parser<TToken, TRight> right)
 | 
			
		||||
    public static IParser<TToken, TLeft> Left<TToken, TLeft, TRight>(this IParser<TToken, TLeft> left,
 | 
			
		||||
        IParser<TToken, TRight> right)
 | 
			
		||||
        => left.Bind(right.Map);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -276,12 +276,12 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TRight"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TRight> Right<TToken, TLeft, TRight>(this Parser<TToken, TLeft> left,
 | 
			
		||||
        Parser<TToken, TRight> right)
 | 
			
		||||
    public static IParser<TToken, TRight> Right<TToken, TLeft, TRight>(this IParser<TToken, TLeft> left,
 | 
			
		||||
        IParser<TToken, TRight> right)
 | 
			
		||||
        => left.Bind(_ => right);
 | 
			
		||||
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    private static Parser<TToken, IEnumerable<T>> ManyRecursively<TToken, T>(this Parser<TToken, T> parser,
 | 
			
		||||
    private static IParser<TToken, IEnumerable<T>> ManyRecursively<TToken, T>(this IParser<TToken, T> parser,
 | 
			
		||||
        IEnumerable<T> result)
 | 
			
		||||
        => parser.Next(x => parser.ManyRecursively(result.Append(x)), result);
 | 
			
		||||
 | 
			
		||||
@@ -293,7 +293,7 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> Many<TToken, T>(this Parser<TToken, T> parser)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> Many<TToken, T>(this IParser<TToken, T> parser)
 | 
			
		||||
        => parser.ManyRecursively([]);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -304,7 +304,7 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> Many1<TToken, T>(this Parser<TToken, T> parser)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> Many1<TToken, T>(this IParser<TToken, T> parser)
 | 
			
		||||
        => parser.Bind(x => parser.ManyRecursively([x]));
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -317,7 +317,7 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TIgnore"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, Unit> SkipMany<TToken, TIgnore>(this Parser<TToken, TIgnore> parser)
 | 
			
		||||
    public static IParser<TToken, Unit> SkipMany<TToken, TIgnore>(this IParser<TToken, TIgnore> parser)
 | 
			
		||||
        => Fix<TToken, Unit>(self => parser.Next(_ => self, Unit.Instance));
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -330,11 +330,11 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TIgnore"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, Unit> SkipMany1<TToken, TIgnore>(this Parser<TToken, TIgnore> parser)
 | 
			
		||||
    public static IParser<TToken, Unit> SkipMany1<TToken, TIgnore>(this IParser<TToken, TIgnore> parser)
 | 
			
		||||
        => parser.Right(parser.SkipMany());
 | 
			
		||||
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    private static Parser<TToken, T> ChainRecursively<TToken, T>(Func<T, Parser<TToken, T>> chain, T value)
 | 
			
		||||
    private static IParser<TToken, T> ChainRecursively<TToken, T>(Func<T, IParser<TToken, T>> chain, T value)
 | 
			
		||||
        => chain(value).Next(x => ChainRecursively(chain, x), value);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -347,12 +347,12 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Chain<TToken, T>(this Parser<TToken, T> parser, Func<T, Parser<TToken, T>> chain)
 | 
			
		||||
    public static IParser<TToken, T> Chain<TToken, T>(this IParser<TToken, T> parser, Func<T, IParser<TToken, T>> chain)
 | 
			
		||||
        => parser.Bind(x => ChainRecursively(chain, x));
 | 
			
		||||
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    private static Parser<TToken, IEnumerable<T>> ManyTillRecursively<TToken, T, TIgnore>(this Parser<TToken, T> parser,
 | 
			
		||||
        Parser<TToken, TIgnore> terminator, IEnumerable<T> result)
 | 
			
		||||
    private static IParser<TToken, IEnumerable<T>> ManyTillRecursively<TToken, T, TIgnore>(this IParser<TToken, T> parser,
 | 
			
		||||
        IParser<TToken, TIgnore> terminator, IEnumerable<T> result)
 | 
			
		||||
        => terminator.Next(_ => Pure<TToken, IEnumerable<T>>(result),
 | 
			
		||||
            _ => parser.Bind(x => parser.ManyTillRecursively(terminator, result.Append(x))));
 | 
			
		||||
 | 
			
		||||
@@ -367,8 +367,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TIgnore"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> ManyTill<TToken, T, TIgnore>(this Parser<TToken, T> parser,
 | 
			
		||||
        Parser<TToken, TIgnore> terminator)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> ManyTill<TToken, T, TIgnore>(this IParser<TToken, T> parser,
 | 
			
		||||
        IParser<TToken, TIgnore> terminator)
 | 
			
		||||
        => parser.ManyTillRecursively(terminator, []);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -382,8 +382,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TIgnore"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> Many1Till<TToken, T, TIgnore>(this Parser<TToken, T> parser,
 | 
			
		||||
        Parser<TToken, TIgnore> terminator)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> Many1Till<TToken, T, TIgnore>(this IParser<TToken, T> parser,
 | 
			
		||||
        IParser<TToken, TIgnore> terminator)
 | 
			
		||||
        => parser.Bind(x => parser.ManyTillRecursively(terminator, [x]));
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -397,8 +397,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> SkipTill<TToken, TIgnore, T>(this Parser<TToken, TIgnore> parser,
 | 
			
		||||
        Parser<TToken, T> terminator)
 | 
			
		||||
    public static IParser<TToken, T> SkipTill<TToken, TIgnore, T>(this IParser<TToken, TIgnore> parser,
 | 
			
		||||
        IParser<TToken, T> terminator)
 | 
			
		||||
        => Fix<TToken, T>(self => terminator | parser.Right(self));
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -412,8 +412,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Skip1Till<TToken, TIgnore, T>(this Parser<TToken, TIgnore> parser,
 | 
			
		||||
        Parser<TToken, T> terminator)
 | 
			
		||||
    public static IParser<TToken, T> Skip1Till<TToken, TIgnore, T>(this IParser<TToken, TIgnore> parser,
 | 
			
		||||
        IParser<TToken, T> terminator)
 | 
			
		||||
        => parser.Right(parser.SkipTill(terminator));
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -424,7 +424,7 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Match<TToken, T>(this Parser<TToken, T> parser)
 | 
			
		||||
    public static IParser<TToken, T> Match<TToken, T>(this IParser<TToken, T> parser)
 | 
			
		||||
        => SkipTill(Any<TToken>(), parser);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -440,8 +440,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TRight"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> Quote<TToken, T, TLeft, TRight>(this Parser<TToken, T> parser,
 | 
			
		||||
        Parser<TToken, TLeft> left, Parser<TToken, TRight> right)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> Quote<TToken, T, TLeft, TRight>(this IParser<TToken, T> parser,
 | 
			
		||||
        IParser<TToken, TLeft> left, IParser<TToken, TRight> right)
 | 
			
		||||
        => left.Right(parser.ManyTill(right));
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -454,8 +454,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TQuote"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> Quote<TToken, T, TQuote>(this Parser<TToken, T> parser,
 | 
			
		||||
        Parser<TToken, TQuote> quotedParser)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> Quote<TToken, T, TQuote>(this IParser<TToken, T> parser,
 | 
			
		||||
        IParser<TToken, TQuote> quotedParser)
 | 
			
		||||
        => parser.Quote(quotedParser, quotedParser);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -470,8 +470,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TSeparator"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> SeparatedBy1<TToken, T, TSeparator>(this Parser<TToken, T> parser,
 | 
			
		||||
        Parser<TToken, TSeparator> separator)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> SeparatedBy1<TToken, T, TSeparator>(this IParser<TToken, T> parser,
 | 
			
		||||
        IParser<TToken, TSeparator> separator)
 | 
			
		||||
        => parser.Bind(x => separator.Right(parser).ManyRecursively([x]));
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -486,8 +486,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TSeparator"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> SeparatedBy<TToken, T, TSeparator>(this Parser<TToken, T> parser,
 | 
			
		||||
        Parser<TToken, TSeparator> separator)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> SeparatedBy<TToken, T, TSeparator>(this IParser<TToken, T> parser,
 | 
			
		||||
        IParser<TToken, TSeparator> separator)
 | 
			
		||||
        => parser.SeparatedBy1(separator).Try([]);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -502,8 +502,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TSeparator"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> EndBy<TToken, T, TSeparator>(this Parser<TToken, T> parser,
 | 
			
		||||
        Parser<TToken, TSeparator> separator)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> EndBy<TToken, T, TSeparator>(this IParser<TToken, T> parser,
 | 
			
		||||
        IParser<TToken, TSeparator> separator)
 | 
			
		||||
        => parser.Many().Left(separator);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -518,8 +518,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TSeparator"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> EndBy1<TToken, T, TSeparator>(this Parser<TToken, T> parser,
 | 
			
		||||
        Parser<TToken, TSeparator> separator)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> EndBy1<TToken, T, TSeparator>(this IParser<TToken, T> parser,
 | 
			
		||||
        IParser<TToken, TSeparator> separator)
 | 
			
		||||
        => parser.Many1().Left(separator);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -534,8 +534,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TSeparator"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> SeparatedOrEndBy1<TToken, T, TSeparator>(this Parser<TToken, T> parser,
 | 
			
		||||
        Parser<TToken, TSeparator> separator)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> SeparatedOrEndBy1<TToken, T, TSeparator>(this IParser<TToken, T> parser,
 | 
			
		||||
        IParser<TToken, TSeparator> separator)
 | 
			
		||||
        => parser.SeparatedBy1(separator).Left(separator.Try());
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -550,8 +550,8 @@ public static class ParserExtensions
 | 
			
		||||
    /// <typeparam name="TSeparator"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> SeparatedOrEndBy<TToken, T, TSeparator>(this Parser<TToken, T> parser,
 | 
			
		||||
        Parser<TToken, TSeparator> separator)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> SeparatedOrEndBy<TToken, T, TSeparator>(this IParser<TToken, T> parser,
 | 
			
		||||
        IParser<TToken, TSeparator> separator)
 | 
			
		||||
        => parser.SeparatedOrEndBy1(separator).Try([]);
 | 
			
		||||
 | 
			
		||||
    #endregion
 | 
			
		||||
@@ -559,13 +559,13 @@ public static class ParserExtensions
 | 
			
		||||
    #region LINQ
 | 
			
		||||
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TResult> Select<TToken, T, TResult>(this Parser<TToken, T> parser,
 | 
			
		||||
    public static IParser<TToken, TResult> Select<TToken, T, TResult>(this IParser<TToken, T> parser,
 | 
			
		||||
        Func<T, TResult> selector)
 | 
			
		||||
        => parser.Map(selector);
 | 
			
		||||
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TResult> SelectMany<TToken, T, TIntermediate, TResult>(this Parser<TToken, T> parser,
 | 
			
		||||
        Func<T, Parser<TToken, TIntermediate>> selector, Func<T, TIntermediate, TResult> projector)
 | 
			
		||||
    public static IParser<TToken, TResult> SelectMany<TToken, T, TIntermediate, TResult>(this IParser<TToken, T> parser,
 | 
			
		||||
        Func<T, IParser<TToken, TIntermediate>> selector, Func<T, TIntermediate, TResult> projector)
 | 
			
		||||
        => parser.Bind(x => selector(x).Map(y => projector(x, y)));
 | 
			
		||||
 | 
			
		||||
    #endregion
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ public static class ParseResultBuilder
 | 
			
		||||
    /// <typeparam name="T">解析成功的对象类型</typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static ParseResult<TToken, T> Succeed<TToken, TState, T>(T value, TState state)
 | 
			
		||||
    public static IParseResult<TToken, T> Succeed<TToken, TState, T>(T value, TState state)
 | 
			
		||||
        where TState : IReadState<TToken, TState>
 | 
			
		||||
        => new InternalSuccessfulResult<TToken, TState, T>(value, state);
 | 
			
		||||
 | 
			
		||||
@@ -32,7 +32,7 @@ public static class ParseResultBuilder
 | 
			
		||||
    /// <typeparam name="T">解析成功的对象类型</typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static ParseResult<TToken, T> Fail<TToken, TState, T>(TState state)
 | 
			
		||||
    public static IParseResult<TToken, T> Fail<TToken, TState, T>(TState state)
 | 
			
		||||
        where TState : IReadState<TToken, TState>
 | 
			
		||||
        => new FailedResultWithError<TToken, TState, T>(state);
 | 
			
		||||
 | 
			
		||||
@@ -47,7 +47,7 @@ public static class ParseResultBuilder
 | 
			
		||||
    /// <typeparam name="T">解析成功的对象类型</typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static ParseResult<TToken, T> Fail<TToken, TState, T>(string message, TState state)
 | 
			
		||||
    public static IParseResult<TToken, T> Fail<TToken, TState, T>(string message, TState state)
 | 
			
		||||
        where TState : IReadState<TToken, TState>
 | 
			
		||||
        => new FailedResultWithMessage<TToken, TState, T>(message, state);
 | 
			
		||||
 | 
			
		||||
@@ -61,7 +61,7 @@ public static class ParseResultBuilder
 | 
			
		||||
    /// <typeparam name="T">解析成功的对象类型</typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static ParseResult<TToken, T> Fail<TToken, TState, T>(Exception exception, TState state)
 | 
			
		||||
    public static IParseResult<TToken, T> Fail<TToken, TState, T>(Exception exception, TState state)
 | 
			
		||||
        where TState : IReadState<TToken, TState>
 | 
			
		||||
        => new FailedResultWithException<TToken, TState, T>(exception, state);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Pure<TToken, T>(T value)
 | 
			
		||||
    public static IParser<TToken, T> Pure<TToken, T>(T value)
 | 
			
		||||
        => new PureParser<TToken, T>(value);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -31,7 +31,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Pure<TToken, T>(Func<IReadState<TToken>, T> valueFunc)
 | 
			
		||||
    public static IParser<TToken, T> Pure<TToken, T>(Func<IReadState<TToken>, T> valueFunc)
 | 
			
		||||
        => new DelayedPureParser<TToken, T>(valueFunc);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -40,7 +40,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="TToken"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, Unit> Null<TToken>() => Pure<TToken, Unit>(Unit.Instance);
 | 
			
		||||
    public static IParser<TToken, Unit> Null<TToken>() => Pure<TToken, Unit>(Unit.Instance);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 失败的解析器
 | 
			
		||||
@@ -49,7 +49,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Fail<TToken, T>() => new FailedParser<TToken, T>();
 | 
			
		||||
    public static IParser<TToken, T> Fail<TToken, T>() => new FailedParser<TToken, T>();
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 失败的解析器
 | 
			
		||||
@@ -59,7 +59,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Fail<TToken, T>(string message) => new FailedParserWithMessage<TToken, T>(message);
 | 
			
		||||
    public static IParser<TToken, T> Fail<TToken, T>(string message) => new FailedParserWithMessage<TToken, T>(message);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 失败的解析器
 | 
			
		||||
@@ -69,7 +69,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Fail<TToken, T>(Func<IReadState<TToken>, string> messageFunc) =>
 | 
			
		||||
    public static IParser<TToken, T> Fail<TToken, T>(Func<IReadState<TToken>, string> messageFunc) =>
 | 
			
		||||
        new FailedParserWithDelayedMessage<TToken, T>(messageFunc);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -80,7 +80,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Fail<TToken, T>(Exception exception) =>
 | 
			
		||||
    public static IParser<TToken, T> Fail<TToken, T>(Exception exception) =>
 | 
			
		||||
        new FailedParserWithException<TToken, T>(exception);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -90,7 +90,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="TToken"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TToken> Satisfy<TToken>(Func<TToken, bool> predicate)
 | 
			
		||||
    public static IParser<TToken, TToken> Satisfy<TToken>(Func<TToken, bool> predicate)
 | 
			
		||||
        => new SatisfyParser<TToken>(predicate);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -99,7 +99,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="TToken"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TToken> Any<TToken>() => Satisfy<TToken>(_ => true);
 | 
			
		||||
    public static IParser<TToken, TToken> Any<TToken>() => Satisfy<TToken>(_ => true);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 识别指定输入元素的解析器
 | 
			
		||||
@@ -108,7 +108,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="TToken"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, TToken> Token<TToken>(TToken token)
 | 
			
		||||
    public static IParser<TToken, TToken> Token<TToken>(TToken token)
 | 
			
		||||
        => Satisfy<TToken>(t => EqualityComparer<TToken>.Default.Equals(t, token));
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -118,7 +118,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="TToken"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, Unit> Skip<TToken>(int count) => new SkipParser<TToken>(count);
 | 
			
		||||
    public static IParser<TToken, Unit> Skip<TToken>(int count) => new SkipParser<TToken>(count);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 识别指定数量输入元素的解析器
 | 
			
		||||
@@ -127,7 +127,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="TToken"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<TToken>> Take<TToken>(int count) => new TakeParser<TToken>(count);
 | 
			
		||||
    public static IParser<TToken, IEnumerable<TToken>> Take<TToken>(int count) => new TakeParser<TToken>(count);
 | 
			
		||||
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
@@ -141,7 +141,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Fix<TToken, T>(Func<Parser<TToken, T>, Parser<TToken, T>> parserFix)
 | 
			
		||||
    public static IParser<TToken, T> Fix<TToken, T>(Func<IParser<TToken, T>, IParser<TToken, T>> parserFix)
 | 
			
		||||
        => new FixParser<TToken, T>(parserFix);
 | 
			
		||||
 | 
			
		||||
    #endregion
 | 
			
		||||
@@ -156,7 +156,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Choice<TToken, T>(IEnumerable<Parser<TToken, T>> parsers)
 | 
			
		||||
    public static IParser<TToken, T> Choice<TToken, T>(IEnumerable<IParser<TToken, T>> parsers)
 | 
			
		||||
        => parsers.Aggregate((result, parser) => result.Alternative(parser));
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -167,7 +167,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, T> Choice<TToken, T>(params Parser<TToken, T>[] parsers)
 | 
			
		||||
    public static IParser<TToken, T> Choice<TToken, T>(params IParser<TToken, T>[] parsers)
 | 
			
		||||
        => Choice(parsers.AsEnumerable());
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -178,7 +178,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> Sequence<TToken, T>(IEnumerable<Parser<TToken, T>> parsers)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> Sequence<TToken, T>(IEnumerable<IParser<TToken, T>> parsers)
 | 
			
		||||
        => parsers.Reverse().Aggregate(Pure<TToken, IEnumerable<T>>([]),
 | 
			
		||||
            (next, parser) => parser.Bind(
 | 
			
		||||
                x => next.Map(result => result.Prepend(x))));
 | 
			
		||||
@@ -191,7 +191,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="T"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<T>> Sequence<TToken, T>(params Parser<TToken, T>[] parsers)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<T>> Sequence<TToken, T>(params IParser<TToken, T>[] parsers)
 | 
			
		||||
        => Sequence(parsers.AsEnumerable());
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -203,7 +203,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="TIgnore"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<TToken>> TakeTill<TToken, TIgnore>(Parser<TToken, TIgnore> terminator)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<TToken>> TakeTill<TToken, TIgnore>(IParser<TToken, TIgnore> terminator)
 | 
			
		||||
        => Any<TToken>().ManyTill(terminator);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -215,7 +215,7 @@ public static class ParserBuilder
 | 
			
		||||
    /// <typeparam name="TIgnore"></typeparam>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<TToken, IEnumerable<TToken>> Take1Till<TToken, TIgnore>(Parser<TToken, TIgnore> termintor)
 | 
			
		||||
    public static IParser<TToken, IEnumerable<TToken>> Take1Till<TToken, TIgnore>(IParser<TToken, TIgnore> termintor)
 | 
			
		||||
        => Any<TToken>().Many1Till(termintor);
 | 
			
		||||
 | 
			
		||||
    #endregion
 | 
			
		||||
 
 | 
			
		||||
@@ -10,11 +10,12 @@ namespace CanonSharp.Combinator.Parsers.Bases;
 | 
			
		||||
/// <param name="second">第二个解析器</param>
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">解析器结果类型</typeparam>
 | 
			
		||||
internal sealed class AlternativeParser<TToken, T>(Parser<TToken, T> first, Parser<TToken, T> second)
 | 
			
		||||
    : Parser<TToken, T>
 | 
			
		||||
internal sealed class AlternativeParser<TToken, T>(IParser<TToken, T> first, IParser<TToken, T> second)
 | 
			
		||||
    : IParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    internal override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
 | 
			
		||||
    public IParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<IParseResult<TToken, T>, IParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        where TState : IReadState<TToken, TState>
 | 
			
		||||
    {
 | 
			
		||||
        return first.Run(state, result => result.CaseOf(continuation, _ => second.Run(state, continuation)));
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -11,10 +11,11 @@ namespace CanonSharp.Combinator.Parsers.Bases;
 | 
			
		||||
/// <typeparam name="TIntermediate">上游解析器结果类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">下游解析器结果类型</typeparam>
 | 
			
		||||
internal sealed class BindParser<TToken, TIntermediate, T>(
 | 
			
		||||
    Parser<TToken, TIntermediate> parser,
 | 
			
		||||
    Func<TIntermediate, Parser<TToken, T>> next) : Parser<TToken, T>
 | 
			
		||||
    IParser<TToken, TIntermediate> parser,
 | 
			
		||||
    Func<TIntermediate, IParser<TToken, T>> next) : IParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    internal override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
 | 
			
		||||
    public IParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<IParseResult<TToken, T>, IParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        where TState : IReadState<TToken, TState>
 | 
			
		||||
        => parser.Run(state, result => result.Next(next, continuation));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,16 +9,17 @@ namespace CanonSharp.Combinator.Parsers.Bases;
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <typeparam name="TToken"></typeparam>
 | 
			
		||||
/// <typeparam name="T"></typeparam>
 | 
			
		||||
internal sealed class FixParser<TToken, T> : Parser<TToken, T>
 | 
			
		||||
internal sealed class FixParser<TToken, T> : IParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    private readonly Parser<TToken, T> _parser;
 | 
			
		||||
    private readonly IParser<TToken, T> _parser;
 | 
			
		||||
 | 
			
		||||
    public FixParser(Func<Parser<TToken, T>, Parser<TToken, T>> func)
 | 
			
		||||
    public FixParser(Func<IParser<TToken, T>, IParser<TToken, T>> func)
 | 
			
		||||
    {
 | 
			
		||||
        _parser = func(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
 | 
			
		||||
    public IParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<IParseResult<TToken, T>, IParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        where TState : IReadState<TToken, TState>
 | 
			
		||||
        => _parser.Run(state, continuation);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,10 +12,11 @@ namespace CanonSharp.Combinator.Parsers.Bases;
 | 
			
		||||
/// <typeparam name="TIntermediate"></typeparam>
 | 
			
		||||
/// <typeparam name="T"></typeparam>
 | 
			
		||||
internal sealed class MapParser<TToken, TIntermediate, T>(
 | 
			
		||||
    Parser<TToken, TIntermediate> parser,
 | 
			
		||||
    Func<TIntermediate, T> func) : Parser<TToken, T>
 | 
			
		||||
    IParser<TToken, TIntermediate> parser,
 | 
			
		||||
    Func<TIntermediate, T> func) : IParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    internal override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
 | 
			
		||||
    public IParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<IParseResult<TToken, T>, IParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        where TState : IReadState<TToken, TState>
 | 
			
		||||
        => parser.Run(state, result => continuation(result.Map(func)));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,12 +12,13 @@ namespace CanonSharp.Combinator.Parsers.Bases;
 | 
			
		||||
/// <typeparam name="TIntermediate">上游解析器结果类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">最终解析结果类型</typeparam>
 | 
			
		||||
internal sealed class NextParser<TToken, TIntermediate, T>(
 | 
			
		||||
    Parser<TToken, TIntermediate> parser,
 | 
			
		||||
    Func<TIntermediate, Parser<TToken, T>> successfulParser,
 | 
			
		||||
    Func<FailedResult<TToken, TIntermediate>, Parser<TToken, T>> failedParser) : Parser<TToken, T>
 | 
			
		||||
    IParser<TToken, TIntermediate> parser,
 | 
			
		||||
    Func<TIntermediate, IParser<TToken, T>> successfulParser,
 | 
			
		||||
    Func<IFailedResult<TToken, TIntermediate>, IParser<TToken, T>> failedParser) : IParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    internal override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
 | 
			
		||||
    public IParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<IParseResult<TToken, T>, IParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        where TState : IReadState<TToken, TState>
 | 
			
		||||
    {
 | 
			
		||||
        return parser.Run(state, result => result.CaseOf(
 | 
			
		||||
            successfulResult => successfulResult.Next(successfulParser, continuation),
 | 
			
		||||
 
 | 
			
		||||
@@ -11,11 +11,12 @@ namespace CanonSharp.Combinator.Parsers.Bases;
 | 
			
		||||
/// <typeparam name="TToken">输入令牌类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">解析结果类型</typeparam>
 | 
			
		||||
internal sealed class ResumeParser<TToken, T>(
 | 
			
		||||
    Parser<TToken, T> parser,
 | 
			
		||||
    Func<FailedResult<TToken, T>, Parser<TToken, T>> failedHandler) : Parser<TToken, T>
 | 
			
		||||
    IParser<TToken, T> parser,
 | 
			
		||||
    Func<IFailedResult<TToken, T>, IParser<TToken, T>> failedHandler) : IParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    internal override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
 | 
			
		||||
    public IParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<IParseResult<TToken, T>, IParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        where TState : IReadState<TToken, TState>
 | 
			
		||||
    {
 | 
			
		||||
        return parser.Run(state,
 | 
			
		||||
            result => result.CaseOf(continuation,
 | 
			
		||||
 
 | 
			
		||||
@@ -9,18 +9,20 @@ namespace CanonSharp.Combinator.Parsers;
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
/// <typeparam name="TIntermediate">需要修改结果的解析器</typeparam>
 | 
			
		||||
/// <typeparam name="T">最终返回的解析结果</typeparam>
 | 
			
		||||
public abstract class ModifiedParser<TToken, TIntermediate, T>(Parser<TToken, TIntermediate> parser) : Parser<TToken, T>
 | 
			
		||||
public abstract class ModifiedParser<TToken, TIntermediate, T>(IParser<TToken, TIntermediate> parser)
 | 
			
		||||
    : IParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    protected abstract ParseResult<TToken, T> Fail<TState>(TState state,
 | 
			
		||||
        FailedResult<TToken, TIntermediate> failedResult)
 | 
			
		||||
    protected abstract IParseResult<TToken, T> Fail<TState>(TState state,
 | 
			
		||||
        IFailedResult<TToken, TIntermediate> failedResult)
 | 
			
		||||
        where TState : IReadState<TToken, TState>;
 | 
			
		||||
 | 
			
		||||
    protected abstract ParseResult<TToken, T> Succeed<TState>(TState state,
 | 
			
		||||
        SuccessfulResult<TToken, TIntermediate> successfulResult)
 | 
			
		||||
    protected abstract IParseResult<TToken, T> Succeed<TState>(TState state,
 | 
			
		||||
        ISuccessfulResult<TToken, TIntermediate> successfulResult)
 | 
			
		||||
        where TState : IReadState<TToken, TState>;
 | 
			
		||||
 | 
			
		||||
    internal override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
 | 
			
		||||
    public IParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<IParseResult<TToken, T>, IParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        where TState : IReadState<TToken, TState>
 | 
			
		||||
        => parser.Run(state, result => result.CaseOf(
 | 
			
		||||
            success => continuation(Succeed(state, success)),
 | 
			
		||||
            failure => continuation(Fail(state, failure))));
 | 
			
		||||
 
 | 
			
		||||
@@ -11,18 +11,18 @@ namespace CanonSharp.Combinator.Parsers.Modifiers;
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">解析结果类型</typeparam>
 | 
			
		||||
internal sealed class DoParser<TToken, T>(
 | 
			
		||||
    Parser<TToken, T> parser,
 | 
			
		||||
    IParser<TToken, T> parser,
 | 
			
		||||
    Action<T> succeed,
 | 
			
		||||
    Action<FailedResult<TToken, T>> fail) : ModifiedParser<TToken, T, T>(parser)
 | 
			
		||||
    Action<IFailedResult<TToken, T>> fail) : ModifiedParser<TToken, T, T>(parser)
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, T> Succeed<TState>(TState state,
 | 
			
		||||
        SuccessfulResult<TToken, T> successfulResult)
 | 
			
		||||
    protected override IParseResult<TToken, T> Succeed<TState>(TState state,
 | 
			
		||||
        ISuccessfulResult<TToken, T> successfulResult)
 | 
			
		||||
    {
 | 
			
		||||
        succeed(successfulResult.Value);
 | 
			
		||||
        return successfulResult;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected override ParseResult<TToken, T> Fail<TState>(TState state, FailedResult<TToken, T> failedResult)
 | 
			
		||||
    protected override IParseResult<TToken, T> Fail<TState>(TState state, IFailedResult<TToken, T> failedResult)
 | 
			
		||||
    {
 | 
			
		||||
        fail(failedResult);
 | 
			
		||||
        return failedResult;
 | 
			
		||||
 
 | 
			
		||||
@@ -10,12 +10,12 @@ namespace CanonSharp.Combinator.Parsers.Modifiers;
 | 
			
		||||
/// <param name="parser">需要向前看的解析器</param>
 | 
			
		||||
/// <typeparam name="TToken">输入流令牌</typeparam>
 | 
			
		||||
/// <typeparam name="T">返回的解析结果类型</typeparam>
 | 
			
		||||
internal sealed class LookAheadParser<TToken, T>(Parser<TToken, T> parser) : ModifiedParser<TToken, T, T>(parser)
 | 
			
		||||
internal sealed class LookAheadParser<TToken, T>(IParser<TToken, T> parser) : ModifiedParser<TToken, T, T>(parser)
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, T> Succeed<TState>(TState state,
 | 
			
		||||
        SuccessfulResult<TToken, T> successfulResult)
 | 
			
		||||
    protected override IParseResult<TToken, T> Succeed<TState>(TState state,
 | 
			
		||||
        ISuccessfulResult<TToken, T> successfulResult)
 | 
			
		||||
        => ParseResultBuilder.Succeed<TToken, TState, T>(successfulResult.Value, state);
 | 
			
		||||
 | 
			
		||||
    protected override ParseResult<TToken, T> Fail<TState>(TState state, FailedResult<TToken, T> failedResult)
 | 
			
		||||
    protected override IParseResult<TToken, T> Fail<TState>(TState state, IFailedResult<TToken, T> failedResult)
 | 
			
		||||
        => ParseResultBuilder.Fail<TToken, TState, T>($"Failed when looking ahead: {failedResult}", state);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,15 +12,15 @@ namespace CanonSharp.Combinator.Parsers.Modifiers;
 | 
			
		||||
/// <typeparam name="TToken">输入流的类型</typeparam>
 | 
			
		||||
/// <typeparam name="TIntermediate">上游解析器结果类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">最终的返回结果</typeparam>
 | 
			
		||||
internal sealed class ReverseParser<TToken, TIntermediate, T>(Parser<TToken, TIntermediate> parser, T result)
 | 
			
		||||
internal sealed class ReverseParser<TToken, TIntermediate, T>(IParser<TToken, TIntermediate> parser, T result)
 | 
			
		||||
    : ModifiedParser<TToken, TIntermediate, T>(parser)
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, T> Succeed<TState>(TState state,
 | 
			
		||||
        SuccessfulResult<TToken, TIntermediate> successfulResult)
 | 
			
		||||
    protected override IParseResult<TToken, T> Succeed<TState>(TState state,
 | 
			
		||||
        ISuccessfulResult<TToken, TIntermediate> successfulResult)
 | 
			
		||||
        => ParseResultBuilder.Fail<TToken, TState, T>($"Unexpected successful result: {successfulResult.Value}",
 | 
			
		||||
            state);
 | 
			
		||||
 | 
			
		||||
    protected override ParseResult<TToken, T> Fail<TState>(TState state,
 | 
			
		||||
        FailedResult<TToken, TIntermediate> failedResult)
 | 
			
		||||
    protected override IParseResult<TToken, T> Fail<TState>(TState state,
 | 
			
		||||
        IFailedResult<TToken, TIntermediate> failedResult)
 | 
			
		||||
        => ParseResultBuilder.Succeed<TToken, TState, T>(result, state);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,15 +12,15 @@ namespace CanonSharp.Combinator.Parsers.Modifiers;
 | 
			
		||||
/// <typeparam name="TIntermediate">上游解析器解析结果类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">最终的解析结果类型</typeparam>
 | 
			
		||||
internal sealed class SuccessfulMapParser<TToken, TIntermediate, T>(
 | 
			
		||||
    Parser<TToken, TIntermediate> parser,
 | 
			
		||||
    IParser<TToken, TIntermediate> parser,
 | 
			
		||||
    Func<TIntermediate, T> successfulHandler,
 | 
			
		||||
    Func<FailedResult<TToken, TIntermediate>, T> failedHandler) : ModifiedParser<TToken, TIntermediate, T>(parser)
 | 
			
		||||
    Func<IFailedResult<TToken, TIntermediate>, T> failedHandler) : ModifiedParser<TToken, TIntermediate, T>(parser)
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, T> Succeed<TState>(TState state,
 | 
			
		||||
        SuccessfulResult<TToken, TIntermediate> successfulResult)
 | 
			
		||||
    protected override IParseResult<TToken, T> Succeed<TState>(TState state,
 | 
			
		||||
        ISuccessfulResult<TToken, TIntermediate> successfulResult)
 | 
			
		||||
        => successfulResult.Map(successfulHandler);
 | 
			
		||||
 | 
			
		||||
    protected override ParseResult<TToken, T> Fail<TState>(TState state,
 | 
			
		||||
        FailedResult<TToken, TIntermediate> failedResult)
 | 
			
		||||
    protected override IParseResult<TToken, T> Fail<TState>(TState state,
 | 
			
		||||
        IFailedResult<TToken, TIntermediate> failedResult)
 | 
			
		||||
        => ParseResultBuilder.Succeed<TToken, TState, T>(failedHandler(failedResult), state);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,13 +11,13 @@ namespace CanonSharp.Combinator.Parsers.Modifiers;
 | 
			
		||||
/// <param name="resume">处理失败结果的恢复函数</param>
 | 
			
		||||
/// <typeparam name="TToken">输入流令牌</typeparam>
 | 
			
		||||
/// <typeparam name="T">解析器返回结果类型</typeparam>
 | 
			
		||||
internal sealed class TryParser<TToken, T>(Parser<TToken, T> parser, Func<FailedResult<TToken, T>, T> resume)
 | 
			
		||||
internal sealed class TryParser<TToken, T>(IParser<TToken, T> parser, Func<IFailedResult<TToken, T>, T> resume)
 | 
			
		||||
    : ModifiedParser<TToken, T, T>(parser)
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, T> Succeed<TState>(TState state,
 | 
			
		||||
        SuccessfulResult<TToken, T> successfulResult)
 | 
			
		||||
    protected override IParseResult<TToken, T> Succeed<TState>(TState state,
 | 
			
		||||
        ISuccessfulResult<TToken, T> successfulResult)
 | 
			
		||||
        => successfulResult;
 | 
			
		||||
 | 
			
		||||
    protected override ParseResult<TToken, T> Fail<TState>(TState state, FailedResult<TToken, T> failedResult)
 | 
			
		||||
    protected override IParseResult<TToken, T> Fail<TState>(TState state, IFailedResult<TToken, T> failedResult)
 | 
			
		||||
        => ParseResultBuilder.Succeed<TToken, TState, T>(resume(failedResult), state);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ namespace CanonSharp.Combinator.Parsers;
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">解析结果的类型</typeparam>
 | 
			
		||||
public abstract class PrimitiveParser<TToken, T> : Parser<TToken, T>
 | 
			
		||||
public abstract class PrimitiveParser<TToken, T> : IParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 运行解析器 返回解析结果
 | 
			
		||||
@@ -16,10 +16,11 @@ public abstract class PrimitiveParser<TToken, T> : Parser<TToken, T>
 | 
			
		||||
    /// <param name="state">当前输入流的状态</param>
 | 
			
		||||
    /// <typeparam name="TState">输入流状态的类型</typeparam>
 | 
			
		||||
    /// <returns>解析结果</returns>
 | 
			
		||||
    protected abstract ParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
    protected abstract IParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
        where TState : IReadState<TToken, TState>;
 | 
			
		||||
 | 
			
		||||
    internal sealed override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
 | 
			
		||||
    public IParseResult<TToken, TResult> Run<TState, TResult>(TState state,
 | 
			
		||||
        Func<IParseResult<TToken, T>, IParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        where TState : IReadState<TToken, TState>
 | 
			
		||||
        => continuation(Run(state));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ namespace CanonSharp.Combinator.Parsers.Primitives;
 | 
			
		||||
/// <typeparam name="T">解析结果的类型</typeparam>
 | 
			
		||||
internal sealed class FailedParser<TToken, T> : PrimitiveParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
    protected override IParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
        => ParseResultBuilder.Fail<TToken, TState, T>(state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -21,7 +21,7 @@ internal sealed class FailedParser<TToken, T> : PrimitiveParser<TToken, T>
 | 
			
		||||
/// <typeparam name="T">解析结果的类型</typeparam>
 | 
			
		||||
internal sealed class FailedParserWithMessage<TToken, T>(string message) : PrimitiveParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
    protected override IParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
        => ParseResultBuilder.Fail<TToken, TState, T>(message, state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -34,7 +34,7 @@ internal sealed class FailedParserWithMessage<TToken, T>(string message) : Primi
 | 
			
		||||
internal sealed class FailedParserWithDelayedMessage<TToken, T>(Func<IReadState<TToken>, string> messageFunc)
 | 
			
		||||
    : PrimitiveParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
    protected override IParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
        => ParseResultBuilder.Fail<TToken, TState, T>(messageFunc(state), state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -46,6 +46,6 @@ internal sealed class FailedParserWithDelayedMessage<TToken, T>(Func<IReadState<
 | 
			
		||||
/// <typeparam name="T">解析结果的类型</typeparam>
 | 
			
		||||
internal sealed class FailedParserWithException<TToken, T>(Exception e) : PrimitiveParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
    protected override IParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
        => ParseResultBuilder.Fail<TToken, TState, T>(e, state);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ namespace CanonSharp.Combinator.Parsers.Primitives;
 | 
			
		||||
/// <typeparam name="T">解析成功返回值的类型</typeparam>
 | 
			
		||||
internal sealed class PureParser<TToken, T>(T value) : PrimitiveParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
    protected override IParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
        => ParseResultBuilder.Succeed<TToken, TState, T>(value, state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -22,6 +22,6 @@ internal sealed class PureParser<TToken, T>(T value) : PrimitiveParser<TToken, T
 | 
			
		||||
/// <typeparam name="T">解析成功返回值的类型</typeparam>
 | 
			
		||||
internal sealed class DelayedPureParser<TToken, T>(Func<IReadState<TToken>, T> valueFunc) : PrimitiveParser<TToken, T>
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
    protected override IParseResult<TToken, T> Run<TState>(TState state)
 | 
			
		||||
        => ParseResultBuilder.Succeed<TToken, TState, T>(valueFunc(state), state);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ namespace CanonSharp.Combinator.Parsers.Primitives;
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
internal sealed class SatisfyParser<TToken>(Func<TToken, bool> predicate) : PrimitiveParser<TToken, TToken>
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, TToken> Run<TState>(TState state)
 | 
			
		||||
    protected override IParseResult<TToken, TToken> Run<TState>(TState state)
 | 
			
		||||
    {
 | 
			
		||||
        return state.HasValue && predicate(state.Current)
 | 
			
		||||
            ? ParseResultBuilder.Succeed<TToken, TState, TToken>(state.Current, state.Next)
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ namespace CanonSharp.Combinator.Parsers.Primitives;
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
internal sealed class SkipParser<TToken>(int count) : PrimitiveParser<TToken, Unit>
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, Unit> Run<TState>(TState state)
 | 
			
		||||
    protected override IParseResult<TToken, Unit> Run<TState>(TState state)
 | 
			
		||||
    {
 | 
			
		||||
        List<TState> result = state.AsEnumerable<TToken, TState>().Take(count).ToList();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ namespace CanonSharp.Combinator.Parsers.Primitives;
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
internal sealed class TakeParser<TToken>(int count) : PrimitiveParser<TToken, IEnumerable<TToken>>
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, IEnumerable<TToken>> Run<TState>(TState state)
 | 
			
		||||
    protected override IParseResult<TToken, IEnumerable<TToken>> Run<TState>(TState state)
 | 
			
		||||
    {
 | 
			
		||||
        List<TState> result = state.AsEnumerable<TToken, TState>().Take(count).ToList();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,14 +8,14 @@ namespace CanonSharp.Combinator.Results;
 | 
			
		||||
/// <typeparam name="TToken">输入流的类型</typeparam>
 | 
			
		||||
/// <typeparam name="TState">输入流的读取类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">实际的结果类型</typeparam>
 | 
			
		||||
internal sealed class FailedResultWithError<TToken, TState, T>(TState state) : FailedResult<TToken, T>
 | 
			
		||||
internal sealed class FailedResultWithError<TToken, TState, T>(TState state) : IFailedResult<TToken, T>
 | 
			
		||||
    where TState : IReadState<TToken, TState>
 | 
			
		||||
{
 | 
			
		||||
    public override IReadState<TToken> State => state;
 | 
			
		||||
    public IReadState<TToken> State => state;
 | 
			
		||||
 | 
			
		||||
    public override string Message => $"Unexpected state: {state}.";
 | 
			
		||||
    public string Message => $"Unexpected state: {state}.";
 | 
			
		||||
 | 
			
		||||
    public override FailedResult<TToken, TNext> Convert<TNext>()
 | 
			
		||||
    public IFailedResult<TToken, TNext> Convert<TNext>()
 | 
			
		||||
    {
 | 
			
		||||
        return new FailedResultWithError<TToken, TState, TNext>(state);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -10,15 +10,15 @@ namespace CanonSharp.Combinator.Results;
 | 
			
		||||
/// <typeparam name="TToken">输入流类型</typeparam>
 | 
			
		||||
/// <typeparam name="TState">当前输入流状态的类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">解析结果的类型</typeparam>
 | 
			
		||||
public class FailedResultWithException<TToken, TState, T>(Exception exception, TState state) : FailedResult<TToken, T>
 | 
			
		||||
public class FailedResultWithException<TToken, TState, T>(Exception exception, TState state) : IFailedResult<TToken, T>
 | 
			
		||||
    where TState : IReadState<TToken, TState>
 | 
			
		||||
{
 | 
			
		||||
    public override IReadState<TToken> State => state;
 | 
			
		||||
    public IReadState<TToken> State => state;
 | 
			
		||||
 | 
			
		||||
    public override ParseException Exception => new(ToString(), exception);
 | 
			
		||||
    public ParseException Exception => new(ToString(), exception);
 | 
			
		||||
 | 
			
		||||
    public override string Message => $"Exception occured: {exception}.";
 | 
			
		||||
    public string Message => $"Exception occured: {exception}.";
 | 
			
		||||
 | 
			
		||||
    public override FailedResult<TToken, TNext> Convert<TNext>()
 | 
			
		||||
    public IFailedResult<TToken, TNext> Convert<TNext>()
 | 
			
		||||
        => new FailedResultWithException<TToken, TState, TNext>(exception, state);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,14 +10,14 @@ namespace CanonSharp.Combinator.Results;
 | 
			
		||||
/// <typeparam name="TToken">输入流的类型</typeparam>
 | 
			
		||||
/// <typeparam name="TState">读取状态类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">解析结果的类型</typeparam>
 | 
			
		||||
internal sealed class FailedResultWithMessage<TToken, TState, T>(string message, TState state) : FailedResult<TToken, T>
 | 
			
		||||
internal sealed class FailedResultWithMessage<TToken, TState, T>(string message, TState state) : IFailedResult<TToken, T>
 | 
			
		||||
    where TState : IReadState<TToken, TState>
 | 
			
		||||
{
 | 
			
		||||
    public override IReadState<TToken> State => state;
 | 
			
		||||
    public IReadState<TToken> State => state;
 | 
			
		||||
 | 
			
		||||
    public override string Message => message;
 | 
			
		||||
    public string Message => message;
 | 
			
		||||
 | 
			
		||||
    public override FailedResult<TToken, TNext> Convert<TNext>()
 | 
			
		||||
    public IFailedResult<TToken, TNext> Convert<TNext>()
 | 
			
		||||
    {
 | 
			
		||||
        return new FailedResultWithMessage<TToken, TState, TNext>(message, state);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -11,13 +11,15 @@ namespace CanonSharp.Combinator.Results;
 | 
			
		||||
/// <typeparam name="TState">输入流的状态类型</typeparam>
 | 
			
		||||
/// <typeparam name="T">解析结果的类型</typeparam>
 | 
			
		||||
internal sealed class InternalSuccessfulResult<TToken, TState, T>(T result, TState state)
 | 
			
		||||
    : SuccessfulResult<TToken, T>(result)
 | 
			
		||||
    : ISuccessfulResult<TToken, T>
 | 
			
		||||
    where TState : IReadState<TToken, TState>
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<TToken, TResult> RunNext<TNext, TResult>(Parser<TToken, TNext> parser,
 | 
			
		||||
        Func<ParseResult<TToken, TNext>, ParseResult<TToken, TResult>> continuation)
 | 
			
		||||
    public T Value => result;
 | 
			
		||||
 | 
			
		||||
    public IParseResult<TToken, TResult> RunNext<TNext, TResult>(IParser<TToken, TNext> parser,
 | 
			
		||||
        Func<IParseResult<TToken, TNext>, IParseResult<TToken, TResult>> continuation)
 | 
			
		||||
        => parser.Run(state, continuation);
 | 
			
		||||
 | 
			
		||||
    public override ParseResult<TToken, TResult> Map<TResult>(Func<T, TResult> map)
 | 
			
		||||
    public IParseResult<TToken, TResult> Map<TResult>(Func<T, TResult> map)
 | 
			
		||||
        => new InternalSuccessfulResult<TToken, TState, TResult>(map(Value), state);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ namespace CanonSharp.Combinator.Text;
 | 
			
		||||
/// <param name="comparison">字符串比较模式</param>
 | 
			
		||||
public class StringParser(string except, StringComparison comparison) : PrimitiveParser<char, string>
 | 
			
		||||
{
 | 
			
		||||
    protected override ParseResult<char, string> Run<TState>(TState state)
 | 
			
		||||
    protected override IParseResult<char, string> Run<TState>(TState state)
 | 
			
		||||
    {
 | 
			
		||||
        TState[] states = state.AsEnumerable<char, TState>().Take(except.Length).ToArray();
 | 
			
		||||
        string actual = new(states.Select(x => x.Current).ToArray());
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ public static class TextParserBuilder
 | 
			
		||||
    /// <param name="token">识别的单个字符</param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, char> Char(char token) => Satisfy<char>(x => x == token);
 | 
			
		||||
    public static IParser<char, char> Char(char token) => Satisfy<char>(x => x == token);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 忽略大小写识别单个字符
 | 
			
		||||
@@ -21,7 +21,7 @@ public static class TextParserBuilder
 | 
			
		||||
    /// <param name="token"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, char> CharIgnoreCase(char token) =>
 | 
			
		||||
    public static IParser<char, char> CharIgnoreCase(char token) =>
 | 
			
		||||
        Satisfy<char>(x => char.ToUpperInvariant(x) == char.ToUpperInvariant(token));
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -30,7 +30,7 @@ public static class TextParserBuilder
 | 
			
		||||
    /// <param name="candidate"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, char> OneOf(string candidate) => Satisfy<char>(candidate.Contains);
 | 
			
		||||
    public static IParser<char, char> OneOf(string candidate) => Satisfy<char>(candidate.Contains);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 忽略大小写识别字符串中的一个字符
 | 
			
		||||
@@ -38,7 +38,7 @@ public static class TextParserBuilder
 | 
			
		||||
    /// <param name="candidate"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, char> OneOfIgnoreCase(string candidate) =>
 | 
			
		||||
    public static IParser<char, char> OneOfIgnoreCase(string candidate) =>
 | 
			
		||||
        Satisfy<char>(x => candidate.Contains(x, StringComparison.OrdinalIgnoreCase));
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -48,7 +48,7 @@ public static class TextParserBuilder
 | 
			
		||||
    /// <param name="comparison">字符串比较方法</param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, string> String(string except, StringComparison comparison) =>
 | 
			
		||||
    public static IParser<char, string> String(string except, StringComparison comparison) =>
 | 
			
		||||
        new StringParser(except, comparison);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -57,7 +57,7 @@ public static class TextParserBuilder
 | 
			
		||||
    /// <param name="except"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, string> String(string except) => String(except, StringComparison.Ordinal);
 | 
			
		||||
    public static IParser<char, string> String(string except) => String(except, StringComparison.Ordinal);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 忽略大小写识别一个字符串
 | 
			
		||||
@@ -65,7 +65,7 @@ public static class TextParserBuilder
 | 
			
		||||
    /// <param name="except"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, string> StringIgnoreCase(string except) =>
 | 
			
		||||
    public static IParser<char, string> StringIgnoreCase(string except) =>
 | 
			
		||||
        String(except, StringComparison.OrdinalIgnoreCase);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -75,28 +75,28 @@ public static class TextParserBuilder
 | 
			
		||||
    /// <param name="end">包括的终止字符</param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, char> Range(char start, char end) => Satisfy<char>(x => x >= start && x <= end);
 | 
			
		||||
    public static IParser<char, char> Range(char start, char end) => Satisfy<char>(x => x >= start && x <= end);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 识别Unicode字符类别的解析器
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, char> Letter() => Satisfy<char>(char.IsLetter);
 | 
			
		||||
    public static IParser<char, char> Letter() => Satisfy<char>(char.IsLetter);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 识别Unicode数字类别的解析器
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, char> Digit() => Satisfy<char>(char.IsDigit);
 | 
			
		||||
    public static IParser<char, char> Digit() => Satisfy<char>(char.IsDigit);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 识别ASCII字符类别的解析器
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, char> AsciiLetter() =>
 | 
			
		||||
    public static IParser<char, char> AsciiLetter() =>
 | 
			
		||||
        Satisfy<char>(x => x is >= 'a' and <= 'z' or >= 'A' and <= 'Z');
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -104,20 +104,20 @@ public static class TextParserBuilder
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, char> AsciiDigit() => Satisfy<char>(x => x is >= '0' and <= '9');
 | 
			
		||||
    public static IParser<char, char> AsciiDigit() => Satisfy<char>(x => x is >= '0' and <= '9');
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 识别Unicode空白类型的字符
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, char> Space() => Satisfy<char>(char.IsWhiteSpace);
 | 
			
		||||
    public static IParser<char, char> Space() => Satisfy<char>(char.IsWhiteSpace);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 识别所有的换行符
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
    public static Parser<char, string> LineBreak() =>
 | 
			
		||||
    public static IParser<char, string> LineBreak() =>
 | 
			
		||||
        OneOf("\u000D\u000A\u0085\u2028\u2029\n").Map(x => x.ToString()) | String("\r\n");
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,9 +6,9 @@ namespace CanonSharp.Combinator.Text;
 | 
			
		||||
 | 
			
		||||
public static class TextParserExtensions
 | 
			
		||||
{
 | 
			
		||||
    public static Parser<char, T> SkipSpaces<T>(this Parser<char, T> parser)
 | 
			
		||||
    public static IParser<char, T> SkipSpaces<T>(this IParser<char, T> parser)
 | 
			
		||||
        => Space().SkipTill(parser);
 | 
			
		||||
 | 
			
		||||
    public static Parser<char, T> SkipSpaceAndLineBreak<T>(this Parser<char, T> parser)
 | 
			
		||||
    public static IParser<char, T> SkipSpaceAndLineBreak<T>(this IParser<char, T> parser)
 | 
			
		||||
        => (Space().Map(x => x.ToString()) | LineBreak()).SkipTill(parser);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
        <TargetFramework>net8.0</TargetFramework>
 | 
			
		||||
        <ImplicitUsings>enable</ImplicitUsings>
 | 
			
		||||
        <Nullable>enable</Nullable>
 | 
			
		||||
        <RootNamespace>CanonSharp.Common</RootNamespace>
 | 
			
		||||
    </PropertyGroup>
 | 
			
		||||
 | 
			
		||||
    <ItemGroup>
 | 
			
		||||
@@ -15,8 +16,4 @@
 | 
			
		||||
      <ProjectReference Include="..\CanonSharp.Combinator\CanonSharp.Combinator.csproj" />
 | 
			
		||||
    </ItemGroup>
 | 
			
		||||
 | 
			
		||||
    <ItemGroup>
 | 
			
		||||
      <Folder Include="SyntaxTree\" />
 | 
			
		||||
    </ItemGroup>
 | 
			
		||||
 | 
			
		||||
</Project>
 | 
			
		||||
@@ -4,11 +4,11 @@ using CanonSharp.Combinator.Extensions;
 | 
			
		||||
using static CanonSharp.Combinator.Text.TextParserBuilder;
 | 
			
		||||
using static CanonSharp.Combinator.ParserBuilder;
 | 
			
		||||
 | 
			
		||||
namespace CanonSharp.Common.Scanner;
 | 
			
		||||
namespace CanonSharp.Pascal.Scanner;
 | 
			
		||||
 | 
			
		||||
public sealed class LexicalScanner
 | 
			
		||||
{
 | 
			
		||||
    private readonly Parser<char, IEnumerable<LexicalToken>> _parser = PascalParser();
 | 
			
		||||
    private readonly IParser<char, IEnumerable<LexicalToken>> _parser = PascalParser();
 | 
			
		||||
 | 
			
		||||
    public IEnumerable<LexicalToken> Tokenize<TState>(TState state)
 | 
			
		||||
        where TState : IReadState<char, TState>
 | 
			
		||||
@@ -16,7 +16,7 @@ public sealed class LexicalScanner
 | 
			
		||||
        return _parser.Parse(state).Value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Parser<char, LexicalToken> KeywordParser()
 | 
			
		||||
    public static IParser<char, LexicalToken> KeywordParser()
 | 
			
		||||
    {
 | 
			
		||||
        return from value in Choice(StringIgnoreCase("program"),
 | 
			
		||||
                StringIgnoreCase("const"),
 | 
			
		||||
@@ -49,16 +49,16 @@ public sealed class LexicalScanner
 | 
			
		||||
            select new LexicalToken(LexicalTokenType.Keyword, value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Parser<char, LexicalToken> DelimiterParser()
 | 
			
		||||
    public static IParser<char, LexicalToken> DelimiterParser()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, LexicalToken> semicolonParser = from token in Char(':')
 | 
			
		||||
        IParser<char, LexicalToken> semicolonParser = from token in Char(':')
 | 
			
		||||
            from _ in Char('=').LookAhead().Not()
 | 
			
		||||
            select new LexicalToken(LexicalTokenType.Delimiter, token.ToString());
 | 
			
		||||
        Parser<char, LexicalToken> periodParser = from token in Char('.')
 | 
			
		||||
        IParser<char, LexicalToken> periodParser = from token in Char('.')
 | 
			
		||||
            from _ in Char('.').LookAhead().Not()
 | 
			
		||||
            select new LexicalToken(LexicalTokenType.Delimiter, ".");
 | 
			
		||||
 | 
			
		||||
        Parser<char, LexicalToken> singleCharTokenParser = from token in Choice(
 | 
			
		||||
        IParser<char, LexicalToken> singleCharTokenParser = from token in Choice(
 | 
			
		||||
                String(","),
 | 
			
		||||
                String(";"),
 | 
			
		||||
                String("("),
 | 
			
		||||
@@ -71,17 +71,17 @@ public sealed class LexicalScanner
 | 
			
		||||
        return singleCharTokenParser | semicolonParser | periodParser;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Parser<char, LexicalToken> OperatorParser()
 | 
			
		||||
    public static IParser<char, LexicalToken> OperatorParser()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, LexicalToken> lessParser = from token in Char('<')
 | 
			
		||||
        IParser<char, LexicalToken> lessParser = from token in Char('<')
 | 
			
		||||
            from _ in Char('=').LookAhead().Not()
 | 
			
		||||
            select new LexicalToken(LexicalTokenType.Operator, "<");
 | 
			
		||||
 | 
			
		||||
        Parser<char, LexicalToken> greaterParser = from token in Char('>')
 | 
			
		||||
        IParser<char, LexicalToken> greaterParser = from token in Char('>')
 | 
			
		||||
            from _ in Char('=').LookAhead().Not()
 | 
			
		||||
            select new LexicalToken(LexicalTokenType.Operator, ">");
 | 
			
		||||
 | 
			
		||||
        Parser<char, LexicalToken> otherParsers = from token in Choice(
 | 
			
		||||
        IParser<char, LexicalToken> otherParsers = from token in Choice(
 | 
			
		||||
                String("="),
 | 
			
		||||
                String("!="),
 | 
			
		||||
                String("<="),
 | 
			
		||||
@@ -96,14 +96,14 @@ public sealed class LexicalScanner
 | 
			
		||||
        return otherParsers | lessParser | greaterParser;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Parser<char, LexicalToken> ConstIntegerParser()
 | 
			
		||||
    public static IParser<char, LexicalToken> ConstIntegerParser()
 | 
			
		||||
    {
 | 
			
		||||
        return from nums in AsciiDigit().Many1()
 | 
			
		||||
            from _ in Char('.').LookAhead().Not()
 | 
			
		||||
            select new LexicalToken(LexicalTokenType.ConstInteger, new string(nums.ToArray()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Parser<char, LexicalToken> ConstFloatParser()
 | 
			
		||||
    public static IParser<char, LexicalToken> ConstFloatParser()
 | 
			
		||||
    {
 | 
			
		||||
        return from integer in AsciiDigit().Many1()
 | 
			
		||||
            from _ in Char('.')
 | 
			
		||||
@@ -112,24 +112,24 @@ public sealed class LexicalScanner
 | 
			
		||||
                new string(integer.ToArray()) + '.' + new string(fraction.ToArray()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Parser<char, LexicalToken> IdentifierParser()
 | 
			
		||||
    public static IParser<char, LexicalToken> IdentifierParser()
 | 
			
		||||
    {
 | 
			
		||||
        return from first in AsciiLetter() | Char('_')
 | 
			
		||||
            from second in (AsciiLetter() | AsciiDigit() | Char('_')).Many()
 | 
			
		||||
            select new LexicalToken(LexicalTokenType.Identifier, first + new string(second.ToArray()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Parser<char, Unit> CommentParser()
 | 
			
		||||
    public static IParser<char, Unit> CommentParser()
 | 
			
		||||
    {
 | 
			
		||||
        return Any<char>().Quote(Char('{'), Char('}')).Map(_ => Unit.Instance);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Parser<char, Unit> JunkParser()
 | 
			
		||||
    public static IParser<char, Unit> JunkParser()
 | 
			
		||||
    {
 | 
			
		||||
        return Space().Map(_ => Unit.Instance) | LineBreak().Map(_ => Unit.Instance) | CommentParser();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Parser<char, LexicalToken> CharParser()
 | 
			
		||||
    public static IParser<char, LexicalToken> CharParser()
 | 
			
		||||
    {
 | 
			
		||||
        return from str in Any<char>().Quote(Char('\'')).Map(x => new string(x.ToArray()))
 | 
			
		||||
            select str.Length <= 1
 | 
			
		||||
@@ -137,7 +137,7 @@ public sealed class LexicalScanner
 | 
			
		||||
                : new LexicalToken(LexicalTokenType.String, str);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Parser<char, IEnumerable<LexicalToken>> PascalParser()
 | 
			
		||||
    public static IParser<char, IEnumerable<LexicalToken>> PascalParser()
 | 
			
		||||
    {
 | 
			
		||||
        return JunkParser().SkipTill(Choice(KeywordParser(),
 | 
			
		||||
            DelimiterParser(),
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
namespace CanonSharp.Common.Scanner;
 | 
			
		||||
namespace CanonSharp.Pascal.Scanner;
 | 
			
		||||
 | 
			
		||||
public enum LexicalTokenType
 | 
			
		||||
{
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
using CanonSharp.Combinator.Abstractions;
 | 
			
		||||
 | 
			
		||||
namespace CanonSharp.Common.Scanner;
 | 
			
		||||
namespace CanonSharp.Pascal.Scanner;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 字符串输入流状态
 | 
			
		||||
@@ -23,7 +23,7 @@
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ProjectReference Include="..\CanonSharp.Common\CanonSharp.Common.csproj" />
 | 
			
		||||
    <ProjectReference Include="..\CanonSharp.Pascal\CanonSharp.Pascal.csproj" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
</Project>
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ public class BasicParsersTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void AlternativeTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Token('a') | Token('b');
 | 
			
		||||
        IParser<char, char> parser = Token('a') | Token('b');
 | 
			
		||||
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'a', "abc");
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'b', "bcd");
 | 
			
		||||
@@ -26,7 +26,7 @@ public class BasicParsersTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void BindTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Token('a').Bind(_ => Token('b')).Bind(_ => Token('c'));
 | 
			
		||||
        IParser<char, char> parser = Token('a').Bind(_ => Token('b')).Bind(_ => Token('c'));
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'c', "abc");
 | 
			
		||||
        ValidateFailedResult(parser, "acd");
 | 
			
		||||
 | 
			
		||||
@@ -36,7 +36,7 @@ public class BasicParsersTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void MapTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, string> parser = Token('a').Map(c => $"{c}");
 | 
			
		||||
        IParser<char, string> parser = Token('a').Map(c => $"{c}");
 | 
			
		||||
        ValidateSuccessfulResult(parser, "a", "abc");
 | 
			
		||||
 | 
			
		||||
        parser = Token('a').Map("test");
 | 
			
		||||
@@ -46,7 +46,7 @@ public class BasicParsersTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void NextTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Token('a').Next(_ => Token('a'), _ => Token('b'));
 | 
			
		||||
        IParser<char, char> parser = Token('a').Next(_ => Token('a'), _ => Token('b'));
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'a', "aaa");
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'b', "bbb");
 | 
			
		||||
 | 
			
		||||
@@ -61,7 +61,7 @@ public class BasicParsersTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void NextTest2()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, string> parser = Token('a').Next(_ => "123", _ => Pure<char, string>("456"));
 | 
			
		||||
        IParser<char, string> parser = Token('a').Next(_ => "123", _ => Pure<char, string>("456"));
 | 
			
		||||
        ValidateSuccessfulResult(parser, "123", "aaa");
 | 
			
		||||
        ValidateSuccessfulResult(parser, "456", "bbb");
 | 
			
		||||
 | 
			
		||||
@@ -77,7 +77,7 @@ public class BasicParsersTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void FixTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Fix<char, Unit>(self => Token('a').Next(_ => self, Unit.Instance))
 | 
			
		||||
        IParser<char, char> parser = Fix<char, Unit>(self => Token('a').Next(_ => self, Unit.Instance))
 | 
			
		||||
            .Bind(_ => Token('b'));
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'b', "aaaaab");
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void ChoiceTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Choice(Token('a'), Token('b'), Token('c'));
 | 
			
		||||
        IParser<char, char> parser = Choice(Token('a'), Token('b'), Token('c'));
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'a', "abc");
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'b', "bcd");
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'c', "cde");
 | 
			
		||||
@@ -25,10 +25,10 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void SequenceTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, IEnumerable<char>> parser = Sequence(Token('a'), Token('b'), Token('c'));
 | 
			
		||||
        IParser<char, IEnumerable<char>> parser = Sequence(Token('a'), Token('b'), Token('c'));
 | 
			
		||||
        ValidateSuccessfulResult(parser, ['a', 'b', 'c'], "abc");
 | 
			
		||||
 | 
			
		||||
        IEnumerable<Parser<char, char>> parsers = [Token('a'), Token('b'), Token('c')];
 | 
			
		||||
        IEnumerable<IParser<char, char>> parsers = [Token('a'), Token('b'), Token('c')];
 | 
			
		||||
        parser = Sequence(parsers);
 | 
			
		||||
        ValidateSuccessfulResult(parser, ['a', 'b', 'c'], "abc");
 | 
			
		||||
    }
 | 
			
		||||
@@ -36,7 +36,7 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void LeftRightTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Token('a').Left(Token('b'));
 | 
			
		||||
        IParser<char, char> parser = Token('a').Left(Token('b'));
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'a', "ab");
 | 
			
		||||
 | 
			
		||||
        parser = Token('a').Right(Token('b'));
 | 
			
		||||
@@ -46,7 +46,7 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void ManyTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, IEnumerable<char>> parser = Token('a').Many();
 | 
			
		||||
        IParser<char, IEnumerable<char>> parser = Token('a').Many();
 | 
			
		||||
        ValidateSuccessfulResult(parser, [], "bbb");
 | 
			
		||||
        ValidateSuccessfulResult(parser, ['a', 'a', 'a'], "aaa");
 | 
			
		||||
 | 
			
		||||
@@ -58,7 +58,7 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void SkipManyTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Token('a').SkipMany().Right(Token('b'));
 | 
			
		||||
        IParser<char, char> parser = Token('a').SkipMany().Right(Token('b'));
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'b', "aaaab");
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'b', "bbbb");
 | 
			
		||||
 | 
			
		||||
@@ -72,7 +72,7 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    {
 | 
			
		||||
        // 等效于Many1
 | 
			
		||||
        // 但是不返回中间结果
 | 
			
		||||
        Parser<char, char> parser = Token('a').Chain(Token);
 | 
			
		||||
        IParser<char, char> parser = Token('a').Chain(Token);
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'a', "aa");
 | 
			
		||||
        ValidateFailedResult(parser, "bb");
 | 
			
		||||
 | 
			
		||||
@@ -84,7 +84,7 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void ManyTillTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, IEnumerable<char>> parser = Token('a').ManyTill(Token('b').LookAhead());
 | 
			
		||||
        IParser<char, IEnumerable<char>> parser = Token('a').ManyTill(Token('b').LookAhead());
 | 
			
		||||
        ValidateSuccessfulResult(parser, ['a', 'a', 'a'], "aaab");
 | 
			
		||||
        ValidateSuccessfulResult(parser, [], "b");
 | 
			
		||||
 | 
			
		||||
@@ -96,7 +96,7 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void SkipTillTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Token('a').SkipTill(Token('b'));
 | 
			
		||||
        IParser<char, char> parser = Token('a').SkipTill(Token('b'));
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'b', "aaab");
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'b', "b");
 | 
			
		||||
 | 
			
		||||
@@ -108,7 +108,7 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void TakeTillTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, IEnumerable<char>> parser = TakeTill(Token('b').LookAhead());
 | 
			
		||||
        IParser<char, IEnumerable<char>> parser = TakeTill(Token('b').LookAhead());
 | 
			
		||||
        ValidateSuccessfulResult(parser, ['a', 'a'], "aab");
 | 
			
		||||
        ValidateSuccessfulResult(parser, [], "b");
 | 
			
		||||
 | 
			
		||||
@@ -120,7 +120,7 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void MatchTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Token('b').Match();
 | 
			
		||||
        IParser<char, char> parser = Token('b').Match();
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'b', "asdfasdfasdfasdfb");
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'b', "b");
 | 
			
		||||
    }
 | 
			
		||||
@@ -128,7 +128,7 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void QuoteTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, IEnumerable<char>> parser = Any<char>().Quote(Token('['), Token(']'));
 | 
			
		||||
        IParser<char, IEnumerable<char>> parser = Any<char>().Quote(Token('['), Token(']'));
 | 
			
		||||
        ValidateSuccessfulResult(parser, ['1', '2', '3'], "[123]");
 | 
			
		||||
 | 
			
		||||
        parser = Any<char>().Quote(Token('\''));
 | 
			
		||||
@@ -138,7 +138,7 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void SeparatedByTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, IEnumerable<char>> parser = Token('a').SeparatedBy(Token(','));
 | 
			
		||||
        IParser<char, IEnumerable<char>> parser = Token('a').SeparatedBy(Token(','));
 | 
			
		||||
        ValidateSuccessfulResult(parser, ['a', 'a', 'a'], "a,a,a");
 | 
			
		||||
        ValidateSuccessfulResult(parser, ['a'], "a");
 | 
			
		||||
        ValidateSuccessfulResult(parser, [], "");
 | 
			
		||||
@@ -152,7 +152,7 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void EndByTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, IEnumerable<char>> parser = Satisfy<char>(char.IsLetter).EndBy(Token('.'));
 | 
			
		||||
        IParser<char, IEnumerable<char>> parser = Satisfy<char>(char.IsLetter).EndBy(Token('.'));
 | 
			
		||||
        ValidateSuccessfulResult(parser, ['a', 'b', 'c'], "abc.");
 | 
			
		||||
        ValidateSuccessfulResult(parser, [], ".");
 | 
			
		||||
 | 
			
		||||
@@ -164,7 +164,7 @@ public class CombinatorParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void SeparatedOrEndByTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, IEnumerable<char>> parser = Satisfy<char>(char.IsLetter).SeparatedOrEndBy1(Token(','));
 | 
			
		||||
        IParser<char, IEnumerable<char>> parser = Satisfy<char>(char.IsLetter).SeparatedOrEndBy1(Token(','));
 | 
			
		||||
        ValidateSuccessfulResult(parser, ['a', 'b', 'c'], "a,b,c,");
 | 
			
		||||
        ValidateSuccessfulResult(parser, ['a', 'b', 'c'], "a,b,c");
 | 
			
		||||
        ValidateFailedResult(parser, "");
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ public class LinqTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void SelectTest1()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, string> parser = from token in Char('a')
 | 
			
		||||
        IParser<char, string> parser = from token in Char('a')
 | 
			
		||||
            select token.ToString();
 | 
			
		||||
        ValidateSuccessfulResult(parser, "a", "a");
 | 
			
		||||
        ValidateFailedResult(parser, "b");
 | 
			
		||||
@@ -19,7 +19,7 @@ public class LinqTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void SelectManyTest1()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, int> parser = from _1 in Char('a')
 | 
			
		||||
        IParser<char, int> parser = from _1 in Char('a')
 | 
			
		||||
            from _2 in Char('b')
 | 
			
		||||
            from _3 in Char('c')
 | 
			
		||||
            select 123;
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ public class ModifierParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void DoTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Token('a').Do(x => Assert.Equal('a', x)).Do(x => Assert.Equal('a', x),
 | 
			
		||||
        IParser<char, char> parser = Token('a').Do(x => Assert.Equal('a', x)).Do(x => Assert.Equal('a', x),
 | 
			
		||||
            failedResult => Assert.ThrowsAny<ParseException>(() => failedResult.Value));
 | 
			
		||||
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'a', "abc");
 | 
			
		||||
@@ -22,7 +22,7 @@ public class ModifierParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void LookAheadTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Token('a').LookAhead().Next(_ => Token('a'), _ => Token('b'));
 | 
			
		||||
        IParser<char, char> parser = Token('a').LookAhead().Next(_ => Token('a'), _ => Token('b'));
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'a', "abc");
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'b', "bcd");
 | 
			
		||||
    }
 | 
			
		||||
@@ -30,7 +30,7 @@ public class ModifierParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void NotTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Token('a').Not('b');
 | 
			
		||||
        IParser<char, char> parser = Token('a').Not('b');
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'b', "bcd");
 | 
			
		||||
 | 
			
		||||
        parser = Token('a').Not().Bind(_ => Token('b'));
 | 
			
		||||
@@ -40,7 +40,7 @@ public class ModifierParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void TryTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, string> parser = String("abc").Try("cde");
 | 
			
		||||
        IParser<char, string> parser = String("abc").Try("cde");
 | 
			
		||||
        ValidateSuccessfulResult(parser, "abc", "abc");
 | 
			
		||||
        ValidateSuccessfulResult(parser, "cde", "cde");
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ public class PrimitiveParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void PureTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Pure<char, char>('a');
 | 
			
		||||
        IParser<char, char> parser = Pure<char, char>('a');
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'a', "abc");
 | 
			
		||||
 | 
			
		||||
        parser = Pure<char, char>(_ => 'a');
 | 
			
		||||
@@ -21,18 +21,18 @@ public class PrimitiveParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void NullTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, Unit> parser = Null<char>();
 | 
			
		||||
        IParser<char, Unit> parser = Null<char>();
 | 
			
		||||
        ValidateSuccessfulResult(parser, Unit.Instance, "abc");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void FailTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Fail<char, char>();
 | 
			
		||||
        IParser<char, char> parser = Fail<char, char>();
 | 
			
		||||
        ValidateFailedResult(parser, "abc");
 | 
			
		||||
 | 
			
		||||
        parser = Fail<char, char>("Failed message");
 | 
			
		||||
        FailedResult<char, char> result = ValidateFailedResult(parser, "abc");
 | 
			
		||||
        IFailedResult<char, char> result = ValidateFailedResult(parser, "abc");
 | 
			
		||||
        Assert.Equal("Failed message", result.Message);
 | 
			
		||||
 | 
			
		||||
        parser = Fail<char, char>(x => $"{x}");
 | 
			
		||||
@@ -47,7 +47,7 @@ public class PrimitiveParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void SatisfyTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Satisfy<char>(char.IsLetter);
 | 
			
		||||
        IParser<char, char> parser = Satisfy<char>(char.IsLetter);
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'a', "abc");
 | 
			
		||||
        ValidateFailedResult(parser, "123");
 | 
			
		||||
    }
 | 
			
		||||
@@ -55,28 +55,28 @@ public class PrimitiveParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void SatisfyFailedTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Satisfy<char>(char.IsLetter);
 | 
			
		||||
        IParser<char, char> parser = Satisfy<char>(char.IsLetter);
 | 
			
		||||
        ValidateFailedResult(parser, "");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void AnyTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Any<char>();
 | 
			
		||||
        IParser<char, char> parser = Any<char>();
 | 
			
		||||
        ValidateSuccessfulResult(parser, '1', "123");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void TokenTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Token('a');
 | 
			
		||||
        IParser<char, char> parser = Token('a');
 | 
			
		||||
        ValidateSuccessfulResult(parser, 'a', "abc");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void TakeTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, IEnumerable<char>> parser = Take<char>(5);
 | 
			
		||||
        IParser<char, IEnumerable<char>> parser = Take<char>(5);
 | 
			
		||||
        ValidateSuccessfulResult(parser, ['h', 'e', 'l', 'l', 'o'], "hello");
 | 
			
		||||
        ValidateFailedResult(parser, "abc");
 | 
			
		||||
    }
 | 
			
		||||
@@ -84,7 +84,7 @@ public class PrimitiveParserTests : ParserTestsBase
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void SkipTest()
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Skip<char>(5).Bind(_ => Token(','));
 | 
			
		||||
        IParser<char, char> parser = Skip<char>(5).Bind(_ => Token(','));
 | 
			
		||||
        ValidateSuccessfulResult(parser, ',', "hello,world.");
 | 
			
		||||
        ValidateFailedResult(parser, "abc");
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
using CanonSharp.Combinator.Extensions;
 | 
			
		||||
using CanonSharp.Common.Scanner;
 | 
			
		||||
using CanonSharp.Pascal.Scanner;
 | 
			
		||||
 | 
			
		||||
namespace CanonSharp.Tests.LexicalAnalyzerTests;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
using CanonSharp.Common.Scanner;
 | 
			
		||||
using CanonSharp.Pascal.Scanner;
 | 
			
		||||
using CanonSharp.Tests.Utils;
 | 
			
		||||
 | 
			
		||||
namespace CanonSharp.Tests.ScannerTest;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
using CanonSharp.Combinator;
 | 
			
		||||
using CanonSharp.Combinator.Abstractions;
 | 
			
		||||
using CanonSharp.Combinator.Extensions;
 | 
			
		||||
using CanonSharp.Common.Scanner;
 | 
			
		||||
using CanonSharp.Pascal.Scanner;
 | 
			
		||||
using CanonSharp.Tests.Utils;
 | 
			
		||||
 | 
			
		||||
namespace CanonSharp.Tests.ScannerTest;
 | 
			
		||||
@@ -29,7 +29,7 @@ public class LexicalTokenParserTest : LexicalTestBase
 | 
			
		||||
    [InlineData("while")]
 | 
			
		||||
    public void KeywordParserTest(string literalValue)
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, LexicalToken> keyword = LexicalScanner.KeywordParser();
 | 
			
		||||
        IParser<char, LexicalToken> keyword = LexicalScanner.KeywordParser();
 | 
			
		||||
        ValidateSuccessfulParser(keyword, LexicalTokenType.Keyword, literalValue, literalValue);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -39,7 +39,7 @@ public class LexicalTokenParserTest : LexicalTestBase
 | 
			
		||||
    [InlineData("todo")]
 | 
			
		||||
    public void FailedKeywordParserTest(string input)
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, LexicalToken> keyword = LexicalScanner.KeywordParser();
 | 
			
		||||
        IParser<char, LexicalToken> keyword = LexicalScanner.KeywordParser();
 | 
			
		||||
        ValidateFailedParser(keyword, input);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -55,7 +55,7 @@ public class LexicalTokenParserTest : LexicalTestBase
 | 
			
		||||
    [InlineData("..")]
 | 
			
		||||
    public void DelimiterParserTest(string literalValue)
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, LexicalToken> delimiter = LexicalScanner.DelimiterParser();
 | 
			
		||||
        IParser<char, LexicalToken> delimiter = LexicalScanner.DelimiterParser();
 | 
			
		||||
        ValidateSuccessfulParser(delimiter, LexicalTokenType.Delimiter, literalValue, literalValue);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -63,7 +63,7 @@ public class LexicalTokenParserTest : LexicalTestBase
 | 
			
		||||
    [InlineData(":=")]
 | 
			
		||||
    public void FailedDelimiterParserTest(string input)
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, LexicalToken> delimiter = LexicalScanner.DelimiterParser();
 | 
			
		||||
        IParser<char, LexicalToken> delimiter = LexicalScanner.DelimiterParser();
 | 
			
		||||
        ValidateFailedParser(delimiter, input);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -81,7 +81,7 @@ public class LexicalTokenParserTest : LexicalTestBase
 | 
			
		||||
    [InlineData(":=")]
 | 
			
		||||
    public void OperatorParserTest(string literalValue)
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, LexicalToken> operatorParser = LexicalScanner.OperatorParser();
 | 
			
		||||
        IParser<char, LexicalToken> operatorParser = LexicalScanner.OperatorParser();
 | 
			
		||||
        ValidateSuccessfulParser(operatorParser, LexicalTokenType.Operator, literalValue, literalValue);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -94,7 +94,7 @@ public class LexicalTokenParserTest : LexicalTestBase
 | 
			
		||||
    [InlineData("andand")]
 | 
			
		||||
    public void IdentifierParserTest(string literalValue)
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, LexicalToken> identifier = LexicalScanner.IdentifierParser();
 | 
			
		||||
        IParser<char, LexicalToken> identifier = LexicalScanner.IdentifierParser();
 | 
			
		||||
 | 
			
		||||
        ValidateSuccessfulParser(identifier, LexicalTokenType.Identifier, literalValue, literalValue);
 | 
			
		||||
    }
 | 
			
		||||
@@ -105,7 +105,7 @@ public class LexicalTokenParserTest : LexicalTestBase
 | 
			
		||||
    public void ConstIntegerTest(int value, string input)
 | 
			
		||||
    {
 | 
			
		||||
        StringReadState state = new(input);
 | 
			
		||||
        ParseResult<char, LexicalToken> result = LexicalScanner.ConstIntegerParser().Parse(state);
 | 
			
		||||
        IParseResult<char, LexicalToken> result = LexicalScanner.ConstIntegerParser().Parse(state);
 | 
			
		||||
 | 
			
		||||
        Assert.Equal(LexicalTokenType.ConstInteger, result.Value.TokenType);
 | 
			
		||||
        Assert.Equal(value, int.Parse(result.Value.LiteralValue));
 | 
			
		||||
@@ -117,7 +117,7 @@ public class LexicalTokenParserTest : LexicalTestBase
 | 
			
		||||
    public void ConstFloatTest(double value, string input)
 | 
			
		||||
    {
 | 
			
		||||
        StringReadState state = new(input);
 | 
			
		||||
        ParseResult<char, LexicalToken> result = LexicalScanner.ConstFloatParser().Parse(state);
 | 
			
		||||
        IParseResult<char, LexicalToken> result = LexicalScanner.ConstFloatParser().Parse(state);
 | 
			
		||||
 | 
			
		||||
        Assert.Equal(LexicalTokenType.ConstFloat, result.Value.TokenType);
 | 
			
		||||
        Assert.Equal(value, double.Parse(result.Value.LiteralValue));
 | 
			
		||||
@@ -129,7 +129,7 @@ public class LexicalTokenParserTest : LexicalTestBase
 | 
			
		||||
    public void CharTest(char value, string input)
 | 
			
		||||
    {
 | 
			
		||||
        StringReadState state = new(input);
 | 
			
		||||
        ParseResult<char, LexicalToken> result = LexicalScanner.CharParser().Parse(state);
 | 
			
		||||
        IParseResult<char, LexicalToken> result = LexicalScanner.CharParser().Parse(state);
 | 
			
		||||
 | 
			
		||||
        Assert.Equal(LexicalTokenType.Character, result.Value.TokenType);
 | 
			
		||||
        Assert.Equal(value, char.Parse(result.Value.LiteralValue));
 | 
			
		||||
@@ -140,7 +140,7 @@ public class LexicalTokenParserTest : LexicalTestBase
 | 
			
		||||
    public void StringTest(string value, string input)
 | 
			
		||||
    {
 | 
			
		||||
        StringReadState state = new(input);
 | 
			
		||||
        ParseResult<char, LexicalToken> result = LexicalScanner.CharParser().Parse(state);
 | 
			
		||||
        IParseResult<char, LexicalToken> result = LexicalScanner.CharParser().Parse(state);
 | 
			
		||||
 | 
			
		||||
        Assert.Equal(LexicalTokenType.String, result.Value.TokenType);
 | 
			
		||||
        Assert.Equal(value, result.Value.LiteralValue);
 | 
			
		||||
@@ -152,7 +152,7 @@ public class LexicalTokenParserTest : LexicalTestBase
 | 
			
		||||
    public void CommentTest(string input)
 | 
			
		||||
    {
 | 
			
		||||
        StringReadState state = new(input);
 | 
			
		||||
        ParseResult<char, Unit> result = LexicalScanner.CommentParser().Parse(state);
 | 
			
		||||
        IParseResult<char, Unit> result = LexicalScanner.CommentParser().Parse(state);
 | 
			
		||||
 | 
			
		||||
        Assert.Equal(Unit.Instance, result.Value);
 | 
			
		||||
    }
 | 
			
		||||
@@ -168,8 +168,8 @@ public class LexicalTokenParserTest : LexicalTestBase
 | 
			
		||||
    public void JunkTest(string input)
 | 
			
		||||
    {
 | 
			
		||||
        StringReadState state = new(input);
 | 
			
		||||
        Parser<char, LexicalToken> parser = LexicalScanner.JunkParser().SkipTill(LexicalScanner.KeywordParser());
 | 
			
		||||
        ParseResult<char, LexicalToken> result = parser.Parse(state);
 | 
			
		||||
        IParser<char, LexicalToken> parser = LexicalScanner.JunkParser().SkipTill(LexicalScanner.KeywordParser());
 | 
			
		||||
        IParseResult<char, LexicalToken> result = parser.Parse(state);
 | 
			
		||||
 | 
			
		||||
        Assert.Equal(LexicalTokenType.Keyword, result.Value.TokenType);
 | 
			
		||||
        Assert.Equal("program", result.Value.LiteralValue);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
using CanonSharp.Combinator.Abstractions;
 | 
			
		||||
using CanonSharp.Combinator.Extensions;
 | 
			
		||||
using CanonSharp.Combinator.Text;
 | 
			
		||||
using CanonSharp.Common.Scanner;
 | 
			
		||||
using CanonSharp.Pascal.Scanner;
 | 
			
		||||
using CanonSharp.Tests.Utils;
 | 
			
		||||
using static CanonSharp.Combinator.Text.TextParserBuilder;
 | 
			
		||||
 | 
			
		||||
@@ -24,7 +24,7 @@ public class TextParserTests : ParserTestsBase
 | 
			
		||||
    [InlineData('d', "d")]
 | 
			
		||||
    public void OneOfTest(char except, string input)
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = OneOf("abcd");
 | 
			
		||||
        IParser<char, char> parser = OneOf("abcd");
 | 
			
		||||
        ValidateSuccessfulResult(parser, except, input);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -39,7 +39,7 @@ public class TextParserTests : ParserTestsBase
 | 
			
		||||
    [InlineData('D', "D")]
 | 
			
		||||
    public void OneOfIgnoreCaseTest(char except, string input)
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = OneOfIgnoreCase("abcd");
 | 
			
		||||
        IParser<char, char> parser = OneOfIgnoreCase("abcd");
 | 
			
		||||
        ValidateSuccessfulResult(parser, except, input);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -50,7 +50,7 @@ public class TextParserTests : ParserTestsBase
 | 
			
		||||
    [InlineData("Hello,World.")]
 | 
			
		||||
    public void StringIgnoreCaseTest(string literalValue)
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, string> parser = StringIgnoreCase("hello,world.");
 | 
			
		||||
        IParser<char, string> parser = StringIgnoreCase("hello,world.");
 | 
			
		||||
        ValidateSuccessfulResult(parser, literalValue, literalValue);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -60,7 +60,7 @@ public class TextParserTests : ParserTestsBase
 | 
			
		||||
    [InlineData('9')]
 | 
			
		||||
    public void RangeTest(char except)
 | 
			
		||||
    {
 | 
			
		||||
        Parser<char, char> parser = Range('0', '9');
 | 
			
		||||
        IParser<char, char> parser = Range('0', '9');
 | 
			
		||||
        ValidateSuccessfulResult(parser, except, except.ToString());
 | 
			
		||||
 | 
			
		||||
        ValidateFailedResult(parser, "abc");
 | 
			
		||||
@@ -161,8 +161,8 @@ public class TextParserTests : ParserTestsBase
 | 
			
		||||
                                    test
 | 
			
		||||
                                    """);
 | 
			
		||||
 | 
			
		||||
        Parser<char, IEnumerable<string>> parser = StringIgnoreCase("test").SkipSpaceAndLineBreak().Many();
 | 
			
		||||
        ParseResult<char, IEnumerable<string>> result = parser.Parse(state);
 | 
			
		||||
        IParser<char, IEnumerable<string>> parser = StringIgnoreCase("test").SkipSpaceAndLineBreak().Many();
 | 
			
		||||
        IParseResult<char, IEnumerable<string>> result = parser.Parse(state);
 | 
			
		||||
 | 
			
		||||
        Assert.All(result.Value, x => Assert.Equal("test", x.ToLower()));
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,33 +1,33 @@
 | 
			
		||||
using CanonSharp.Combinator;
 | 
			
		||||
using CanonSharp.Combinator.Abstractions;
 | 
			
		||||
using CanonSharp.Common.Scanner;
 | 
			
		||||
using CanonSharp.Pascal.Scanner;
 | 
			
		||||
 | 
			
		||||
namespace CanonSharp.Tests.Utils;
 | 
			
		||||
 | 
			
		||||
public abstract class LexicalTestBase
 | 
			
		||||
{
 | 
			
		||||
    protected static void ValidateSuccessfulParser(Parser<char, LexicalToken> parser, LexicalTokenType exceptedType,
 | 
			
		||||
    protected static void ValidateSuccessfulParser(IParser<char, LexicalToken> parser, LexicalTokenType exceptedType,
 | 
			
		||||
        string literalValue, string input)
 | 
			
		||||
    {
 | 
			
		||||
        StringReadState state = new(input);
 | 
			
		||||
        ParseResult<char, LexicalToken> result = parser.Parse(state);
 | 
			
		||||
        IParseResult<char, LexicalToken> result = parser.Parse(state);
 | 
			
		||||
 | 
			
		||||
        Assert.Equal(exceptedType, result.Value.TokenType);
 | 
			
		||||
        Assert.Equal(literalValue, result.Value.LiteralValue);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected static void ValidateFailedParser(Parser<char, LexicalToken> parser, string input)
 | 
			
		||||
    protected static void ValidateFailedParser(IParser<char, LexicalToken> parser, string input)
 | 
			
		||||
    {
 | 
			
		||||
        StringReadState state = new(input);
 | 
			
		||||
        ParseResult<char, LexicalToken> result = parser.Parse(state);
 | 
			
		||||
        IParseResult<char, LexicalToken> result = parser.Parse(state);
 | 
			
		||||
        Assert.ThrowsAny<ParseException>(() => result.Value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected static void ValidateLexicalTokens(Parser<char, IEnumerable<LexicalToken>> parser, string input,
 | 
			
		||||
    protected static void ValidateLexicalTokens(IParser<char, IEnumerable<LexicalToken>> parser, string input,
 | 
			
		||||
        IEnumerable<(LexicalTokenType, string)> exceptedResult)
 | 
			
		||||
    {
 | 
			
		||||
        StringReadState state = new(input);
 | 
			
		||||
        ParseResult<char, IEnumerable<LexicalToken>> result = parser.Parse(state);
 | 
			
		||||
        IParseResult<char, IEnumerable<LexicalToken>> result = parser.Parse(state);
 | 
			
		||||
 | 
			
		||||
        foreach (((LexicalTokenType exceptedType, string exceptedValue), LexicalToken token) in exceptedResult.Zip(
 | 
			
		||||
                     result.Value))
 | 
			
		||||
 
 | 
			
		||||
@@ -1,26 +1,26 @@
 | 
			
		||||
using CanonSharp.Combinator;
 | 
			
		||||
using CanonSharp.Combinator.Abstractions;
 | 
			
		||||
using CanonSharp.Common.Scanner;
 | 
			
		||||
using CanonSharp.Pascal.Scanner;
 | 
			
		||||
 | 
			
		||||
namespace CanonSharp.Tests.Utils;
 | 
			
		||||
 | 
			
		||||
public abstract class ParserTestsBase
 | 
			
		||||
{
 | 
			
		||||
    protected static void ValidateSuccessfulResult<T>(Parser<char, T> parser, T value, string source)
 | 
			
		||||
    protected static void ValidateSuccessfulResult<T>(IParser<char, T> parser, T value, string source)
 | 
			
		||||
    {
 | 
			
		||||
        StringReadState state = new(source);
 | 
			
		||||
 | 
			
		||||
        ParseResult<char, T> result = parser.Parse(state);
 | 
			
		||||
        IParseResult<char, T> result = parser.Parse(state);
 | 
			
		||||
        Assert.Equal(value, result.Value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected static void ValidateSuccessfulResult<T>(
 | 
			
		||||
        Parser<char, IEnumerable<T>> parser,
 | 
			
		||||
        IParser<char, IEnumerable<T>> parser,
 | 
			
		||||
        IEnumerable<T> values, string source)
 | 
			
		||||
    {
 | 
			
		||||
        StringReadState state = new(source);
 | 
			
		||||
 | 
			
		||||
        ParseResult<char, IEnumerable<T>> result = parser.Parse(state);
 | 
			
		||||
        IParseResult<char, IEnumerable<T>> result = parser.Parse(state);
 | 
			
		||||
 | 
			
		||||
        foreach ((T actual, T except) in result.Value.Zip(values))
 | 
			
		||||
        {
 | 
			
		||||
@@ -28,16 +28,16 @@ public abstract class ParserTestsBase
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected static FailedResult<char, T> ValidateFailedResult<T>(Parser<char, T> parser, string source)
 | 
			
		||||
    protected static IFailedResult<char, T> ValidateFailedResult<T>(IParser<char, T> parser, string source)
 | 
			
		||||
    {
 | 
			
		||||
        StringReadState state = new(source);
 | 
			
		||||
 | 
			
		||||
        ParseResult<char, T> result = parser.Parse(state);
 | 
			
		||||
        IParseResult<char, T> result = parser.Parse(state);
 | 
			
		||||
        Assert.ThrowsAny<ParseException>(() =>
 | 
			
		||||
        {
 | 
			
		||||
            _ = result.Value;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return (FailedResult<char, T>)result;
 | 
			
		||||
        return (IFailedResult<char, T>)result;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@ VisualStudioVersion = 17.0.31903.59
 | 
			
		||||
MinimumVisualStudioVersion = 10.0.40219.1
 | 
			
		||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CanonSharp.Tests", "CanonSharp.Tests\CanonSharp.Tests.csproj", "{5A28EF92-805F-44E9-8E13-EA9A5BB623BB}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CanonSharp.Common", "CanonSharp.Common\CanonSharp.Common.csproj", "{288943FE-E3E6-49E2-8C6F-9B5B9242266C}"
 | 
			
		||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CanonSharp.Pascal", "CanonSharp.Pascal\CanonSharp.Pascal.csproj", "{288943FE-E3E6-49E2-8C6F-9B5B9242266C}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".gitea", ".gitea", "{B97A35A0-4616-4B3F-8F73-A66827BC98BA}"
 | 
			
		||||
EndProject
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user