Beispiel #1
0
        /// <summary>
        /// Yields success when the specified <paramref name="parser"/> does not match.
        /// </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 for which any match results in failure.</param>
        /// <returns>A parser that yields failure when the specified <paramref name="parser"/> matches or
        /// an empty sequence to indicate success when it does not match.</returns>
        public static IObservableParser <TSource, IObservable <TResult> > None <TSource, TResult>(
            this IObservableParser <TSource, TResult> parser)
        {
            Contract.Requires(parser != null);
            Contract.Ensures(Contract.Result <IObservableParser <TSource, IObservable <TResult> > >() != null);

            if (parser is IObservableParserCursor <TSource> )
            {
                return(parser.AtEndOfSequence());
            }
            else
            {
                return(parser.Yield <TSource, TResult, IObservable <TResult> >(
                           "None",
                           (source, observer) =>
                {
                    return parser.Parse(source).Any().SubscribeSafe(
                        any =>
                    {
                        if (!any)
                        {
                            observer.OnNext(ObservableParseResult.SuccessMany <TResult>(length: 0));
                        }
                    },
                        observer.OnError,
                        observer.OnCompleted);
                }));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Matches the specified <paramref name="parser"/> or yields success without a value when it does not match.
        /// </summary>
        /// <typeparam name="TSource">The type of the source elements.</typeparam>
        /// <typeparam name="TResult">The type of the elements of the result sequences that are generated from parsing the source elements.</typeparam>
        /// <param name="parser">The parser that might produce matches.</param>
        /// <returns>A parser that yields matches from the specified <paramref name="parser"/> or
        /// an empty observable sequence to indicate success when it does not match.</returns>
        public static IObservableParser <TSource, IObservable <TResult> > Maybe <TSource, TResult>(
            this IObservableParser <TSource, IObservable <TResult> > parser)
        {
            Contract.Requires(parser != null);
            Contract.Ensures(Contract.Result <IObservableParser <TSource, IObservable <TResult> > >() != null);

            return(parser.Yield(
                       "Maybe",
                       (source, observer) =>
            {
                bool hasResult = false;

                return parser.Parse(source).SubscribeSafe(
                    result =>
                {
                    hasResult = true;

                    observer.OnNext(result);
                },
                    observer.OnError,
                    () =>
                {
                    if (!hasResult)
                    {
                        observer.OnNext(ObservableParseResult.SuccessMany <TResult>(length: 0));
                    }

                    observer.OnCompleted();
                });
            }));
        }
Beispiel #3
0
        /// <summary>
        /// Indicates a failure to parse without actually parsing by returning an empty sequence of parse results.
        /// </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 that is to fail.</param>
        /// <returns>A parser that always returns an empty sequence of parse results, starting from the index at which
        /// the specified <paramref name="parser"/> starts.</returns>
        public static IObservableParser <TSource, TResult> Failure <TSource, TResult>(
            this IObservableParser <TSource, TResult> parser)
        {
            Contract.Requires(parser != null);
            Contract.Ensures(Contract.Result <IObservableParser <TSource, TResult> >() != null);

            return(parser.Yield("Failure", source => ObservableParseResult.ReturnFailure <TResult>()));
        }
Beispiel #4
0
        /// <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)));
        }
Beispiel #5
0
        /// <summary>
        /// Indicates a successful parse operation without actually parsing by yielding the specified scalar <paramref name="result"/>
        /// with the specified length.
        /// </summary>
        /// <typeparam name="TSource">The type of the source elements.</typeparam>
        /// <typeparam name="TIntermediate">The type of the elements that are generated from parsing the source elements.</typeparam>
        /// <typeparam name="TResult">The type of the <paramref name="result"/>.</typeparam>
        /// <param name="parser">The parser for which the specified <paramref name="result"/> indicates success.</param>
        /// <param name="result">The value of the created parser's result.</param>
        /// <param name="length">The length of the created parser's result.</param>
        /// <returns>A parser that always returns the specified scalar <paramref name="result"/> with the specified
        /// length, starting from the index at which the specified <paramref name="parser"/> starts.</returns>
        public static IObservableParser <TSource, TResult> Success <TSource, TIntermediate, TResult>(
            this IObservableParser <TSource, TIntermediate> parser,
            TResult result,
            int length)
        {
            Contract.Requires(parser != null);
            Contract.Requires(length >= 0);
            Contract.Ensures(Contract.Result <IObservableParser <TSource, TResult> >() != null);

            return(parser.Yield("Success", source => ObservableParseResult.Return(result, length)));
        }
Beispiel #6
0
        /// <summary>
        /// Yields success if the specified parser starts at the end of the input sequence.
        /// </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 that provides the context in which to check whether the cursor is at the end of the input sequence.</param>
        /// <returns>A new parser that yields success without parsing if the cursor is positioned at the end of the input sequence; otherwise, yields no results.</returns>
        public static IObservableParser <TSource, IObservable <TResult> > AtEndOfSequence <TSource, TResult>(
            this IObservableParser <TSource, TResult> parser)
        {
            Contract.Requires(parser != null);
            Contract.Ensures(Contract.Result <IObservableParser <TSource, IObservable <TResult> > >() != null);

            return(parser.Yield <TSource, TResult, IObservable <TResult> >(
                       "AtEndOfSequence",
                       (source, observer) =>
            {
                IDisposable disposable;

                if (source.IsSequenceTerminated)
                {
                    if (source.AtEndOfSequence)
                    {
                        observer.OnNext(ObservableParseResult.SuccessMany <TResult>(length: 0));
                    }

                    observer.OnCompleted();

                    disposable = Disposable.Empty;
                }
                else
                {
                    bool hasResult = false;

                    disposable = source.Subscribe(
                        Observer.Create <TSource>(
                            result => hasResult = true,
                            observer.OnError,
                            () =>
                    {
                        if (!hasResult)
                        {
                            Contract.Assume(source.AtEndOfSequence);

                            observer.OnNext(ObservableParseResult.SuccessMany <TResult>(length: 0));
                        }

                        observer.OnCompleted();
                    }),
                        count: 1);
                }

                return disposable;
            }));
        }
Beispiel #7
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());
            }
        }