/// <summary> /// Indicates a successful parse operation without actually parsing by yielding a single result containing an empty sequence. /// </summary> /// <typeparam name="TSource">The type of the source elements.</typeparam> /// <typeparam name="TResult">The type of the elements in the sequences that are generated from parsing the source elements.</typeparam> /// <param name="parser">The parser for which a single empty result sequence is returned to indicate success.</param> /// <remarks> /// <see cref="Success{TSource,TResult}(IObservableParser{TSource,IObservable{TResult}})"/> is required as an explicit overload /// because the meaning of the parser's result sequence is special and must not be compounded into a sequence of sequences, /// which would happen if the <see cref="Success{TSource,TResult}(IObservableParser{TSource,TResult})"/> overload were to be called /// instead. /// </remarks> /// <returns>A parser that returns a single result containing an empty sequence with a length /// of zero, starting from the index at which the specified <paramref name="parser"/> starts.</returns> public static IObservableParser <TSource, IObservable <TResult> > Success <TSource, TResult>( this IObservableParser <TSource, IObservable <TResult> > parser) { Contract.Requires(parser != null); Contract.Ensures(Contract.Result <IObservableParser <TSource, IObservable <TResult> > >() != null); return(parser.Yield("Success", source => ObservableParseResult.ReturnSuccessMany <TResult>(length: 0))); }
/// <summary> /// Matches the specified <paramref name="parser"/> the specified number of times. /// </summary> /// <typeparam name="TSource">The type of the source elements.</typeparam> /// <typeparam name="TResult">The type of the elements that are generated from parsing the source elements.</typeparam> /// <param name="parser">The parser to be matched.</param> /// <param name="count">The specified number of times to match the specified <paramref name="parser"/>.</param> /// <returns>A parser that matches the specified <paramref name="parser"/> the specified number of times.</returns> public static IObservableParser <TSource, IObservable <TResult> > Exactly <TSource, TResult>( this IObservableParser <TSource, TResult> parser, int count) { Contract.Requires(parser != null); Contract.Requires(count >= 0); Contract.Ensures(Contract.Result <IObservableParser <TSource, IObservable <TResult> > >() != null); if (count == 0) { return(parser.Yield(_ => ObservableParseResult.ReturnSuccessMany <TResult>(length: 0))); } else if (count == 1) { // Profiling has shown this to be about 50% faster than Repeat(parser, 1).All() return(parser.Amplify()); } else if (parser is IObservableParserCursor <TSource> ) { /* Profiling has shown this to be exponentially faster in next.Exactly(largeN) queries for Ix. * It hasn't been profiled in Rx, but I'm assuming that for similar reasons as Ix it would prove * to be exponentially faster. Furthermore, due to the extra plumbing in Rx that's being avoided * by this optimization, it may have even greater gains than Ix. */ return(parser.Yield <TSource, TResult, IObservable <TResult> >( "Exactly", source => from list in source.Take(count).ToList() where list.Count == count select ParseResult.Create(list.Cast <TResult>().ToObservable(Scheduler.Immediate), count))); } else { return(System.Linq.Enumerable.Repeat(parser, count).All()); } }