Exemplo n.º 1
0
        public static IGeneralReply FailsToParse(this IGeneralParser parser, IEnumerable <Token> tokens)
        {
            var reply = parser.ParseGenerally(new TokenStream(tokens));

            if (reply.Success)
            {
                throw new AssertionException("parser failure", "parser completed successfully");
            }

            return(reply);
        }
Exemplo n.º 2
0
        /// <inheritdoc/>
        public override IReply <TValue[]> Parse(TokenStream tokens)
        {
            var tokensToParse = tokens ?? throw new ArgumentNullException(nameof(tokens));

            var parsersLength = _items.Length;

            var result      = new TValue[parsersLength];
            var parsersUsed = new bool[parsersLength];
            var parsersToGo = parsersLength;

            var separatorParserIsPresent = _separator != null;

            var failures = FailureMessages.Empty;

            var atLeastOneItemParsed = false;

            var separatorWasTheLastTokenParsed = false;

            for (var i = 0; i < parsersLength; ++i)
            {
                if (parsersUsed[i])
                {
                    continue;
                }

                if (separatorParserIsPresent && atLeastOneItemParsed && !separatorWasTheLastTokenParsed)
                {
                    var positionBeforeSeparator = tokensToParse.Position;
                    var separatorReply          = _separator.ParseGenerally(tokensToParse);
                    var positionAfterSeparator  = separatorReply.UnparsedTokens.Position;

                    separatorWasTheLastTokenParsed = separatorReply.Success;

                    if (separatorWasTheLastTokenParsed)
                    {
                        if (positionBeforeSeparator == positionAfterSeparator)
                        {
                            throw new Exception($"Separator parser {_separator.Expression} encountered a potential infinite loop at position {positionBeforeSeparator}.");
                        }
                    }
                    else
                    {
                        if (positionBeforeSeparator != positionAfterSeparator || _mode == UnorderedParsingMode.FullSet)
                        {
                            return(Failure <TValue[]> .From(separatorReply));
                        }
                    }

                    tokensToParse = separatorReply.UnparsedTokens;
                }

                var oldPosition = tokensToParse.Position;
                var reply       = _items[i].Parse(tokensToParse);
                var newPosition = reply.UnparsedTokens.Position;

                tokensToParse = reply.UnparsedTokens;

                if (reply.Success)
                {
                    if (newPosition == oldPosition)
                    {
                        throw new Exception($"Item parser {_items[i].Expression} encountered a potential infinite loop at position {newPosition}.");
                    }

                    result[i]      = reply.ParsedValue;
                    parsersUsed[i] = true;
                    --parsersToGo;

                    i = -1; // start from the beginning of _parsers
                    atLeastOneItemParsed           = true;
                    separatorWasTheLastTokenParsed = false;
                    failures = FailureMessages.Empty;

                    continue;
                }
                else if (newPosition != oldPosition)
                {
                    return(Failure <TValue[]> .From(reply));
                }

                failures = failures.Merge(reply.FailureMessages);

                var triedAllParsers = i == parsersLength - 1;

                if (newPosition != oldPosition || (triedAllParsers && (separatorWasTheLastTokenParsed || _mode == UnorderedParsingMode.FullSet)))
                {
                    return(new Failure <TValue[]>(reply.UnparsedTokens, failures));
                }
            }

            if ((parsersToGo > 0 && _mode == UnorderedParsingMode.FullSet) || (!atLeastOneItemParsed && _mode == UnorderedParsingMode.NonemptySubset))
            {
                return(new Failure <TValue[]>(tokensToParse, failures));
            }

            return(new Success <TValue[]>(result, tokensToParse));
        }
