CanonSharp/CanonSharp.Combinator/ParserBuilder.cs
jackfiled cf19f8197e feat: Grammar Parser (#3)
Reviewed-on: https://git.bupt-hpc.cn/jackfiled/CanonSharp/pulls/3
Co-authored-by: jackfiled <xcrenchangjun@outlook.com>
Co-committed-by: jackfiled <xcrenchangjun@outlook.com>
2024-08-18 12:01:27 +08:00

223 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 IParser<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 IParser<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 IParser<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 IParser<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 IParser<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 IParser<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 IParser<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 IParser<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 IParser<TToken, TToken> Any<TToken>() => Satisfy<TToken>(_ => true);
/// <summary>
/// 识别指定输入元素的解析器
/// </summary>
/// <param name="token">识别的指定元素</param>
/// <typeparam name="TToken"></typeparam>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IParser<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 IParser<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 IParser<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 IParser<TToken, T> Fix<TToken, T>(Func<IParser<TToken, T>, IParser<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 IParser<TToken, T> Choice<TToken, T>(IEnumerable<IParser<TToken, T>> parsers)
=> parsers.Aggregate((result, parser) => result.Alternative(parser));
/// <summary>
/// 按照给定的解析器组依次尝试
/// </summary>
/// <param name="parsers"></param>
/// <typeparam name="TToken"></typeparam>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IParser<TToken, T> Choice<TToken, T>(params IParser<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 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))));
/// <summary>
/// 顺序应用输入输入的解析器
/// </summary>
/// <param name="parsers"></param>
/// <typeparam name="TToken"></typeparam>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IParser<TToken, IEnumerable<T>> Sequence<TToken, T>(params IParser<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 IParser<TToken, IEnumerable<TToken>> TakeTill<TToken, TIgnore>(IParser<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 IParser<TToken, IEnumerable<TToken>> Take1Till<TToken, TIgnore>(IParser<TToken, TIgnore> termintor)
=> Any<TToken>().Many1Till(termintor);
#endregion
}