feat: Parser Combinator库和词法分析器 (#2)
All checks were successful
Run unit test / Unit-Test (push) Successful in 41s
All checks were successful
Run unit test / Unit-Test (push) Successful in 41s
Reviewed-on: https://git.bupt-hpc.cn/jackfiled/CanonSharp/pulls/2 Co-authored-by: jackfiled <xcrenchangjun@outlook.com> Co-committed-by: jackfiled <xcrenchangjun@outlook.com>
This commit is contained in:
49
CanonSharp.Combinator/Abstractions/FailedResult.cs
Normal file
49
CanonSharp.Combinator/Abstractions/FailedResult.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
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}.";
|
||||
}
|
||||
}
|
26
CanonSharp.Combinator/Abstractions/IReadState.cs
Normal file
26
CanonSharp.Combinator/Abstractions/IReadState.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace CanonSharp.Combinator.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// 输入流的读取状态
|
||||
/// </summary>
|
||||
/// <typeparam name="TToken">输入流元素类型</typeparam>
|
||||
public interface IReadState<out TToken>
|
||||
{
|
||||
public TToken Current { get; }
|
||||
|
||||
public bool HasValue { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 输入流的读取状态
|
||||
/// </summary>
|
||||
/// <typeparam name="TToken">输入流元素类型</typeparam>
|
||||
/// <typeparam name="TState">下一个读取状态的类型</typeparam>
|
||||
public interface IReadState<out TToken, TState> : IReadState<TToken>, IEquatable<TState>
|
||||
where TState : IReadState<TToken, TState>
|
||||
{
|
||||
/// <summary>
|
||||
/// 下一个读取状态
|
||||
/// </summary>
|
||||
TState Next { get; }
|
||||
}
|
48
CanonSharp.Combinator/Abstractions/ParseResult.cs
Normal file
48
CanonSharp.Combinator/Abstractions/ParseResult.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
namespace CanonSharp.Combinator.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// 解析器结果
|
||||
/// </summary>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="T">实际结果类型</typeparam>
|
||||
public abstract class ParseResult<TToken, T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 实际结果对象
|
||||
/// </summary>
|
||||
public abstract T Value { get; }
|
||||
|
||||
protected ParseResult()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在当前结果上应用下一个解析器
|
||||
/// </summary>
|
||||
/// <param name="nextParser">下一个解析器的函数</param>
|
||||
/// <param name="continuation">处理解析结果的后继函数</param>
|
||||
/// <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);
|
||||
|
||||
/// <summary>
|
||||
/// 映射结果
|
||||
/// </summary>
|
||||
/// <param name="map">映射结果的函数</param>
|
||||
/// <typeparam name="TResult">映射结果函数返回解析结果的类型</typeparam>
|
||||
/// <returns>最终的解析结果</returns>
|
||||
public abstract ParseResult<TToken, TResult> Map<TResult>(Func<T, TResult> map);
|
||||
|
||||
/// <summary>
|
||||
/// 在成功或者失败解析结果上应用不同的后继函数
|
||||
/// </summary>
|
||||
/// <param name="successfulHandler">在成功解析结果上应用的函数</param>
|
||||
/// <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);
|
||||
}
|
43
CanonSharp.Combinator/Abstractions/Parser.cs
Normal file
43
CanonSharp.Combinator/Abstractions/Parser.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using CanonSharp.Combinator.Extensions;
|
||||
|
||||
namespace CanonSharp.Combinator.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// 解析器抽象基类
|
||||
/// </summary>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="T">解析结果类型</typeparam>
|
||||
public abstract class Parser<TToken, T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 解析器运行函数
|
||||
/// </summary>
|
||||
/// <param name="state">解析的输入流状态</param>
|
||||
/// <param name="continuation">运行之后的后继函数</param>
|
||||
/// <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)
|
||||
where TState : IReadState<TToken, TState>;
|
||||
|
||||
public ParseResult<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>
|
||||
{
|
||||
try
|
||||
{
|
||||
return Run(state, result => result);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return ParseResultBuilder.Fail<TToken, TState, T>(e, state);
|
||||
}
|
||||
}
|
||||
|
||||
public static Parser<TToken, T> operator |(Parser<TToken, T> a, Parser<TToken, T> b)
|
||||
=> a.Alternative(b);
|
||||
}
|
33
CanonSharp.Combinator/Abstractions/SuccessfulResult.cs
Normal file
33
CanonSharp.Combinator/Abstractions/SuccessfulResult.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
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;
|
||||
}
|
9
CanonSharp.Combinator/CanonSharp.Combinator.csproj
Normal file
9
CanonSharp.Combinator/CanonSharp.Combinator.csproj
Normal file
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
572
CanonSharp.Combinator/Extensions/ParserExtensions.cs
Normal file
572
CanonSharp.Combinator/Extensions/ParserExtensions.cs
Normal file
@@ -0,0 +1,572 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
using CanonSharp.Combinator.Parsers.Bases;
|
||||
using CanonSharp.Combinator.Parsers.Modifiers;
|
||||
using static CanonSharp.Combinator.ParserBuilder;
|
||||
|
||||
namespace CanonSharp.Combinator.Extensions;
|
||||
|
||||
public static class ParserExtensions
|
||||
{
|
||||
#region BasesParser
|
||||
|
||||
/// <summary>
|
||||
/// 选择组合子
|
||||
/// </summary>
|
||||
/// <param name="first"></param>
|
||||
/// <param name="second"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <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)
|
||||
=> new AlternativeParser<TToken, T>(first, second);
|
||||
|
||||
/// <summary>
|
||||
/// 选择组合子
|
||||
/// 按照失败的解析结果选择第二个解析器
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="resume"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <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)
|
||||
=> new ResumeParser<TToken, T>(parser, resume);
|
||||
|
||||
/// <summary>
|
||||
/// 单子解析器组合子
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="next">按照输出指定下一个解析器的函数</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> new BindParser<TToken, T, TResult>(parser, next);
|
||||
|
||||
/// <summary>
|
||||
/// 映射解析器组合子
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="map">按照输出指定结果的函数</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> new MapParser<TToken, T, TResult>(parser, map);
|
||||
|
||||
/// <summary>
|
||||
/// 映射解析器组合子
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="result">最后的输出结果</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> parser.Map(_ => result);
|
||||
|
||||
/// <summary>
|
||||
/// 下一个解析器组合子
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="next">输入成功结果输出下一个解析器的函数</param>
|
||||
/// <param name="failedNext">输入失败结果输出下一个解析器的函数</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> new NextParser<TToken, T, TResult>(parser, next, failedNext);
|
||||
|
||||
/// <summary>
|
||||
/// 下一个解析器组合子
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="next">输入成功结果输出下一个解析器的函数</param>
|
||||
/// <param name="failedHandler">输出失败结果输出后续结果的函数</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> parser.Next(next, failedResult => Pure<TToken, TResult>(failedHandler(failedResult)));
|
||||
|
||||
/// <summary>
|
||||
/// 下一个解析器组合子
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="next">输出成功结果输出下一个解析器的函数</param>
|
||||
/// <param name="failedResult">如果失败之后返回该结果</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> parser.Next(next, _ => Pure<TToken, TResult>(failedResult));
|
||||
|
||||
/// <summary>
|
||||
/// 下一个解析器组合子
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="nextResult">输入成功结果返回新的结果</param>
|
||||
/// <param name="failedResume">输入失败结果返回下一个解析器的函数</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> parser.Next(x => Pure<TToken, TResult>(nextResult(x)), failedResume);
|
||||
|
||||
/// <summary>
|
||||
/// 下一个解析器组合子
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="nextResult">输入成功结果返回新的结果</param>
|
||||
/// <param name="failedResult">输入失败结果返回新的结果</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> new SuccessfulMapParser<TToken, T, TResult>(parser, nextResult, failedResult);
|
||||
|
||||
/// <summary>
|
||||
/// 下一个解析器组合子
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="successfulHandler">输入成功结果返回新结果的函数</param>
|
||||
/// <param name="failedResult">返回的失败结果</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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> successfulHandler, TResult failedResult)
|
||||
=> parser.Next(successfulHandler, _ => failedResult);
|
||||
|
||||
#endregion
|
||||
|
||||
#region ModifiedParser
|
||||
|
||||
/// <summary>
|
||||
/// 在解析结果上执行指定操作
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="successfulAction">成功结果上执行的操作</param>
|
||||
/// <param name="failedAction">失败结果上执行的操作</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <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)
|
||||
=> new DoParser<TToken, T>(parser, successfulAction, failedAction);
|
||||
|
||||
/// <summary>
|
||||
/// 在解析结果上执行指定的操作
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="successfulAction">成功结果上执行的操作</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <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)
|
||||
=> parser.Do(successfulAction, _ => { });
|
||||
|
||||
/// <summary>
|
||||
/// 向前看解析器
|
||||
/// 执行解析器的同时不消耗输入流
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, T> LookAhead<TToken, T>(this Parser<TToken, T> parser)
|
||||
=> new LookAheadParser<TToken, T>(parser);
|
||||
|
||||
/// <summary>
|
||||
/// 翻转上游解析器的输出结果
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="result">翻转之后的输出结果</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="TIgnore"></typeparam>
|
||||
/// <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)
|
||||
=> new ReverseParser<TToken, TIgnore, T>(parser, result);
|
||||
|
||||
/// <summary>
|
||||
/// 翻转上游解析器的输出结果
|
||||
/// 输出结果默认为Unit
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="TIgnore"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, Unit> Not<TToken, TIgnore>(this Parser<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)
|
||||
=> new TryParser<TToken, T>(parser, resume);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, T> Try<TToken, T>(this Parser<TToken, T> parser, T result)
|
||||
=> parser.Try(_ => result);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, bool> Try<TToken, T>(this Parser<TToken, T> parser)
|
||||
=> parser.Next(_ => true, false).Try(false);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Combinators
|
||||
|
||||
/// <summary>
|
||||
/// 连接两个解析器,返回左边解析器的结果
|
||||
/// </summary>
|
||||
/// <param name="left"></param>
|
||||
/// <param name="right"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="TLeft"></typeparam>
|
||||
/// <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)
|
||||
=> left.Bind(right.Map);
|
||||
|
||||
/// <summary>
|
||||
/// 连接两个解析器,返回右边解析器的结果
|
||||
/// </summary>
|
||||
/// <param name="left"></param>
|
||||
/// <param name="right"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="TLeft"></typeparam>
|
||||
/// <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)
|
||||
=> left.Bind(_ => right);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Parser<TToken, IEnumerable<T>> ManyRecursively<TToken, T>(this Parser<TToken, T> parser,
|
||||
IEnumerable<T> result)
|
||||
=> parser.Next(x => parser.ManyRecursively(result.Append(x)), result);
|
||||
|
||||
/// <summary>
|
||||
/// 将上游解析器运行零或若干次
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, IEnumerable<T>> Many<TToken, T>(this Parser<TToken, T> parser)
|
||||
=> parser.ManyRecursively([]);
|
||||
|
||||
/// <summary>
|
||||
/// 将上游解析器运行若干次
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, IEnumerable<T>> Many1<TToken, T>(this Parser<TToken, T> parser)
|
||||
=> parser.Bind(x => parser.ManyRecursively([x]));
|
||||
|
||||
/// <summary>
|
||||
/// 跳过执行上游解析器运行零或若干次
|
||||
/// 跳过执行不是不执行
|
||||
/// 而是不返回结果
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="TIgnore"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, Unit> SkipMany<TToken, TIgnore>(this Parser<TToken, TIgnore> parser)
|
||||
=> Fix<TToken, Unit>(self => parser.Next(_ => self, Unit.Instance));
|
||||
|
||||
/// <summary>
|
||||
/// 跳过执行上游解析器运行若干次
|
||||
/// 跳过执行不是不执行
|
||||
/// 而是不返回结果
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="TIgnore"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, Unit> SkipMany1<TToken, TIgnore>(this Parser<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)
|
||||
=> chain(value).Next(x => ChainRecursively(chain, x), value);
|
||||
|
||||
/// <summary>
|
||||
/// 链式解析器组合子
|
||||
/// 按照解析结果决定下一个解析器
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="chain"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <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)
|
||||
=> 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)
|
||||
=> terminator.Next(_ => Pure<TToken, IEnumerable<T>>(result),
|
||||
_ => parser.Bind(x => parser.ManyTillRecursively(terminator, result.Append(x))));
|
||||
|
||||
/// <summary>
|
||||
/// 执行指定解析器直到终结解析器执行成功的组合子
|
||||
/// 指定解析器可以执行零次或者多次
|
||||
/// </summary>
|
||||
/// <param name="parser">指定重复执行的解析器</param>
|
||||
/// <param name="terminator">判断是否终结的解析器</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> parser.ManyTillRecursively(terminator, []);
|
||||
|
||||
/// <summary>
|
||||
/// 执行指定解析器直到终结解析器执行成功的组合子
|
||||
/// 指定解析器至少执行一次
|
||||
/// </summary>
|
||||
/// <param name="parser">指定重复执行的解析器</param>
|
||||
/// <param name="terminator">判断是否终结的解析器</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> parser.Bind(x => parser.ManyTillRecursively(terminator, [x]));
|
||||
|
||||
/// <summary>
|
||||
/// 跳过指定解析器直到终结解析器执行成功的组合子
|
||||
/// 指定解析器可以执行零次或者若干次
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="terminator"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="TIgnore"></typeparam>
|
||||
/// <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)
|
||||
=> Fix<TToken, T>(self => terminator | parser.Right(self));
|
||||
|
||||
/// <summary>
|
||||
/// 跳过指定解析器直到终结解析器执行成功的组合子
|
||||
/// 指定解析器至少要执行一次
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="terminator"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="TIgnore"></typeparam>
|
||||
/// <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)
|
||||
=> parser.Right(parser.SkipTill(terminator));
|
||||
|
||||
/// <summary>
|
||||
/// 解析直到指定的解析器识别成功
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, T> Match<TToken, T>(this Parser<TToken, T> parser)
|
||||
=> SkipTill(Any<TToken>(), parser);
|
||||
|
||||
/// <summary>
|
||||
/// 在左右两个解析器指定的范围内进行解析
|
||||
/// 解析类似于左右括号和左右引号类似的句式
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="left"></param>
|
||||
/// <param name="right"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TLeft"></typeparam>
|
||||
/// <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)
|
||||
=> left.Right(parser.ManyTill(right));
|
||||
|
||||
/// <summary>
|
||||
/// 在同一个解析器指定的范围内进行解析
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="quotedParser"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> parser.Quote(quotedParser, quotedParser);
|
||||
|
||||
/// <summary>
|
||||
/// 解析由分隔符解析器分割的多个符号
|
||||
/// 例如a,b,c
|
||||
/// 实际的解析器可以运行零次或者多次
|
||||
/// </summary>
|
||||
/// <param name="parser">实际的解析器</param>
|
||||
/// <param name="separator">分隔符解析器</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> parser.Bind(x => separator.Right(parser).ManyRecursively([x]));
|
||||
|
||||
/// <summary>
|
||||
/// 解析由分隔符解析器分割的多个符号
|
||||
/// 例如a,b,c
|
||||
/// 实际的解析器可以运行多次
|
||||
/// </summary>
|
||||
/// <param name="parser">实际的解析器</param>
|
||||
/// <param name="separator">分隔符解析器</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> parser.SeparatedBy1(separator).Try([]);
|
||||
|
||||
/// <summary>
|
||||
/// 解析直到使用分隔符解析器结束
|
||||
/// 例如abc.
|
||||
/// 实际的解析器可以运行零次或者多次
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="separator"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> parser.Many().Left(separator);
|
||||
|
||||
/// <summary>
|
||||
/// 解析直到使用分隔符解析器结束
|
||||
/// 例如abc.
|
||||
/// 实际的解析器至少运行一次
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="separator"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> parser.Many1().Left(separator);
|
||||
|
||||
/// <summary>
|
||||
/// Separated和End的综合体
|
||||
/// 形如a,b,c,
|
||||
/// 实际的解析器至少运行一次
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="separator"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> parser.SeparatedBy1(separator).Left(separator.Try());
|
||||
|
||||
/// <summary>
|
||||
/// Separated和End的综合体
|
||||
/// 形如a,b,c,
|
||||
/// 实际的解析器可以运行零次或者多次
|
||||
/// </summary>
|
||||
/// <param name="parser"></param>
|
||||
/// <param name="separator"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <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)
|
||||
=> parser.SeparatedOrEndBy1(separator).Try([]);
|
||||
|
||||
#endregion
|
||||
|
||||
#region LINQ
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, TResult> Select<TToken, T, TResult>(this Parser<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)
|
||||
=> parser.Bind(x => selector(x).Map(y => projector(x, y)));
|
||||
|
||||
#endregion
|
||||
}
|
18
CanonSharp.Combinator/Extensions/ReadStateExtensions.cs
Normal file
18
CanonSharp.Combinator/Extensions/ReadStateExtensions.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Extensions;
|
||||
|
||||
public static class ReadStateExtensions
|
||||
{
|
||||
public static IEnumerable<TState> AsEnumerable<TToken, TState>(this TState source)
|
||||
where TState : IReadState<TToken, TState>
|
||||
{
|
||||
TState current = source;
|
||||
|
||||
while (current.HasValue)
|
||||
{
|
||||
yield return current;
|
||||
current = current.Next;
|
||||
}
|
||||
}
|
||||
}
|
15
CanonSharp.Combinator/ParseException.cs
Normal file
15
CanonSharp.Combinator/ParseException.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace CanonSharp.Combinator;
|
||||
|
||||
/// <summary>
|
||||
/// 解析过程中的异常
|
||||
/// </summary>
|
||||
public class ParseException : Exception
|
||||
{
|
||||
public ParseException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public ParseException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
67
CanonSharp.Combinator/ParseResultBuilder.cs
Normal file
67
CanonSharp.Combinator/ParseResultBuilder.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
using CanonSharp.Combinator.Results;
|
||||
|
||||
namespace CanonSharp.Combinator;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="T:CanonSharp.Combinator.Abstractions.ParseResult"/> 相关的扩展方法
|
||||
/// </summary>
|
||||
public static class ParseResultBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// 生成解析成功的结果
|
||||
/// </summary>
|
||||
/// <param name="value">解析成功的对象</param>
|
||||
/// <param name="state">下一个输入流状态</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="TState">输入流状态类型</typeparam>
|
||||
/// <typeparam name="T">解析成功的对象类型</typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ParseResult<TToken, T> Succeed<TToken, TState, T>(T value, TState state)
|
||||
where TState : IReadState<TToken, TState>
|
||||
=> new InternalSuccessfulResult<TToken, TState, T>(value, state);
|
||||
|
||||
/// <summary>
|
||||
/// 生成错误类型的解析失败结果
|
||||
/// </summary>
|
||||
/// <param name="state">解析的输入流状态</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="TState">输入流状态类型</typeparam>
|
||||
/// <typeparam name="T">解析成功的对象类型</typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ParseResult<TToken, T> Fail<TToken, TState, T>(TState state)
|
||||
where TState : IReadState<TToken, TState>
|
||||
=> new FailedResultWithError<TToken, TState, T>(state);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 生成消息类型的解析失败结果
|
||||
/// </summary>
|
||||
/// <param name="message">错误消息</param>
|
||||
/// <param name="state">输入流状态</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="TState">输入流状态类型</typeparam>
|
||||
/// <typeparam name="T">解析成功的对象类型</typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ParseResult<TToken, T> Fail<TToken, TState, T>(string message, TState state)
|
||||
where TState : IReadState<TToken, TState>
|
||||
=> new FailedResultWithMessage<TToken, TState, T>(message, state);
|
||||
|
||||
/// <summary>
|
||||
/// 生成异常类型的解析失败结果
|
||||
/// </summary>
|
||||
/// <param name="exception">解析异常</param>
|
||||
/// <param name="state">输入流状态</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="TState">输入流状态类型</typeparam>
|
||||
/// <typeparam name="T">解析成功的对象类型</typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ParseResult<TToken, T> Fail<TToken, TState, T>(Exception exception, TState state)
|
||||
where TState : IReadState<TToken, TState>
|
||||
=> new FailedResultWithException<TToken, TState, T>(exception, state);
|
||||
}
|
223
CanonSharp.Combinator/ParserBuilder.cs
Normal file
223
CanonSharp.Combinator/ParserBuilder.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
using CanonSharp.Combinator.Extensions;
|
||||
using CanonSharp.Combinator.Parsers.Bases;
|
||||
using CanonSharp.Combinator.Parsers.Primitives;
|
||||
|
||||
namespace CanonSharp.Combinator;
|
||||
|
||||
public static class ParserBuilder
|
||||
{
|
||||
#region PrimitiveParser
|
||||
|
||||
// 对应Parsers.Primitives命名空间下的Parser实现
|
||||
|
||||
/// <summary>
|
||||
/// 直接成功的解析器
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, T> Pure<TToken, T>(T value)
|
||||
=> new PureParser<TToken, T>(value);
|
||||
|
||||
/// <summary>
|
||||
/// 直接成功的解析器
|
||||
/// </summary>
|
||||
/// <param name="valueFunc">生成结果的函数</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, T> Pure<TToken, T>(Func<IReadState<TToken>, T> valueFunc)
|
||||
=> new DelayedPureParser<TToken, T>(valueFunc);
|
||||
|
||||
/// <summary>
|
||||
/// 生成空结果的解析器
|
||||
/// </summary>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, Unit> Null<TToken>() => Pure<TToken, Unit>(Unit.Instance);
|
||||
|
||||
/// <summary>
|
||||
/// 失败的解析器
|
||||
/// </summary>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, T> Fail<TToken, T>() => new FailedParser<TToken, T>();
|
||||
|
||||
/// <summary>
|
||||
/// 失败的解析器
|
||||
/// </summary>
|
||||
/// <param name="message">失败的原因</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, T> Fail<TToken, T>(string message) => new FailedParserWithMessage<TToken, T>(message);
|
||||
|
||||
/// <summary>
|
||||
/// 失败的解析器
|
||||
/// </summary>
|
||||
/// <param name="messageFunc">产生失败原因的函数</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, T> Fail<TToken, T>(Func<IReadState<TToken>, string> messageFunc) =>
|
||||
new FailedParserWithDelayedMessage<TToken, T>(messageFunc);
|
||||
|
||||
/// <summary>
|
||||
/// 失败的解析器
|
||||
/// </summary>
|
||||
/// <param name="exception">失败的异常</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, T> Fail<TToken, T>(Exception exception) =>
|
||||
new FailedParserWithException<TToken, T>(exception);
|
||||
|
||||
/// <summary>
|
||||
/// 满足指定条件的解析器
|
||||
/// </summary>
|
||||
/// <param name="predicate"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, TToken> Satisfy<TToken>(Func<TToken, bool> predicate)
|
||||
=> new SatisfyParser<TToken>(predicate);
|
||||
|
||||
/// <summary>
|
||||
/// 识别任何输入的解析器
|
||||
/// </summary>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, TToken> Any<TToken>() => Satisfy<TToken>(_ => true);
|
||||
|
||||
/// <summary>
|
||||
/// 识别指定输入元素的解析器
|
||||
/// </summary>
|
||||
/// <param name="token">识别的指定元素</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, TToken> Token<TToken>(TToken token)
|
||||
=> Satisfy<TToken>(t => EqualityComparer<TToken>.Default.Equals(t, token));
|
||||
|
||||
/// <summary>
|
||||
/// 跳过指定数量输入元素的解析器
|
||||
/// </summary>
|
||||
/// <param name="count"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, Unit> Skip<TToken>(int count) => new SkipParser<TToken>(count);
|
||||
|
||||
/// <summary>
|
||||
/// 识别指定数量输入元素的解析器
|
||||
/// </summary>
|
||||
/// <param name="count"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, IEnumerable<TToken>> Take<TToken>(int count) => new TakeParser<TToken>(count);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Bases
|
||||
|
||||
/// <summary>
|
||||
/// 按照给定的函数修改解析器的解析器
|
||||
/// </summary>
|
||||
/// <param name="parserFix"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <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)
|
||||
=> new FixParser<TToken, T>(parserFix);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Combinators
|
||||
|
||||
/// <summary>
|
||||
/// 按照给定的解析器组依次尝试
|
||||
/// </summary>
|
||||
/// <param name="parsers"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, T> Choice<TToken, T>(IEnumerable<Parser<TToken, T>> parsers)
|
||||
=> parsers.Reverse().Aggregate((next, parser) => parser.Alternative(next));
|
||||
|
||||
/// <summary>
|
||||
/// 按照给定的解析器组依次尝试
|
||||
/// </summary>
|
||||
/// <param name="parsers"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, T> Choice<TToken, T>(params Parser<TToken, T>[] parsers)
|
||||
=> Choice(parsers.AsEnumerable());
|
||||
|
||||
/// <summary>
|
||||
/// 顺序应用所有输入的解析器
|
||||
/// </summary>
|
||||
/// <param name="parsers"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, IEnumerable<T>> Sequence<TToken, T>(IEnumerable<Parser<TToken, T>> parsers)
|
||||
=> parsers.Reverse().Aggregate(Pure<TToken, IEnumerable<T>>([]),
|
||||
(next, parser) => parser.Bind(
|
||||
x => next.Map(result => result.Prepend(x))));
|
||||
|
||||
/// <summary>
|
||||
/// 顺序应用输入输入的解析器
|
||||
/// </summary>
|
||||
/// <param name="parsers"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, IEnumerable<T>> Sequence<TToken, T>(params Parser<TToken, T>[] parsers)
|
||||
=> Sequence(parsers.AsEnumerable());
|
||||
|
||||
/// <summary>
|
||||
/// 识别输入令牌直到终止解析器运行成功
|
||||
/// 在终止解析器之前可以存在零个或者多个输入令牌
|
||||
/// </summary>
|
||||
/// <param name="terminator"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="TIgnore"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, IEnumerable<TToken>> TakeTill<TToken, TIgnore>(Parser<TToken, TIgnore> terminator)
|
||||
=> Any<TToken>().ManyTill(terminator);
|
||||
|
||||
/// <summary>
|
||||
/// 识别输入令牌直到终止解析器运行成功
|
||||
/// 在终止解析器之前至少存在一个输入令牌
|
||||
/// </summary>
|
||||
/// <param name="termintor"></param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="TIgnore"></typeparam>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<TToken, IEnumerable<TToken>> Take1Till<TToken, TIgnore>(Parser<TToken, TIgnore> termintor)
|
||||
=> Any<TToken>().Many1Till(termintor);
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
21
CanonSharp.Combinator/Parsers/Bases/AlternativeParser.cs
Normal file
21
CanonSharp.Combinator/Parsers/Bases/AlternativeParser.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Bases;
|
||||
|
||||
/// <summary>
|
||||
/// 选择解析器
|
||||
/// 如果第一个不成功则调用第二个
|
||||
/// </summary>
|
||||
/// <param name="first">第一个解析器</param>
|
||||
/// <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 override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
|
||||
Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
|
||||
{
|
||||
return first.Run(state, result => result.CaseOf(continuation, _ => second.Run(state, continuation)));
|
||||
}
|
||||
}
|
20
CanonSharp.Combinator/Parsers/Bases/BindParser.cs
Normal file
20
CanonSharp.Combinator/Parsers/Bases/BindParser.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Bases;
|
||||
|
||||
/// <summary>
|
||||
/// 单子解析器
|
||||
/// </summary>
|
||||
/// <param name="parser">上游解析器</param>
|
||||
/// <param name="next">下游解析器生成函数</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <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>
|
||||
{
|
||||
internal override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
|
||||
Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
|
||||
=> parser.Run(state, result => result.Next(next, continuation));
|
||||
}
|
33
CanonSharp.Combinator/Parsers/Bases/FixParser.cs
Normal file
33
CanonSharp.Combinator/Parsers/Bases/FixParser.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Bases;
|
||||
|
||||
/// <summary>
|
||||
/// 修正?解析器
|
||||
/// 感觉是一种递归的高级实现?
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
internal sealed class FixParser<TToken, T> : Parser<TToken, T>
|
||||
{
|
||||
private readonly Parser<TToken, T> _parser;
|
||||
|
||||
public FixParser(Func<Parser<TToken, T>, Parser<TToken, T>> func)
|
||||
{
|
||||
_parser = func(this);
|
||||
}
|
||||
|
||||
internal override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
|
||||
Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
|
||||
=> _parser.Run(state, continuation);
|
||||
}
|
||||
|
||||
internal sealed class FixParser<TToken, TParameter, T>(
|
||||
Func<Func<TParameter, Parser<TToken, T>>, TParameter, Parser<TToken, T>> func,
|
||||
TParameter parameter) : Parser<TToken, T>
|
||||
{
|
||||
internal override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
|
||||
Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
|
||||
=> func(p => new FixParser<TToken, TParameter, T>(func, p), parameter).Run(state, continuation);
|
||||
}
|
21
CanonSharp.Combinator/Parsers/Bases/MapParser.cs
Normal file
21
CanonSharp.Combinator/Parsers/Bases/MapParser.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Bases;
|
||||
|
||||
/// <summary>
|
||||
/// 映射解析器
|
||||
/// 提供一个函数修改上游解析器返回的结果
|
||||
/// </summary>
|
||||
/// <param name="parser">上游解析器</param>
|
||||
/// <param name="func">修改上游解析器返回结果的</param>
|
||||
/// <typeparam name="TToken"></typeparam>
|
||||
/// <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>
|
||||
{
|
||||
internal override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
|
||||
Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
|
||||
=> parser.Run(state, result => continuation(result.Map(func)));
|
||||
}
|
26
CanonSharp.Combinator/Parsers/Bases/NextParser.cs
Normal file
26
CanonSharp.Combinator/Parsers/Bases/NextParser.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Bases;
|
||||
|
||||
/// <summary>
|
||||
/// 下一步解析器
|
||||
/// </summary>
|
||||
/// <param name="parser">上游解析器</param>
|
||||
/// <param name="successfulParser">成功情况下的解析器函数</param>
|
||||
/// <param name="failedParser">失败情况下的解析器函数</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <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>
|
||||
{
|
||||
internal override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
|
||||
Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
|
||||
{
|
||||
return parser.Run(state, result => result.CaseOf(
|
||||
successfulResult => successfulResult.Next(successfulParser, continuation),
|
||||
failedResult => failedParser(failedResult).Run(state, continuation)));
|
||||
}
|
||||
}
|
24
CanonSharp.Combinator/Parsers/Bases/ResumeParser.cs
Normal file
24
CanonSharp.Combinator/Parsers/Bases/ResumeParser.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Bases;
|
||||
|
||||
/// <summary>
|
||||
/// 恢复解析器
|
||||
/// 在上游解析器失败的情况下调用指定恢复函数返回的解析器
|
||||
/// </summary>
|
||||
/// <param name="parser">上游解析器</param>
|
||||
/// <param name="failedHandler">返回新解析器的恢复函数</param>
|
||||
/// <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>
|
||||
{
|
||||
internal override ParseResult<TToken, TResult> Run<TState, TResult>(TState state,
|
||||
Func<ParseResult<TToken, T>, ParseResult<TToken, TResult>> continuation)
|
||||
{
|
||||
return parser.Run(state,
|
||||
result => result.CaseOf(continuation,
|
||||
failedResult => failedHandler(failedResult).Run(state, continuation)));
|
||||
}
|
||||
}
|
27
CanonSharp.Combinator/Parsers/ModifiedParser.cs
Normal file
27
CanonSharp.Combinator/Parsers/ModifiedParser.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers;
|
||||
|
||||
/// <summary>
|
||||
/// 修改解析器返回结果的解析器基类
|
||||
/// </summary>
|
||||
/// <param name="parser">需要修改结果的解析器</param>
|
||||
/// <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>
|
||||
{
|
||||
protected abstract ParseResult<TToken, T> Fail<TState>(TState state,
|
||||
FailedResult<TToken, TIntermediate> failedResult)
|
||||
where TState : IReadState<TToken, TState>;
|
||||
|
||||
protected abstract ParseResult<TToken, T> Succeed<TState>(TState state,
|
||||
SuccessfulResult<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)
|
||||
=> parser.Run(state, result => result.CaseOf(
|
||||
success => continuation(Succeed(state, success)),
|
||||
failure => continuation(Fail(state, failure))));
|
||||
}
|
30
CanonSharp.Combinator/Parsers/Modifiers/DoParser.cs
Normal file
30
CanonSharp.Combinator/Parsers/Modifiers/DoParser.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Modifiers;
|
||||
|
||||
/// <summary>
|
||||
/// 对结果运行指定操作,但是不做修改操作的解析器
|
||||
/// </summary>
|
||||
/// <param name="parser">上游解析器</param>
|
||||
/// <param name="succeed">对成功结果的操作</param>
|
||||
/// <param name="fail">对失败结果的操作</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="T">解析结果类型</typeparam>
|
||||
internal sealed class DoParser<TToken, T>(
|
||||
Parser<TToken, T> parser,
|
||||
Action<T> succeed,
|
||||
Action<FailedResult<TToken, T>> fail) : ModifiedParser<TToken, T, T>(parser)
|
||||
{
|
||||
protected override ParseResult<TToken, T> Succeed<TState>(TState state,
|
||||
SuccessfulResult<TToken, T> successfulResult)
|
||||
{
|
||||
succeed(successfulResult.Value);
|
||||
return successfulResult;
|
||||
}
|
||||
|
||||
protected override ParseResult<TToken, T> Fail<TState>(TState state, FailedResult<TToken, T> failedResult)
|
||||
{
|
||||
fail(failedResult);
|
||||
return failedResult;
|
||||
}
|
||||
}
|
21
CanonSharp.Combinator/Parsers/Modifiers/LookAheadParser.cs
Normal file
21
CanonSharp.Combinator/Parsers/Modifiers/LookAheadParser.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Modifiers;
|
||||
|
||||
/// <summary>
|
||||
/// 向前看解析器
|
||||
/// 使用传入的解析器向前解析
|
||||
/// 但是返回的结果中输入流读取状态不前移
|
||||
/// </summary>
|
||||
/// <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)
|
||||
{
|
||||
protected override ParseResult<TToken, T> Succeed<TState>(TState state,
|
||||
SuccessfulResult<TToken, T> successfulResult)
|
||||
=> ParseResultBuilder.Succeed<TToken, TState, T>(successfulResult.Value, state);
|
||||
|
||||
protected override ParseResult<TToken, T> Fail<TState>(TState state, FailedResult<TToken, T> failedResult)
|
||||
=> ParseResultBuilder.Fail<TToken, TState, T>($"Failed when looking ahead: {failedResult}", state);
|
||||
}
|
26
CanonSharp.Combinator/Parsers/Modifiers/ReverseParser.cs
Normal file
26
CanonSharp.Combinator/Parsers/Modifiers/ReverseParser.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Modifiers;
|
||||
|
||||
/// <summary>
|
||||
/// 翻转结果的解析器
|
||||
/// 当成功时失败
|
||||
/// 当失败时返回指定的成功结果
|
||||
/// </summary>
|
||||
/// <param name="parser">上游解析器</param>
|
||||
/// <param name="result">期望中的结果</param>
|
||||
/// <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)
|
||||
: ModifiedParser<TToken, TIntermediate, T>(parser)
|
||||
{
|
||||
protected override ParseResult<TToken, T> Succeed<TState>(TState state,
|
||||
SuccessfulResult<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)
|
||||
=> ParseResultBuilder.Succeed<TToken, TState, T>(result, state);
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Modifiers;
|
||||
|
||||
/// <summary>
|
||||
/// 成功映射的解析器
|
||||
/// </summary>
|
||||
/// <param name="parser">上游解析器</param>
|
||||
/// <param name="successfulHandler">当上游成功时的处理函数</param>
|
||||
/// <param name="failedHandler">当上游失败时的处理函数</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="TIntermediate">上游解析器解析结果类型</typeparam>
|
||||
/// <typeparam name="T">最终的解析结果类型</typeparam>
|
||||
internal sealed class SuccessfulMapParser<TToken, TIntermediate, T>(
|
||||
Parser<TToken, TIntermediate> parser,
|
||||
Func<TIntermediate, T> successfulHandler,
|
||||
Func<FailedResult<TToken, TIntermediate>, T> failedHandler) : ModifiedParser<TToken, TIntermediate, T>(parser)
|
||||
{
|
||||
protected override ParseResult<TToken, T> Succeed<TState>(TState state,
|
||||
SuccessfulResult<TToken, TIntermediate> successfulResult)
|
||||
=> successfulResult.Map(successfulHandler);
|
||||
|
||||
protected override ParseResult<TToken, T> Fail<TState>(TState state,
|
||||
FailedResult<TToken, TIntermediate> failedResult)
|
||||
=> ParseResultBuilder.Succeed<TToken, TState, T>(failedHandler(failedResult), state);
|
||||
}
|
23
CanonSharp.Combinator/Parsers/Modifiers/TryParser.cs
Normal file
23
CanonSharp.Combinator/Parsers/Modifiers/TryParser.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Modifiers;
|
||||
|
||||
/// <summary>
|
||||
/// 尝试的解析器
|
||||
/// 当成功时直接返回原结果
|
||||
/// 当失败时调用resume函数处理失败结果并返回成功结果
|
||||
/// </summary>
|
||||
/// <param name="parser">上游解析器</param>
|
||||
/// <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)
|
||||
: ModifiedParser<TToken, T, T>(parser)
|
||||
{
|
||||
protected override ParseResult<TToken, T> Succeed<TState>(TState state,
|
||||
SuccessfulResult<TToken, T> successfulResult)
|
||||
=> successfulResult;
|
||||
|
||||
protected override ParseResult<TToken, T> Fail<TState>(TState state, FailedResult<TToken, T> failedResult)
|
||||
=> ParseResultBuilder.Succeed<TToken, TState, T>(resume(failedResult), state);
|
||||
}
|
25
CanonSharp.Combinator/Parsers/PrimitiveParser.cs
Normal file
25
CanonSharp.Combinator/Parsers/PrimitiveParser.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers;
|
||||
|
||||
/// <summary>
|
||||
/// 解析器原型基类
|
||||
/// 实际上就是处理了一个后继调用
|
||||
/// </summary>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="T">解析结果的类型</typeparam>
|
||||
public abstract class PrimitiveParser<TToken, T> : Parser<TToken, T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 运行解析器 返回解析结果
|
||||
/// </summary>
|
||||
/// <param name="state">当前输入流的状态</param>
|
||||
/// <typeparam name="TState">输入流状态的类型</typeparam>
|
||||
/// <returns>解析结果</returns>
|
||||
protected abstract ParseResult<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)
|
||||
=> continuation(Run(state));
|
||||
}
|
51
CanonSharp.Combinator/Parsers/Primitives/FailedParser.cs
Normal file
51
CanonSharp.Combinator/Parsers/Primitives/FailedParser.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Primitives;
|
||||
|
||||
/// <summary>
|
||||
/// 直接失败的解析器
|
||||
/// </summary>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="T">解析结果的类型</typeparam>
|
||||
internal sealed class FailedParser<TToken, T> : PrimitiveParser<TToken, T>
|
||||
{
|
||||
protected override ParseResult<TToken, T> Run<TState>(TState state)
|
||||
=> ParseResultBuilder.Fail<TToken, TState, T>(state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 含有失败信息的失败解析器
|
||||
/// </summary>
|
||||
/// <param name="message">失败信息</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="T">解析结果的类型</typeparam>
|
||||
internal sealed class FailedParserWithMessage<TToken, T>(string message) : PrimitiveParser<TToken, T>
|
||||
{
|
||||
protected override ParseResult<TToken, T> Run<TState>(TState state)
|
||||
=> ParseResultBuilder.Fail<TToken, TState, T>(message, state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按照输入状态产生失败信息的失败解析器
|
||||
/// </summary>
|
||||
/// <param name="messageFunc">产生失败信息的函数</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="T">解析结果的类型</typeparam>
|
||||
internal sealed class FailedParserWithDelayedMessage<TToken, T>(Func<IReadState<TToken>, string> messageFunc)
|
||||
: PrimitiveParser<TToken, T>
|
||||
{
|
||||
protected override ParseResult<TToken, T> Run<TState>(TState state)
|
||||
=> ParseResultBuilder.Fail<TToken, TState, T>(messageFunc(state), state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 含有失败异常的失败解析器
|
||||
/// </summary>
|
||||
/// <param name="e">异常</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="T">解析结果的类型</typeparam>
|
||||
internal sealed class FailedParserWithException<TToken, T>(Exception e) : PrimitiveParser<TToken, T>
|
||||
{
|
||||
protected override ParseResult<TToken, T> Run<TState>(TState state)
|
||||
=> ParseResultBuilder.Fail<TToken, TState, T>(e, state);
|
||||
}
|
27
CanonSharp.Combinator/Parsers/Primitives/PureParser.cs
Normal file
27
CanonSharp.Combinator/Parsers/Primitives/PureParser.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Primitives;
|
||||
|
||||
/// <summary>
|
||||
/// 直接成功的解析器
|
||||
/// </summary>
|
||||
/// <param name="value">解析成功返回的值</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="T">解析成功返回值的类型</typeparam>
|
||||
internal sealed class PureParser<TToken, T>(T value) : PrimitiveParser<TToken, T>
|
||||
{
|
||||
protected override ParseResult<TToken, T> Run<TState>(TState state)
|
||||
=> ParseResultBuilder.Succeed<TToken, TState, T>(value, state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按照输入状态返回结果的始终成功解析器
|
||||
/// </summary>
|
||||
/// <param name="valueFunc">按照输入状态返回解析结果的函数</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <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)
|
||||
=> ParseResultBuilder.Succeed<TToken, TState, T>(valueFunc(state), state);
|
||||
}
|
18
CanonSharp.Combinator/Parsers/Primitives/SatisfyParser.cs
Normal file
18
CanonSharp.Combinator/Parsers/Primitives/SatisfyParser.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Primitives;
|
||||
|
||||
/// <summary>
|
||||
/// 满足指定条件即成功的解析器
|
||||
/// </summary>
|
||||
/// <param name="predicate">满足的条件谓词</param>
|
||||
/// <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)
|
||||
{
|
||||
return state.HasValue && predicate(state.Current)
|
||||
? ParseResultBuilder.Succeed<TToken, TState, TToken>(state.Current, state.Next)
|
||||
: ParseResultBuilder.Fail<TToken, TState, TToken>(state);
|
||||
}
|
||||
}
|
22
CanonSharp.Combinator/Parsers/Primitives/SkipParser.cs
Normal file
22
CanonSharp.Combinator/Parsers/Primitives/SkipParser.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
using CanonSharp.Combinator.Extensions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Primitives;
|
||||
|
||||
/// <summary>
|
||||
/// 跳过指定数量的输入令牌
|
||||
/// </summary>
|
||||
/// <param name="count">需要跳过的令牌数量</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
internal sealed class SkipParser<TToken>(int count) : PrimitiveParser<TToken, Unit>
|
||||
{
|
||||
protected override ParseResult<TToken, Unit> Run<TState>(TState state)
|
||||
{
|
||||
List<TState> result = state.AsEnumerable<TToken, TState>().Take(count).ToList();
|
||||
|
||||
return result.Count == count
|
||||
? ParseResultBuilder.Succeed<TToken, TState, Unit>(Unit.Instance,
|
||||
result.Count == 0 ? state : result.Last().Next)
|
||||
: ParseResultBuilder.Fail<TToken, TState, Unit>("An input does not have required length.", state);
|
||||
}
|
||||
}
|
23
CanonSharp.Combinator/Parsers/Primitives/TakeParser.cs
Normal file
23
CanonSharp.Combinator/Parsers/Primitives/TakeParser.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
using CanonSharp.Combinator.Extensions;
|
||||
|
||||
namespace CanonSharp.Combinator.Parsers.Primitives;
|
||||
|
||||
/// <summary>
|
||||
/// 解析指定数量的解析器
|
||||
/// </summary>
|
||||
/// <param name="count">需要解析的数量</param>
|
||||
/// <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)
|
||||
{
|
||||
List<TState> result = state.AsEnumerable<TToken, TState>().Take(count).ToList();
|
||||
|
||||
return result.Count == count
|
||||
? ParseResultBuilder.Succeed<TToken, TState, IEnumerable<TToken>>(result.Select(s => s.Current),
|
||||
result.Count == 0 ? state : result.Last().Next)
|
||||
: ParseResultBuilder.Fail<TToken, TState, IEnumerable<TToken>>("An input does not have required length.",
|
||||
state);
|
||||
}
|
||||
}
|
22
CanonSharp.Combinator/Results/FailedResultWithError.cs
Normal file
22
CanonSharp.Combinator/Results/FailedResultWithError.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Results;
|
||||
|
||||
/// <summary>
|
||||
/// 错误类型的失败解析结果
|
||||
/// </summary>
|
||||
/// <typeparam name="TToken">输入流的类型</typeparam>
|
||||
/// <typeparam name="TState">输入流的读取类型</typeparam>
|
||||
/// <typeparam name="T">实际的结果类型</typeparam>
|
||||
internal sealed class FailedResultWithError<TToken, TState, T>(TState state) : FailedResult<TToken, T>
|
||||
where TState : IReadState<TToken, TState>
|
||||
{
|
||||
public override IReadState<TToken> State => state;
|
||||
|
||||
public override string Message => $"Unexpected state: {state}.";
|
||||
|
||||
public override FailedResult<TToken, TNext> Convert<TNext>()
|
||||
{
|
||||
return new FailedResultWithError<TToken, TState, TNext>(state);
|
||||
}
|
||||
}
|
24
CanonSharp.Combinator/Results/FailedResultWithException.cs
Normal file
24
CanonSharp.Combinator/Results/FailedResultWithException.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Results;
|
||||
|
||||
/// <summary>
|
||||
/// 异常类型的失败解析结果
|
||||
/// </summary>
|
||||
/// <param name="exception">解析中发生的异常</param>
|
||||
/// <param name="state">当前输入流的状态</param>
|
||||
/// <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>
|
||||
where TState : IReadState<TToken, TState>
|
||||
{
|
||||
public override IReadState<TToken> State => state;
|
||||
|
||||
public override ParseException Exception => new(ToString(), exception);
|
||||
|
||||
public override string Message => $"Exception occured: {exception}.";
|
||||
|
||||
public override FailedResult<TToken, TNext> Convert<TNext>()
|
||||
=> new FailedResultWithException<TToken, TState, TNext>(exception, state);
|
||||
}
|
24
CanonSharp.Combinator/Results/FailedResultWithMessage.cs
Normal file
24
CanonSharp.Combinator/Results/FailedResultWithMessage.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Results;
|
||||
|
||||
/// <summary>
|
||||
/// 消息类型的失败解析结果
|
||||
/// </summary>
|
||||
/// <param name="message">解析失败的消息</param>
|
||||
/// <param name="state">当前读取的状态</param>
|
||||
/// <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>
|
||||
where TState : IReadState<TToken, TState>
|
||||
{
|
||||
public override IReadState<TToken> State => state;
|
||||
|
||||
public override string Message => message;
|
||||
|
||||
public override FailedResult<TToken, TNext> Convert<TNext>()
|
||||
{
|
||||
return new FailedResultWithMessage<TToken, TState, TNext>(message, state);
|
||||
}
|
||||
}
|
23
CanonSharp.Combinator/Results/InternalSuccessfulResult.cs
Normal file
23
CanonSharp.Combinator/Results/InternalSuccessfulResult.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
|
||||
namespace CanonSharp.Combinator.Results;
|
||||
|
||||
/// <summary>
|
||||
/// 实际实现的解析成功结果
|
||||
/// </summary>
|
||||
/// <param name="result">解析结果</param>
|
||||
/// <param name="state">解析成功之后的下一个输入流状态</param>
|
||||
/// <typeparam name="TToken">输入流类型</typeparam>
|
||||
/// <typeparam name="TState">输入流的状态类型</typeparam>
|
||||
/// <typeparam name="T">解析结果的类型</typeparam>
|
||||
internal sealed class InternalSuccessfulResult<TToken, TState, T>(T result, TState state)
|
||||
: SuccessfulResult<TToken, T>(result)
|
||||
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)
|
||||
=> parser.Run(state, continuation);
|
||||
|
||||
public override ParseResult<TToken, TResult> Map<TResult>(Func<T, TResult> map)
|
||||
=> new InternalSuccessfulResult<TToken, TState, TResult>(map(Value), state);
|
||||
}
|
22
CanonSharp.Combinator/Text/StringParser.cs
Normal file
22
CanonSharp.Combinator/Text/StringParser.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
using CanonSharp.Combinator.Extensions;
|
||||
using CanonSharp.Combinator.Parsers;
|
||||
|
||||
namespace CanonSharp.Combinator.Text;
|
||||
|
||||
/// <summary>
|
||||
/// 字符串解析器
|
||||
/// </summary>
|
||||
/// <param name="except">期望的字符串</param>
|
||||
/// <param name="comparison">字符串比较模式</param>
|
||||
public class StringParser(string except, StringComparison comparison) : PrimitiveParser<char, string>
|
||||
{
|
||||
protected override ParseResult<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());
|
||||
return string.Equals(except, actual, comparison)
|
||||
? ParseResultBuilder.Succeed<char, TState, string>(actual, states.Length == 0 ? state : states.Last().Next)
|
||||
: ParseResultBuilder.Fail<char, TState, string>($"Except '{except}' but found '{actual}.", state);
|
||||
}
|
||||
}
|
123
CanonSharp.Combinator/Text/TextParserBuilder.cs
Normal file
123
CanonSharp.Combinator/Text/TextParserBuilder.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
using CanonSharp.Combinator.Extensions;
|
||||
using static CanonSharp.Combinator.ParserBuilder;
|
||||
|
||||
namespace CanonSharp.Combinator.Text;
|
||||
|
||||
public static class TextParserBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// 识别单个字符
|
||||
/// </summary>
|
||||
/// <param name="token">识别的单个字符</param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<char, char> Char(char token) => Satisfy<char>(x => x == token);
|
||||
|
||||
/// <summary>
|
||||
/// 忽略大小写识别单个字符
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<char, char> CharIgnoreCase(char token) =>
|
||||
Satisfy<char>(x => char.ToUpperInvariant(x) == char.ToUpperInvariant(token));
|
||||
|
||||
/// <summary>
|
||||
/// 识别提供字符串中的一个字符
|
||||
/// </summary>
|
||||
/// <param name="candidate"></param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<char, char> OneOf(string candidate) => Satisfy<char>(candidate.Contains);
|
||||
|
||||
/// <summary>
|
||||
/// 忽略大小写识别字符串中的一个字符
|
||||
/// </summary>
|
||||
/// <param name="candidate"></param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<char, char> OneOfIgnoreCase(string candidate) =>
|
||||
Satisfy<char>(x => candidate.Contains(x, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
/// <summary>
|
||||
/// 识别一个字符串
|
||||
/// </summary>
|
||||
/// <param name="except">识别的字符串</param>
|
||||
/// <param name="comparison">字符串比较方法</param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<char, string> String(string except, StringComparison comparison) =>
|
||||
new StringParser(except, comparison);
|
||||
|
||||
/// <summary>
|
||||
/// 识别一个字符串
|
||||
/// </summary>
|
||||
/// <param name="except"></param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<char, string> String(string except) => String(except, StringComparison.Ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// 忽略大小写识别一个字符串
|
||||
/// </summary>
|
||||
/// <param name="except"></param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<char, string> StringIgnoreCase(string except) =>
|
||||
String(except, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// 识别范围内的所有字符
|
||||
/// </summary>
|
||||
/// <param name="start">包括的起始字符</param>
|
||||
/// <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);
|
||||
|
||||
/// <summary>
|
||||
/// 识别Unicode字符类别的解析器
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<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);
|
||||
|
||||
/// <summary>
|
||||
/// 识别ASCII字符类别的解析器
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<char, char> AsciiLetter() =>
|
||||
Satisfy<char>(x => x is >= 'a' and <= 'z' or >= 'A' and <= 'Z');
|
||||
|
||||
/// <summary>
|
||||
/// 识别ASCII数字类别的解析器
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<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);
|
||||
|
||||
/// <summary>
|
||||
/// 识别所有的换行符
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Parser<char, string> LineBreak() =>
|
||||
OneOf("\u000D\u000A\u0085\u2028\u2029\n").Map(x => x.ToString()) | String("\r\n");
|
||||
}
|
14
CanonSharp.Combinator/Text/TextParserExtensions.cs
Normal file
14
CanonSharp.Combinator/Text/TextParserExtensions.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using CanonSharp.Combinator.Abstractions;
|
||||
using CanonSharp.Combinator.Extensions;
|
||||
using static CanonSharp.Combinator.Text.TextParserBuilder;
|
||||
|
||||
namespace CanonSharp.Combinator.Text;
|
||||
|
||||
public static class TextParserExtensions
|
||||
{
|
||||
public static Parser<char, T> SkipSpaces<T>(this Parser<char, T> parser)
|
||||
=> Space().SkipTill(parser);
|
||||
|
||||
public static Parser<char, T> SkipSpaceAndLineBreak<T>(this Parser<char, T> parser)
|
||||
=> (Space().Map(x => x.ToString()) | LineBreak()).SkipTill(parser);
|
||||
}
|
23
CanonSharp.Combinator/Unit.cs
Normal file
23
CanonSharp.Combinator/Unit.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace CanonSharp.Combinator;
|
||||
|
||||
/// <summary>
|
||||
/// 单元类型Unit
|
||||
/// </summary>
|
||||
public readonly struct Unit : IComparable<Unit>, IEquatable<Unit>
|
||||
{
|
||||
public static Unit Instance => default;
|
||||
|
||||
public bool Equals(Unit other) => true;
|
||||
|
||||
public int CompareTo(Unit other) => 0;
|
||||
|
||||
public override bool Equals(object? obj) => obj is Unit;
|
||||
|
||||
public override int GetHashCode() => 0;
|
||||
|
||||
public override string ToString() => $"<{nameof(Unit)}>";
|
||||
|
||||
public static bool operator ==(Unit _0, Unit _1) => true;
|
||||
|
||||
public static bool operator !=(Unit _0, Unit _1) => false;
|
||||
}
|
Reference in New Issue
Block a user