コード例 #1
0
        public IObservable <IParseResult <TResult> > Parse(IObservableCursor <TSource> source)
        {
#if !SILVERLIGHT && !PORT_45 && !PORT_40
            using (ParserTraceSources.TraceQueryCompilation(name))
#endif
            {
                IObservable <IParseResult <TResult> > results;

                if (parserFactory == null)
                {
                    results = parse(source);

                    Contract.Assume(results != null);
                }
                else
                {
                    var parser = parserFactory.Value;

                    Contract.Assume(parser != null);

                    results = parser.Parse(source);
                }

                return(results);
            }
        }
コード例 #2
0
        public IObservable <IParseResult <TResult> > Parse(IObservableCursor <TSource> source)
        {
            if (Interlocked.Exchange(ref parsing, 1) == 1)
            {
                throw new InvalidOperationException(Errors.ParseCalledWhileParsing);
            }

            if (cursor != null)
            {
                cursor.Dispose();
            }

            cursor = CreateCursor(source);

            object gate = new object();
            bool   allowSubscription = true;

            return(Observable.Create <IParseResult <TResult> >(
                       observer =>
            {
                lock (gate)
                {
                    if (!allowSubscription)
                    {
                        throw new InvalidOperationException(Errors.ParseSubscribeCalledWhileParsing);
                    }

                    allowSubscription = false;
                }

#if !SILVERLIGHT && !PORT_45 && !PORT_40
                var parse = Observable.Using(() => ParserTraceSources.TraceExecution(Cursor, TraceName), Parse);
#else
                var parse = Parse();
#endif

                var parseSubscription = parse.Subscribe(observer);
                var sourceSubscription = cursor.Connect();

                return new CompositeDisposable(sourceSubscription, parseSubscription);
            })
                   .Finally(() =>
            {
                lock (gate)
                {
                    allowSubscription = true;
                }

                Interlocked.Exchange(ref parsing, 0);
            }));
        }
コード例 #3
0
        public IObservable <IParseResult <T> > Parse(IObservableCursor <T> source)
        {
            return(Observable.Create <IParseResult <T> >(
                       observer =>
            {
                return source.Subscribe(
                    Observer.Create <T>(
                        value =>
                {
#if !SILVERLIGHT && !PORT_45 && !PORT_40
                    ParserTraceSources.TraceInput(value);
#endif

                    observer.OnNext(ParseResult.Create(value, length: 1));
                },
                        observer.OnError,
                        observer.OnCompleted),
                    count: 1);
            }));
        }
コード例 #4
0
        protected override IObservable <IParseResult <TResult> > Parse()
#endif
        {
            return(Observable.Create <IParseResult <TResult> >(
                       observer =>
            {
                var cursor = Cursor;

                IObservableParser <TSource, TResult> compiledGrammar;

#if !SILVERLIGHT && !PORT_45 && !PORT_40
                using (ParserTraceSources.TraceGrammarCompilation())
                {
                    compiledGrammar = grammar(cursor);
                }
#else
                compiledGrammar = grammar(cursor);
#endif

                var subscription = new SerialDisposable();

                /* This scheduler is only used for recursion.  It must be Immediate.
                 *
                 * In testing, using a scheduler such as CurrentThread would cause the
                 * ambiguous lab to miss values due to the order in which the ambiguous
                 * parser enqueues the subscription to the underyling source and the
                 * memoizing cursor, in relation to this parser's scheduling of recursion.
                 */
                var schedule = Scheduler.Immediate.Schedule(
                    self =>
                {
#if !SILVERLIGHT && !PORT_45 && !PORT_40
                    traceContext.TraceBeginIteration();
#endif

                    bool hasResult = false;

                    subscription.SetDisposableIndirectly(
                        () => compiledGrammar.Parse(cursor).SubscribeSafe(
                            result =>
                    {
                        var lookAhead = result as ILookAheadParseResult <TResult>;

                        if (lookAhead != null)
                        {
                            lookAhead.OnCompleted(success: true);
                            return;
                        }

                        hasResult = true;

#if !SILVERLIGHT && !PORT_45 && !PORT_40
                        traceContext.TraceResult(result);
#endif

                        observer.OnNext(result);

                        if (!cursor.AtEndOfSequence)
                        {
                            cursor.Move(result.Length);
                        }
                    },
                            observer.OnError,
                            () =>
                    {
                        if (!hasResult)
                        {
                            cursor.MoveToEnd();
                        }

                        if (cursor.AtEndOfSequence)
                        {
                            observer.OnCompleted();
                        }
                        else
                        {
                            self();
                        }
                    }));
                });

                return new CompositeDisposable(schedule, subscription);
            }));
        }