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); } }
public ObservableParserCursor(IObservableCursor <T> cursor) { Contract.Requires(cursor != null); Contract.Requires(cursor.IsForwardOnly); this.cursor = cursor; }
public IObservable <IParseResult <TResult> > Parse(IObservableCursor <TSource> source) { Contract.Requires(source != null); Contract.Requires(source.IsForwardOnly); Contract.Ensures(Contract.Result <IObservable <IParseResult <TResult> > >() != null); return(null); }
public IObservable <IParseResult <IObservable <TResult> > > Parse(IObservableCursor <TSource> source) { return(Observable.Defer(() => { firstParser = null; bool first = true; var any = new AnyObservableParser <TSource, TResult>(parsers); var except = new List <IObservableParser <TSource, TResult> >(); // See the AllObservableParser.Parse method for an explanation of the optimization that is provided by SelectMany's TContext argument var root = source.Branch(); var rootDisposable = new RefCountDisposable(root); return ObservableParseResult.ReturnSuccessMany <TResult>(0) .SelectMany( Tuple.Create(root, rootDisposable), parsers.Select( parser => (Func <Tuple <IObservableCursor <TSource>, RefCountDisposable>, Tuple <IParseResult <IObservable <TResult> >, bool>, Tuple <Tuple <IObservableCursor <TSource>, RefCountDisposable>, IObservable <IParseResult <IObservable <TResult> > > > >) ((context, value) => { if (first) { first = false; firstParser = parser; } var branch = context.Item1; var disposable = context.Item2; var refDisposable = disposable.GetDisposable(); IObservable <IParseResult <IObservable <TResult> > > results; // Item2 is only true when value.Item1 is the last element of its sequence. if (value.Item2) { branch.Move(value.Item1.Length); results = any.Parse(except, branch) .Select(result => result.YieldMany()) .Finally(refDisposable.Dispose); } else { branch = branch.Remainder(value.Item1.Length); disposable = new RefCountDisposable(new CompositeDisposable(branch, refDisposable)); results = any.Parse(except, branch) .Select(result => result.YieldMany()) .Finally(disposable.Dispose); } return Tuple.Create(Tuple.Create(branch, disposable), results); })), (firstResult, otherResults) => firstResult.Concat(otherResults)) .Finally(rootDisposable.Dispose); })); }
/// <summary> /// Applies the parser's grammar, which is defined by <see cref="Start"/>, to generate matches asynchronously. /// </summary> /// <param name="source">The observable sequence to parse.</param> /// <returns>An observable sequence of parse results.</returns> public IObservable <TResult> Parse(IObservableCursor <TSource> source) { Contract.Requires(source != null); Contract.Requires(source.IsForwardOnly); Contract.Ensures(Contract.Result <IObservable <TResult> >() != null); return(parser.Parse(source).Select(result => result.Value)); }
protected virtual ObservableParserCursor <TSource> CreateCursor(IObservableCursor <TSource> source) { Contract.Requires(source != null); Contract.Requires(source.IsForwardOnly); Contract.Ensures(Contract.Result <ObservableParserCursor <TSource> >() != null); return(new ObservableParserCursor <TSource>(source)); }
private static IObservable <IParseResult <TResult> > SelectManyInternal <TSource, TFirstResult, TSecondResult, TResult>( IObservableCursor <TSource> source, IObservableParser <TSource, TFirstResult> firstParser, Func <TFirstResult, IObservableParser <TSource, TSecondResult> > secondSelector, Func <TFirstResult, TSecondResult, TResult> resultSelector, Func <IParseResult <TFirstResult>, IParseResult <TSecondResult>, int> lengthSelector = null) { Contract.Requires(source != null); Contract.Requires(source.IsForwardOnly); Contract.Requires(firstParser != null); Contract.Requires(secondSelector != null); Contract.Requires(resultSelector != null); Contract.Ensures(Contract.Result <IObservable <IParseResult <TResult> > >() != null); return(from first in firstParser.Parse(source) from second in Observable.Create <IParseResult <TSecondResult> >( observer => { var lookAhead = first as ILookAheadParseResult <TFirstResult>; bool hasResult = false; var remainder = source.Remainder(first.Length); return secondSelector(first.Value) .Parse(remainder) .Finally(remainder.Dispose) .Subscribe( second => { hasResult = true; if (lookAhead != null) { lookAhead.OnCompleted(success: true); observer.OnCompleted(); } else { observer.OnNext(second); } }, observer.OnError, () => { if (!hasResult && lookAhead != null) { lookAhead.OnCompleted(success: false); } observer.OnCompleted(); }); }) select lengthSelector == null ? first.Add(second, resultSelector) : first.Yield(second, resultSelector, lengthSelector)); }
[ContractVerification(false)] // Static checker times out (raised time-out setting to 20 minutes and it still timed out) public static IObservableCursor <TSource> Remainder <TSource>(this IObservableCursor <TSource> cursor, int skip) { Contract.Requires(cursor != null); Contract.Requires(skip >= 0); Contract.Ensures(cursor.IsSynchronized == Contract.OldValue(cursor.IsSynchronized)); Contract.Ensures(cursor.IsForwardOnly == Contract.OldValue(cursor.IsForwardOnly)); Contract.Ensures(Contract.Result <IObservableCursor <TSource> >() != null); Contract.Ensures(Contract.Result <IObservableCursor <TSource> >().IsSynchronized == cursor.IsSynchronized); Contract.Ensures(Contract.Result <IObservableCursor <TSource> >().IsForwardOnly == cursor.IsForwardOnly); Contract.Ensures(cursor.IsSynchronized || Contract.Result <IObservableCursor <TSource> >().IsSequenceTerminated == cursor.IsSequenceTerminated); Contract.Ensures(cursor.IsSynchronized || Contract.Result <IObservableCursor <TSource> >().LatestIndex == cursor.LatestIndex); Contract.Ensures(cursor.IsSynchronized || Contract.Result <IObservableCursor <TSource> >().CurrentIndex == (cursor.AtEndOfSequence ? cursor.CurrentIndex : cursor.IsSequenceTerminated ? Math.Min(cursor.CurrentIndex + skip, cursor.LatestIndex + 1) : cursor.CurrentIndex + skip)); var branch = cursor.Branch(); Contract.Assert(branch.IsSynchronized == cursor.IsSynchronized); Contract.Assert(branch.IsSynchronized || branch.IsSequenceTerminated == cursor.IsSequenceTerminated); Contract.Assert(branch.IsSynchronized || branch.CurrentIndex == cursor.CurrentIndex); Contract.Assert(branch.IsSynchronized || branch.LatestIndex == cursor.LatestIndex); Contract.Assert(branch.IsSynchronized || branch.AtEndOfSequence == cursor.AtEndOfSequence); if (branch.IsSynchronized) { branch.Move(skip); } else if (!branch.AtEndOfSequence) { int count = skip; if (branch.IsSequenceTerminated && branch.CurrentIndex + count > branch.LatestIndex + 1) { count = (branch.LatestIndex + 1) - branch.CurrentIndex; Contract.Assert(cursor.CurrentIndex + count == cursor.LatestIndex + 1); } branch.Move(count); Contract.Assert(!branch.IsSynchronized); Contract.Assert(branch.CurrentIndex == cursor.CurrentIndex + count); Contract.Assert(cursor.IsSequenceTerminated || branch.CurrentIndex == cursor.CurrentIndex + skip); Contract.Assume(!cursor.IsSequenceTerminated || cursor.CurrentIndex + skip <= cursor.LatestIndex + 1 || branch.CurrentIndex == cursor.LatestIndex + 1); Contract.Assume(!cursor.IsSequenceTerminated || branch.CurrentIndex == Math.Min(cursor.CurrentIndex + skip, cursor.LatestIndex + 1)); } else { Contract.Assert(branch.CurrentIndex == cursor.CurrentIndex); } return(branch); }
public SynchronizedObservableCursor(IObservableCursor <T> cursor, object gate = null) { Contract.Requires(cursor != null); Contract.Ensures(IsSynchronized); Contract.Ensures(IsForwardOnly == cursor.IsForwardOnly); this.cursor = cursor; this.gate = gate ?? new object(); Contract.Assume(IsForwardOnly == cursor.IsForwardOnly); }
public IObservable <TResult> Parse(IObservableCursor <char> source, IObservableParser <char, TResult> grammar) { Contract.Requires(source != null); Contract.Requires(source.IsForwardOnly); Contract.Requires(grammar != null); Contract.Ensures(Contract.Result <IObservable <TResult> >() != null); this.start = grammar; return(base.Parse(source)); }
public static IObservableCursor <TSource> Synchronize <TSource>(this IObservableCursor <TSource> cursor) { Contract.Requires(cursor != null); Contract.Ensures(cursor.IsSynchronized == Contract.OldValue(cursor.IsSynchronized)); Contract.Ensures(cursor.IsForwardOnly == Contract.OldValue(cursor.IsForwardOnly)); Contract.Ensures(Contract.Result <IObservableCursor <TSource> >() != null); Contract.Ensures(Contract.Result <IObservableCursor <TSource> >().IsSynchronized); Contract.Ensures(Contract.Result <IObservableCursor <TSource> >().IsForwardOnly == cursor.IsForwardOnly); return(new SynchronizedObservableCursor <TSource>(cursor)); }
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); })); }
public IObservable <IParseResult <TResult> > Parse(IObservableCursor <TSource> source) { return(Observable.Defer(() => { var completed = new AsyncSubject <Unit>(); bool hasResult = false; return parsers.Select( parser => Observable.Create <IParseResult <TResult> >( observer => { return parser.Parse(source).SubscribeSafe( result => { if (!hasResult) { hasResult = true; /* The XML lab has shown that Parse may be called multiple times on the same AnyObservableParser * instance during a single Parse operation, sometimes with the same source but most of the time * with a different source; therefore, the selected parser must be reassigned to the latest selection * for each call to Parse, maintaining a local variable (hasResult) to determine whether the current * call to Parse has matched while enumerating the choices. * * It is currently unknown whether it is possible for a nested Parse operation to overwrite the * selected parser, or whether it will have any negative impact. */ selectedParser = parser; } observer.OnNext(result); }, observer.OnError, () => { if (hasResult) { completed.OnNext(new Unit()); completed.OnCompleted(); } observer.OnCompleted(); }); })) .Concat() .TakeUntil(completed); })); }
public ObservableParserCursorBranch(IObservableCursor<T> branch, Action dispose) { Contract.Requires(branch != null); Contract.Requires(branch.IsForwardOnly); Contract.Requires(dispose != null); Contract.Ensures(IsSynchronized == branch.IsSynchronized); Contract.Ensures(IsForwardOnly == branch.IsForwardOnly); Contract.Ensures(IsSynchronized || CurrentIndex == branch.CurrentIndex); Contract.Ensures(IsSynchronized || LatestIndex == branch.LatestIndex); Contract.Ensures(IsSynchronized || AtEndOfSequence == branch.AtEndOfSequence); Contract.Ensures(IsSynchronized || IsSequenceTerminated == branch.IsSequenceTerminated); this.branch = branch; this.dispose = dispose; }
internal IObservable <IParseResult <TResult> > Parse( ICollection <IObservableParser <TSource, TResult> > except, IObservableCursor <TSource> source) { Contract.Requires(except != null); Contract.Requires(!except.IsReadOnly); Contract.Requires(source != null); Contract.Ensures(Contract.Result <IObservable <IParseResult <TResult> > >() != null); return(Observable.Defer(() => { var completed = new AsyncSubject <Unit>(); bool hasResult = false; return parsers.Except(except).Select( parser => Observable.Create <IParseResult <TResult> >( observer => { return parser.Parse(source).SubscribeSafe( result => { if (!hasResult) { hasResult = true; except.Add(parser); } observer.OnNext(result); }, observer.OnError, () => { if (hasResult) { completed.OnNext(new Unit()); completed.OnCompleted(); } observer.OnCompleted(); }); })) .Concat() .TakeUntil(completed); })); }
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); })); }
private static IObservable <IParseResult <TResult> > SelectManyInternal <TSource, TFirstResult, TCollection, TResult>( IObservableCursor <TSource> source, IObservableParser <TSource, TFirstResult> parser, Func <TFirstResult, IObservable <TCollection> > collectionSelector, Func <TFirstResult, TCollection, TResult> resultSelector, Func <IParseResult <TFirstResult>, TCollection, int> lengthSelector = null) { Contract.Requires(source != null); Contract.Requires(source.IsForwardOnly); Contract.Requires(parser != null); Contract.Requires(collectionSelector != null); Contract.Requires(resultSelector != null); Contract.Ensures(Contract.Result <IObservable <IParseResult <TResult> > >() != null); return(from first in parser.Parse(source) from second in Observable.Create <Tuple <TCollection, bool> >( observer => { var lookAhead = first as ILookAheadParseResult <TFirstResult>; var hasResult = false; TCollection previous = default(TCollection); return collectionSelector(first.Value).Subscribe( second => { if (lookAhead != null) { hasResult = true; lookAhead.OnCompleted(success: true); observer.OnCompleted(); } else { if (hasResult) { observer.OnNext(Tuple.Create(previous, false)); } hasResult = true; previous = second; } }, observer.OnError, () => { if (hasResult && lookAhead == null) { observer.OnNext(Tuple.Create(previous, true)); } else if (!hasResult && lookAhead != null) { lookAhead.OnCompleted(success: false); } observer.OnCompleted(); }); }) select lengthSelector == null ? first.Yield(second.Item1, resultSelector, (f, s) => second.Item2?f.Length : 0) : first.Yield(second.Item1, resultSelector, lengthSelector)); }
IObservable <IParseResult <TResult> > IObservableParser <byte, TResult> .Parse(IObservableCursor <byte> source) { throw new NotSupportedException(Properties.Errors.InlineParseNotSupported); }
public IObservable <IParseResult <T> > Parse(IObservableCursor <T> source) { return(ParserCursor.Parse(source)); }
public IObservable <IParseResult <IObservable <TResult> > > Parse(IObservableCursor <TSource> source) { return(Observable.Defer(() => { firstParser = null; bool first = true; /* The TContext of branches allows for an optimization on top of the previous implementation, which used to create a new * branch for every parse result in every parse result sequence. This new implementation changes that behavior slightly * by not creating a new branch for the last result in each sequence. All parser rules (at the time of writing) in Rxx * generate zero or one result only; therefore, the current branch can be moved forward and reused by child sequences * without affecting the parent result sequence, because it's already completed. This optimization has proven to be * slightly beneficial across normal parser queries that use And, All and Exactly operators. It should also be beneficial * for multi-result queries since most of the individual parser rules in these queries will only generate a single result. * A new branch would only be created for each result in the multi-result sequence. Scalar-result parsers that follow * sequentially in the All query would simply move their shared parent branch instead of creating new branches. */ var root = source.Branch(); var rootDisposable = new RefCountDisposable(root); return ObservableParseResult.ReturnSuccessMany <TResult>(0) .SelectMany( Tuple.Create(root, rootDisposable), parsers.Select( parser => (Func <Tuple <IObservableCursor <TSource>, RefCountDisposable>, Tuple <IParseResult <IObservable <TResult> >, bool>, Tuple <Tuple <IObservableCursor <TSource>, RefCountDisposable>, IObservable <IParseResult <IObservable <TResult> > > > >) ((context, value) => { if (first) { first = false; firstParser = parser; } var branch = context.Item1; var disposable = context.Item2; var refDisposable = disposable.GetDisposable(); IObservable <IParseResult <IObservable <TResult> > > results; // Item2 is only true when value.Item1 is the last element of its sequence. if (value.Item2) { branch.Move(value.Item1.Length); results = parser.Parse(branch) .Select(result => result.YieldMany()) .Finally(refDisposable.Dispose); } else { branch = branch.Remainder(value.Item1.Length); disposable = new RefCountDisposable(new CompositeDisposable(branch, refDisposable)); results = parser.Parse(branch) .Select(result => result.YieldMany()) .Finally(disposable.Dispose); } return Tuple.Create(Tuple.Create(branch, disposable), results); })), (firstResult, otherResults) => firstResult.Concat(otherResults)) .Finally(rootDisposable.Dispose); })); }
IObservable <IParseResult <char> > IObservableParser <char, char> .Parse(IObservableCursor <char> source) { throw new NotSupportedException(Properties.Errors.InlineParseNotSupported); }
IObservable <IParseResult <TResult> > IObservableParser <TSource, TResult> .Parse(IObservableCursor <TSource> source) { return(parser.Parse(source)); }
public IObservable <IParseResult <IObservable <TResult> > > Parse(IObservableCursor <TSource> source) { return(Observable.Create <IParseResult <IObservable <TResult> > >( observer => { int matchCount = 0; int remainingLength = 0; Action <Action> iterate = moveNext => { bool hasResult = false; int length = 0; var branch = source.Branch(); var values = parser.Parse(branch) .Finally(branch.Dispose) .Select(result => { if (!hasResult) { matchCount++; hasResult = true; } length = Math.Max(length, result.Length); return result.Value; }) .Do( __ => { }, () => { /* We must respect the greediness of the results unless the length is zero since the * cursor would have already moved to the following element. It is acceptable to ignore * zero-length results because marking an entirely non-greedy parser as ambiguous would * otherwise cause the parser to continously parse the first element indefinitely. */ if (length > 0) { remainingLength = length - 1; } else if (remainingLength > 0) { remainingLength--; } moveNext(); }); observer.OnNext(ParseResult.Create(values, length: 1)); }; Action complete = () => { if (remainingLength > 0) { observer.OnNext(ObservableParseResult.SuccessMany <TResult>(remainingLength)); } observer.OnCompleted(); }; var untilSubscription = new SerialDisposable(); var schedule = Scheduler.Immediate.Schedule( self => { if (!source.AtEndOfSequence && (untilCount == unlimitedCount || matchCount < untilCount)) { if (untilParser == null) { iterate(self); } else { untilSubscription.SetDisposableIndirectly(() => untilParser.Parse(source).Any().Subscribe( any => { if (!any) { iterate(self); } else { complete(); } }, observer.OnError)); } } else { complete(); } }); return new CompositeDisposable(schedule, untilSubscription); })); }
private static IObservable <IParseResult <IObservable <TSource> > > AmbiguousGroupInternal <TSource>( IObservableCursor <TSource> source, IObservableParser <TSource, TSource> open, IObservableParser <TSource, TSource> close) { Contract.Requires(source != null); Contract.Requires(open != null); Contract.Requires(close != null); Contract.Ensures(Contract.Result <IObservable <IParseResult <IObservable <TSource> > > >() != null); return(Observable.Create <IParseResult <IObservable <TSource> > >( observer => { var branch = source.Branch(); var disposables = new CompositeDisposable(branch); bool hasOpenResult = false; disposables.Add(open.Parse(source).SubscribeSafe( openResult => { hasOpenResult = true; int openCount = 1; var openSinks = new List <Action <IParseResult <TSource> > >(); var closeSinks = new List <Action <IParseResult <TSource> > >(); var contentSinks = new List <Action <IParseResult <TSource> > >(); var bufferedResults = new List <IEnumerable <IParseResult <IObservable <TSource> > > >(); Func <List <IParseResult <IObservable <TSource> > > > addBuffer = () => { var buffer = new List <IParseResult <IObservable <TSource> > >(); bufferedResults.Add(buffer); return buffer; }; Action installSinks = () => { var buffer = addBuffer(); var content = new List <TSource>(); openSinks.Add(result => content.Add(result.Value)); contentSinks.Add(result => content.Add(result.Value)); closeSinks.Add(result => { // copy the content list to create a new branch var branchResult = result.Yield(new List <TSource>(content).ToObservable(Scheduler.Immediate)); buffer.Add(branchResult); if (openCount > 0) { content.Add(result.Value); } }); }; // base sinks must be installed first - openCount must be incremented before other sinks are executed openSinks.Add(_ => { openCount++; installSinks(); }); closeSinks.Add(_ => { openCount--; }); // now we can install the sinks for the first open (matched in the foreach above) installSinks(); var innerBranch = branch.Remainder(openResult.Length); bool hasInnerResult = false; IObservableParser <TSource, TSource> current = open; var recursion = new SingleAssignmentDisposable(); disposables.Add(recursion); recursion.Disposable = Scheduler.Immediate.Schedule( self => { var capturedBranch = innerBranch; var innerParser = open.OnSuccess(innerOpenResult => { hasInnerResult = true; var clone = openSinks.ToList(); // the sinks list is modified when open is matched, so we must run a clone clone.ForEach(sink => sink(innerOpenResult)); innerBranch = capturedBranch.Remainder(innerOpenResult.Length); current = open; }) .Or( close.OnSuccess(closeResult => { hasInnerResult = true; closeSinks.ForEach(sink => sink(closeResult)); innerBranch = capturedBranch.Remainder(closeResult.Length); current = close; })) .Or( current.Next.OnSuccess(content => { hasInnerResult = true; contentSinks.ForEach(sink => sink(content)); innerBranch = capturedBranch.Remainder(content.Length); })); var innerSubscription = new SingleAssignmentDisposable(); disposables.Add(innerSubscription); innerSubscription.Disposable = innerParser.Parse(capturedBranch).SubscribeSafe( _ => { }, observer.OnError, () => { if (openCount > 0 && hasInnerResult) { self(); } else { innerBranch.Dispose(); disposables.Remove(innerSubscription); disposables.Remove(recursion); if (hasInnerResult) { try { bufferedResults.Concat().ForEach(observer.OnNext); } catch (Exception ex) { observer.OnError(ex); } observer.OnCompleted(); } else { // completing without results is failure observer.OnCompleted(); } } }); }); }, observer.OnError, () => { if (!hasOpenResult) { observer.OnCompleted(); } })); return disposables; })); }
public IObservable <IParseResult <TResult> > Parse(IObservableCursor <byte> source) { return(null); }