/
Parser.RecoverWith.cs
57 lines (50 loc) · 2.11 KB
/
Parser.RecoverWith.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
namespace Pidgin
{
public partial class Parser<TToken, T>
{
/// <summary>
/// Creates a parser which runs the current parser, running <paramref name="errorHandler" /> on failure.
/// </summary>
/// <param name="errorHandler">A function which returns a parser to apply when the current parser fails.</param>
/// <returns>A parser which runs the current parser, running <paramref name="errorHandler" /> on failure.</returns>
public Parser<TToken, T> RecoverWith(Func<ParseError<TToken>, Parser<TToken, T>> errorHandler)
{
if (errorHandler == null)
{
throw new ArgumentNullException(nameof(errorHandler));
}
return new RecoverWithParser(this, errorHandler);
}
private sealed class RecoverWithParser : Parser<TToken, T>
{
private readonly Parser<TToken, T> _parser;
private readonly Func<ParseError<TToken>, Parser<TToken, T>> _errorHandler;
public RecoverWithParser(Parser<TToken, T> parser, Func<ParseError<TToken>, Parser<TToken, T>> errorHandler)
{
_parser = parser;
_errorHandler = errorHandler;
}
// see comment about expecteds in ParseState.Error.cs
internal override InternalResult<T> Parse(ref ParseState<TToken> state)
{
state.BeginExpectedTran();
var result = _parser.Parse(ref state);
if (result.Success)
{
state.EndExpectedTran(false);
return result;
}
var parserExpecteds = state.ExpectedTranState();
state.EndExpectedTran(false);
var recoverParser = _errorHandler(state.BuildError(parserExpecteds.ToImmutableSortedSet()));
parserExpecteds.Dispose();
return recoverParser.Parse(ref state);
}
}
}
}