Exemplo n.º 3
0
        /// <inheritdoc/>
        public override IReply <IList <TValue> > Parse(TokenStream tokens)
        {
            var oldPosition = tokens.Position;
            var reply       = _item.Parse(tokens);
            var newPosition = reply.UnparsedTokens.Position;

            var times = 0;

            var list = new List <TValue>();

            var separatorParserIsPresent = _separator != null;
            var separatorWasParsed       = false;

            while (reply.Success)
            {
                if (oldPosition == newPosition)
                {
                    throw new Exception($"Item parser {_item.Expression} encountered a potential infinite loop at position {newPosition}.");
                }

                ++times;

                switch (_quantificationRule)
                {
                case QuantificationRule.ExactlyN:
                    if (times > _n)
                    {
                        return(new Failure <IList <TValue> >(
                                   reply.UnparsedTokens,
                                   FailureMessages.Empty.With(FailureMessage.Expected($"{_item.Expression} occurring no more than exactly {_n} times"))
                                   ));
                    }
                    break;

                case QuantificationRule.NtoM:
                    if (times > _m)
                    {
                        return(new Failure <IList <TValue> >(
                                   reply.UnparsedTokens,
                                   FailureMessages.Empty.With(FailureMessage.Expected($"{_item.Expression} occurring no more than between {_n} and {_m} times"))
                                   ));
                    }
                    break;

                case QuantificationRule.NOrLess:
                    if (times > _n)
                    {
                        return(new Failure <IList <TValue> >(
                                   reply.UnparsedTokens,
                                   FailureMessages.Empty.With(FailureMessage.Expected($"{_item.Expression} occurring no more than {_n} times"))
                                   ));
                    }
                    break;
                }

                list.Add(reply.ParsedValue);

                var unparsedTokens = reply.UnparsedTokens;

                if (separatorParserIsPresent)
                {
                    var positionBeforeSeparator = newPosition;

                    var separatorReply = _separator.ParseGenerally(reply.UnparsedTokens);

                    unparsedTokens = separatorReply.UnparsedTokens;

                    var positionAfterSeparator = unparsedTokens.Position;

                    if (separatorReply.Success)
                    {
                        if (positionBeforeSeparator == positionAfterSeparator)
                        {
                            throw new Exception($"Separator parser {_separator.Expression} encountered a potential infinite loop at position {positionBeforeSeparator}.");
                        }
                    }
                    else
                    {
                        if (positionBeforeSeparator != positionAfterSeparator)
                        {
                            return(Failure <TValue[]> .From(separatorReply));
                        }
                    }

                    newPosition = positionAfterSeparator;

                    separatorWasParsed = separatorReply.Success;
                }

                oldPosition = newPosition;

                if (separatorParserIsPresent && !separatorWasParsed)
                {
                    break;
                }

                reply = _item.Parse(unparsedTokens);

                if (!reply.Success && separatorParserIsPresent)
                {
                    return(new Failure <IList <TValue> >(reply.UnparsedTokens, reply.FailureMessages));
                }

                newPosition = reply.UnparsedTokens.Position;
            }

            //The item parser finally failed or the separator parser parsed the next separator, but there was no item following it
            if (oldPosition != newPosition || separatorParserIsPresent && separatorWasParsed)
            {
                return(new Failure <IList <TValue> >(reply.UnparsedTokens, reply.FailureMessages));
            }

            switch (_quantificationRule)
            {
            case QuantificationRule.NOrMore:
                if (times < _n)
                {
                    return(new Failure <IList <TValue> >(
                               reply.UnparsedTokens,
                               FailureMessages.Empty.With(FailureMessage.Expected($"{_item.Expression} occurring {_n}+ times"))));
                }
                break;

            case QuantificationRule.ExactlyN:
                if (times != _n)
                {
                    return(new Failure <IList <TValue> >(
                               reply.UnparsedTokens,
                               FailureMessages.Empty.With(FailureMessage.Expected($"{_item.Expression} occurring no {(times > _n ? "more" : "less")} than exactly {_n} times"))));
                }
                break;

            case QuantificationRule.NtoM:
                if (times < _n)
                {
                    return(new Failure <IList <TValue> >(
                               reply.UnparsedTokens,
                               FailureMessages.Empty.With(FailureMessage.Expected($"{_item.Expression} occurring no less than between {_n} and {_m} times"))));
                }
                break;

            case QuantificationRule.NOrLess:
                if (times > _n)
                {
                    return(new Failure <IList <TValue> >(
                               reply.UnparsedTokens,
                               FailureMessages.Empty.With(FailureMessage.Expected($"{_item.Expression} occurring no more than {_n} times"))));
                }
                break;
            }

            return(new Success <IList <TValue> >(list, reply.UnparsedTokens, reply.FailureMessages));
        }
Exemplo n.º 4
0
 public static IGeneralReply Parses(this IGeneralParser parser, IEnumerable <Token> tokens)
 {
     return(parser.ParseGenerally(new TokenStream(tokens)).Succeeds().AtEndOfInput());
 }
Exemplo n.º 5
0
        public static IGeneralReply PartiallyParses(this IGeneralParser parser, IEnumerable <Token> tokens)
        {
            var stream = new TokenStream(tokens);

            return(parser.ParseGenerally(stream).Succeeds());
        }