Exemple #1
0
        private bool Rest(Parser <TToken, T> parser, ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, List <T> ts)
        {
            var lastStartingLoc = state.Location;
            var childExpecteds  = new ExpectedCollector <TToken>();
            var success         = parser.TryParse(ref state, ref childExpecteds, out var result);

            while (success)
            {
                var endingLoc = state.Location;
                childExpecteds.Clear();

                if (endingLoc <= lastStartingLoc)
                {
                    childExpecteds.Dispose();
                    throw new InvalidOperationException("Many() used with a parser which consumed no input");
                }

                ts.Add(result);

                lastStartingLoc = endingLoc;
                success         = parser.TryParse(ref state, ref childExpecteds, out result);
            }
            var lastParserConsumedInput = state.Location > lastStartingLoc;

            expecteds.AddIf(ref childExpecteds, lastParserConsumedInput);
            childExpecteds.Dispose();

            // we fail if the most recent parser failed after consuming input.
            // it sets state.Error for us
            return(!lastParserConsumedInput);
        }
Exemple #2
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);
        }
Exemple #3
0
        internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out U result)
        {
            var success1 = _parser.TryParse(ref state, ref expecteds, out var result1);

            if (!success1)
            {
                // state.Error set by _parser
                result = default;
                return(false);
            }

            var chainer = _factory();

            chainer.Apply(result1);

            var lastStartLoc   = state.Location;
            var childExpecteds = new ExpectedCollector <TToken>();
            var success        = _parser.TryParse(ref state, ref childExpecteds, out var childResult);

            while (success)
            {
                var endLoc = state.Location;
                childExpecteds.Clear();
                if (endLoc <= lastStartLoc)
                {
                    childExpecteds.Dispose();
                    chainer.OnError();
                    throw new InvalidOperationException("Many() used with a parser which consumed no input");
                }
                chainer.Apply(childResult);

                lastStartLoc = endLoc;
                success      = _parser.TryParse(ref state, ref childExpecteds, out childResult);
            }
            var lastParserConsumedInput = state.Location > lastStartLoc;

            expecteds.AddIf(ref childExpecteds, lastParserConsumedInput);
            childExpecteds.Dispose();

            if (lastParserConsumedInput)  // the most recent parser failed after consuming input
            {
                // state.Error set by _parser
                chainer.OnError();
                result = default;
                return(false);
            }

            result = chainer.GetResult();
            return(true);
        }
Exemple #4
0
        internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out T result)
        {
            var childExpecteds = new ExpectedCollector <TToken>();

            var success = _parser.TryParse(ref state, ref childExpecteds, out result);

            expecteds.AddIf(ref childExpecteds, success);
            childExpecteds.Dispose();

            if (!success)
            {
                return(false);
            }

            if (!_predicate(result))
            {
                state.Error = new InternalError <TToken>(
                    Maybe.Nothing <TToken>(),
                    false,
                    state.Location,
                    _message(result)
                    );
                expecteds.Add(_expected);

                result = default;
                return(false);
            }
            return(true);
        }
Exemple #5
0
        internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out Unit result)
        {
            var startingLocation = state.Location;
            var token            = state.HasCurrent ? Maybe.Just(state.Current) : Maybe.Nothing <TToken>();

            state.PushBookmark();  // make sure we don't throw out the buffer, we may need it to compute a SourcePos
            var childExpecteds = new ExpectedCollector <TToken>(true);

            var success = _parser.TryParse(ref state, ref childExpecteds, out var result1);

            childExpecteds.Dispose();
            state.PopBookmark();

            if (success)
            {
                state.Error = new InternalError <TToken>(
                    token,
                    false,
                    startingLocation,
                    null
                    );
                result = default;
                return(false);
            }

            result = Unit.Value;
            return(true);
        }
Exemple #6
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 childExpecteds = new ExpectedCollector <TToken>();
            var success        = _parser.TryParse(ref state, ref childExpecteds, out result);

            if (success)
            {
                childExpecteds.Dispose();
                return(true);
            }

            var recoverParser = _errorHandler(state.BuildError(ref childExpecteds));

            childExpecteds.Dispose();

            return(recoverParser.TryParse(ref state, ref expecteds, out result));
        }
Exemple #7
0
        internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out T result)
        {
            var childExpecteds = new ExpectedCollector <TToken>(true);
            var success        = _parser.TryParse(ref state, ref childExpecteds, out result);

            childExpecteds.Dispose();
            if (!success)
            {
                expecteds.Add(_expected);
            }
            return(success);
        }
