コード例 #1
0
        public IMultiResult <TOutput> Parse(IParseState <TInput> state)
        {
            var multiResult = _inner.Parse(state);

            var results = new List <IResultAlternative <TOutput> >();

            foreach (var alt in multiResult.Results.Where(r => r.Success))
            {
                alt.Continuation.Rewind();
                _left.Location = multiResult.Location;
                _left.Value    = alt.Value;
                var result = _right.Parse(state);
                if (!result.Success)
                {
                    results.Add(new FailureResultAlternative <TOutput>("Right parser returned no valid results", multiResult.StartCheckpoint));
                    continue;
                }

                foreach (var resultAlt in result.Results)
                {
                    results.Add(new SuccessResultAlternative <TOutput>(resultAlt.Value, resultAlt.Consumed, resultAlt.Continuation));
                }
            }

            multiResult.StartCheckpoint.Rewind();
            return(new MultiResult <TOutput>(this, multiResult.Location, multiResult.StartCheckpoint, results));
        }
コード例 #2
0
 /// <summary>
 /// Execute a parser and catch any unhandled exceptions which may be thrown by it. On
 /// receiving an exception, the input sequence is rewound to the location where Try started
 /// and options are provided to determine what actions to take.
 /// </summary>
 /// <typeparam name="TOutput"></typeparam>
 /// <param name="parser"></param>
 /// <param name="examine"></param>
 /// <param name="bubble"></param>
 /// <returns></returns>
 public static IMultiParser <TInput, TOutput> Try <TOutput>(IMultiParser <TInput, TOutput> parser, Action <Exception>?examine = null, bool bubble = false)
 => new Function <TInput, TOutput> .MultiParser(args =>
 {
     var cp = args.Input.Checkpoint();
     try
     {
         return(parser.Parse(args.State));
     }
     catch (ControlFlowException)
     {
         // These exceptions are used within the library for non-local control flow, and
         // should not be caught or modified here.
         throw;
     }
     catch (Exception e)
     {
         cp.Rewind();
         examine?.Invoke(e);
         if (bubble)
         {
             throw;
         }
         return(new MultiResult <TOutput>(parser, cp.Location, cp, Array.Empty <IResultAlternative <TOutput> >(), data: new[] { e }));
     }
 }, "TRY {child}", new[] { parser });
コード例 #3
0
    /// <summary>
    /// Attempts a parse but does not consume any input. Instead it returns a boolean true if
    /// the parser would succeed or false otherwise.
    /// </summary>
    /// <typeparam name="TInput"></typeparam>
    /// <param name="parser"></param>
    /// <param name="input"></param>
    /// <returns></returns>
    public static bool CanMatch <TInput>(this IMultiParser <TInput> parser, ISequence <TInput> input)
    {
        var state  = new ParseState <TInput>(input, Defaults.LogMethod);
        var result = parser.Parse(state);

        result.StartCheckpoint.Rewind();
        return(result.Success);
    }
コード例 #4
0
    /// <summary>
    /// Convenience method for parsers which act on character sequences. Attempts a parse but
    /// does not consume any input. Returns true if the parse would succeed, false otherwise.
    /// </summary>
    /// <param name="parser"></param>
    /// <param name="input"></param>
    /// <param name="options"></param>
    /// <returns></returns>
    public static bool CanMatch(this IMultiParser <char> parser, string input, StringCharacterSequence.Options options = default)
    {
        // Don't need to .Checkpoint()/.Rewind() because the sequence is private and we don't
        // reuse it
        var sequence = new StringCharacterSequence(input, options);
        var state    = new ParseState <char>(sequence, Defaults.LogMethod);
        var result   = parser.Parse(state);

        return(result.Success);
    }
コード例 #5
0
 public static IMultiParser <TInput, TOutput> Context <TOutput>(IMultiParser <TInput, TOutput> parser, Action <IParseState <TInput> > setup, Action <IParseState <TInput> > cleanup)
 => new Function <TInput, TOutput> .MultiParser(args =>
 {
     var state = args.State;
     try
     {
         setup(state);
         return(parser.Parse(state));
     }
     finally
     {
         cleanup(state);
     }
 }, string.Empty, new[] { parser });
コード例 #6
0
 public IMultiResult <TOutput> Parse(IParseState <TInput> state) => _value.Parse(state);
コード例 #7
0
 /// <summary>
 /// Convenience method to invoke a parser which does not return a value. Creates the
 /// necessary ParseState.
 /// </summary>
 /// <typeparam name="TInput"></typeparam>
 /// <param name="parser"></param>
 /// <param name="input"></param>
 /// <param name="log"></param>
 /// <returns></returns>
 public static IMultiResult Parse <TInput>(this IMultiParser <TInput> parser, ISequence <TInput> input, Action <string>?log = null)
 => parser.Parse(new ParseState <TInput>(input, log ?? Defaults.LogMethod));