224 lines
8.3 KiB
C#
224 lines
8.3 KiB
C#
|
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
|
||
|
}
|