Exemple #8
0
        private static Result <TToken, T> DoParse <TToken, T>(Parser <TToken, T> parser, ref ParseState <TToken> state)
        {
            var startingLoc = state.Location;
            var expecteds   = new ExpectedCollector <TToken>();
            var success     = parser.TryParse(ref state, ref expecteds, out var result);

            var result1 = success
                ? new Result <TToken, T>(state.Location > startingLoc, result)
                : new Result <TToken, T>(state.Location > startingLoc, state.BuildError(ref expecteds));

            expecteds.Dispose();
            state.Dispose();  // ensure we return the state's buffers to the buffer pool

            return(result1);
        }
Exemple #9
0
        // see comment about expecteds in ParseState.Error.cs
        internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out IEnumerable <T>?result)
        {
            var ts = _keepResults ? new List <T>() : null;

            var firstItemStartLoc = state.Location;
            var firstItemSuccess  = _parser.TryParse(ref state, ref expecteds, out var result1);

            if (!firstItemSuccess)
            {
                // state.Error set by _parser
                result = null;
                return(false);
            }
            if (state.Location <= firstItemStartLoc)
            {
                throw new InvalidOperationException("Until() used with a parser which consumed no input");
            }
            ts?.Add(result1);

            var terminatorExpecteds = new ExpectedCollector <TToken>();
            var itemExpecteds       = new ExpectedCollector <TToken>();

            while (true)
            {
                var terminatorStartLoc = state.Location;
                var terminatorSuccess  = _terminator.TryParse(ref state, ref terminatorExpecteds, out var terminatorResult);
                if (terminatorSuccess)
                {
                    terminatorExpecteds.Dispose();
                    itemExpecteds.Dispose();
                    result = ts;
                    return(true);
                }
                if (state.Location > terminatorStartLoc)
                {
                    // state.Error set by _terminator
                    expecteds.Add(ref terminatorExpecteds);
                    terminatorExpecteds.Dispose();
                    itemExpecteds.Dispose();
                    result = null;
                    return(false);
                }

                var itemStartLoc      = state.Location;
                var itemSuccess       = _parser.TryParse(ref state, ref itemExpecteds, out var itemResult);
                var itemConsumedInput = state.Location > itemStartLoc;
                if (!itemSuccess)
                {
                    if (!itemConsumedInput)
                    {
                        // get the expected from both _terminator and _parser
                        expecteds.Add(ref terminatorExpecteds);
                        expecteds.Add(ref itemExpecteds);
                    }
                    else
                    {
                        // throw out the _terminator expecteds and keep only _parser
                        expecteds.Add(ref itemExpecteds);
                    }
                    terminatorExpecteds.Dispose();
                    itemExpecteds.Dispose();
                    result = null;
                    return(false);
                }
                // throw out both sets of expecteds
                terminatorExpecteds.Clear();
                itemExpecteds.Clear();
                if (!itemConsumedInput)
                {
                    throw new InvalidOperationException("Until() used with a parser which consumed no input");
                }
                ts?.Add(itemResult);
            }
        }
Exemple #10
0
        internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out IEnumerable <T> result)
        {
            var success = _parser.TryParse(ref state, ref expecteds, out var result1);

            if (!success)
            {
                // state.Error set by _parser
                result = null;
                return(false);
            }
            var ts = new List <T> {
                result1
            };

            var childExpecteds = new ExpectedCollector <TToken>();

            while (true)
            {
                var sepStartLoc      = state.Location;
                var sepSuccess       = _separator.TryParse(ref state, ref childExpecteds, out var _);
                var sepConsumedInput = state.Location > sepStartLoc;

                expecteds.AddIf(ref childExpecteds, !sepSuccess && sepConsumedInput);
                childExpecteds.Clear();

                if (!sepSuccess)
                {
                    childExpecteds.Dispose();
                    if (sepConsumedInput)
                    {
                        // state.Error set by _separator
                        result = null;
                        return(false);
                    }
                    result = ts;
                    return(true);
                }


                var itemStartLoc      = state.Location;
                var itemSuccess       = _parser.TryParse(ref state, ref childExpecteds, out var itemResult);
                var itemConsumedInput = state.Location > itemStartLoc;

                expecteds.AddIf(ref childExpecteds, !itemSuccess && itemConsumedInput);
                childExpecteds.Clear();

                if (!itemSuccess)
                {
                    childExpecteds.Dispose();
                    if (itemConsumedInput)
                    {
                        // state.Error set by _parser
                        result = null;
                        return(false);
                    }
                    result = ts;
                    return(true);
                }
                ts.Add(itemResult);
            }
        }