예제 #1
0
        // see comment about expecteds in ParseState.Error.cs
        internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out T result)
        {
            var firstTime = true;
            var err       = new InternalError <TToken>(
                Maybe.Nothing <TToken>(),
                false,
                state.Location,
                "OneOf had no arguments"
                );

            var childExpecteds      = new ExpectedCollector <TToken>(); // the expecteds for all loop iterations
            var grandchildExpecteds = new ExpectedCollector <TToken>(); // the expecteds for the current loop iteration

            foreach (var p in _parsers)
            {
                var thisStartLoc = state.Location;
                var success      = p.TryParse(ref state, ref grandchildExpecteds, out result);
                if (success)
                {
                    // throw out all expecteds
                    grandchildExpecteds.Dispose();
                    childExpecteds.Dispose();
                    return(true);
                }

                // we'll usually return the error from the first parser that didn't backtrack,
                // even if other parsers had a longer match.
                // There is some room for improvement here.
                if (state.Location > thisStartLoc)
                {
                    // throw out all expecteds except this one
                    expecteds.Add(ref grandchildExpecteds);
                    childExpecteds.Dispose();
                    grandchildExpecteds.Dispose();
                    result = default;
                    return(false);
                }

                childExpecteds.Add(ref grandchildExpecteds);
                grandchildExpecteds.Clear();
                // choose the longest match, preferring the left-most error in a tie,
                // except the first time (avoid returning "OneOf had no arguments").
                if (firstTime || state.Error.ErrorLocation > err.ErrorLocation)
                {
                    err = state.Error;
                }
                firstTime = false;
            }
            state.Error = err;
            expecteds.Add(ref childExpecteds);
            childExpecteds.Dispose();
            grandchildExpecteds.Dispose();
            result = default;
            return(false);
        }
예제 #2
0
            // see comment about expecteds in ParseState.Error.cs
            internal sealed override InternalResult <T> Parse(ref ParseState <TToken> state)
            {
                var firstTime = true;
                var err       = new InternalError <TToken>(
                    Maybe.Nothing <TToken>(),
                    false,
                    state.Location,
                    "OneOf had no arguments"
                    );

                state.BeginExpectedTran();
                foreach (var p in _parsers)
                {
                    state.BeginExpectedTran();
                    var thisResult = p.Parse(ref state);
                    if (thisResult.Success)
                    {
                        // throw out all expecteds
                        state.EndExpectedTran(false);
                        state.EndExpectedTran(false);
                        return(thisResult);
                    }

                    // we'll usually return the error from the first parser that didn't backtrack,
                    // even if other parsers had a longer match.
                    // There is some room for improvement here.
                    if (thisResult.ConsumedInput)
                    {
                        // throw out all expecteds except this one
                        var expected = state.ExpectedTranState();
                        state.EndExpectedTran(false);
                        state.EndExpectedTran(false);
                        state.AddExpected(expected.AsSpan());
                        expected.Dispose(clearArray: true);
                        return(thisResult);
                    }

                    state.EndExpectedTran(true);
                    // choose the longest match, preferring the left-most error in a tie,
                    // except the first time (avoid returning "OneOf had no arguments").
                    if (firstTime || state.Error.ErrorLocation > err.ErrorLocation)
                    {
                        err = state.Error;
                    }
                    firstTime = false;
                }
                state.Error = err;
                state.EndExpectedTran(true);
                return(InternalResult.Failure <T>(false));
            }