Beispiel #1
0
        public void CreatesNewCollectionWhenAddingItems()
        {
            FailureMessages list = FailureMessages.Empty.With(FailureMessage.Expected("expectation"));

            list.ToString().ShouldBe("expectation expected");
            list.ShouldNotBeSameAs(FailureMessages.Empty);
        }
Beispiel #2
0
        public void CanIndicateSpecificExpectation()
        {
            var failure = (ExpectationFailureMessage)FailureMessage.Expected("statement");

            failure.Expectation.ShouldBe("statement");
            failure.ToString().ShouldBe("statement expected");
        }
Beispiel #3
0
        public void CanIncludeBacktrackErrors()
        {
            var deepBacktrack = FailureMessage.Backtrack(new Position(3, 4),
                                                         FailureMessages.Empty
                                                         .With(FailureMessage.Expected("A"))
                                                         .With(FailureMessage.Expected("B")));

            var shallowBacktrack = FailureMessage.Backtrack(new Position(2, 3),
                                                            FailureMessages.Empty
                                                            .With(FailureMessage.Expected("C"))
                                                            .With(FailureMessage.Expected("D"))
                                                            .With(deepBacktrack));

            var unrelatedBacktrack = FailureMessage.Backtrack(new Position(1, 2),
                                                              FailureMessages.Empty
                                                              .With(FailureMessage.Expected("E"))
                                                              .With(FailureMessage.Expected("F")));

            FailureMessages.Empty
            .With(deepBacktrack)
            .ToString().ShouldBe("[(3, 4): A or B expected]");

            FailureMessages.Empty
            .With(shallowBacktrack)
            .ToString().ShouldBe("[(2, 3): C or D expected [(3, 4): A or B expected]]");

            FailureMessages.Empty
            .With(FailureMessage.Expected("G"))
            .With(FailureMessage.Expected("H"))
            .With(shallowBacktrack)
            .With(unrelatedBacktrack)
            .ToString().ShouldBe("G or H expected [(1, 2): E or F expected] [(2, 3): C or D expected [(3, 4): A or B expected]]");
        }
Beispiel #4
0
        public void CanIndicateMultipleErrorsAtTheCurrentPosition()
        {
            var errors = FailureMessages.Empty
                         .With(FailureMessage.Expected("A"))
                         .With(FailureMessage.Expected("B"));

            new Failure <object>(endOfInput, errors).FailureMessages.ToString().ShouldBe("A or B expected");
        }
Beispiel #5
0
        public void CanIndicatePotentialErrors()
        {
            var potentialErrors = FailureMessages.Empty
                                  .With(FailureMessage.Expected("A"))
                                  .With(FailureMessage.Expected("B"));

            new Success <object>("x", _unparsed, potentialErrors).FailureMessages.ShouldBe(potentialErrors);
        }
Beispiel #6
0
 public void OmitsUnknownErrorsWhenAdditionalErrorsExist()
 {
     FailureMessages.Empty
     .With(FailureMessage.Expected("A"))
     .With(FailureMessage.Expected("B"))
     .With(FailureMessage.Unknown())
     .With(FailureMessage.Expected("C"))
     .ToString().ShouldBe("A, B or C expected");
 }
Beispiel #7
0
        /// <inheritdoc/>
        public override IReply <TValue> Parse(TokenStream tokens)
        {
            if (tokens.Current.Kind == _kind)
            {
                return(new Success <TValue>(_value, tokens.Advance()));
            }

            return(new Failure <TValue>(tokens, FailureMessage.Expected(_kind.Name)));
        }
Beispiel #8
0
        /// <inheritdoc/>
        public override IGeneralReply ParseGenerally(TokenStream tokens)
        {
            if (tokens.Current.Kind == _kind)
            {
                return(new GeneralSuccess(tokens.Advance()));
            }

            return(new GeneralFailure(tokens, FailureMessage.Expected(_kind.Name)));
        }
        /// <inheritdoc/>
        public override IReply <TValue> Parse(TokenStream tokens)
        {
            if (tokens.Current.Kind != _kind)
            {
                return(new Failure <TValue>(tokens, FailureMessage.Expected(_kind.Name)));
            }

            var parsedValue = _lexemeMapping(tokens.Current.Lexeme);

            return(new Success <TValue>(parsedValue, tokens.Advance()));
        }
        /// <inheritdoc/>
        public override IReply <string> Parse(TokenStream tokens)
        {
            var currentToken = tokens.Current;

            if (currentToken.Kind != _kind)
            {
                return(new Failure <string>(tokens, FailureMessage.Expected(_kind.Name)));
            }

            return(new Success <string>(currentToken.Lexeme, tokens.Advance()));
        }
Beispiel #11
0
 public void OmitsDuplicateExpectationsFromExpectationLists()
 {
     FailureMessages.Empty
     .With(FailureMessage.Expected("A"))
     .With(FailureMessage.Expected("A"))
     .With(FailureMessage.Expected("B"))
     .With(FailureMessage.Expected("C"))
     .With(FailureMessage.Unknown())
     .With(FailureMessage.Expected("C"))
     .With(FailureMessage.Expected("C"))
     .With(FailureMessage.Expected("A"))
     .ToString().ShouldBe("A, B or C expected");
 }
Beispiel #12
0
        public void CanIndicateErrorsWhichCausedBacktracking()
        {
            var             position = new Position(3, 4);
            FailureMessages failures = FailureMessages.Empty
                                       .With(FailureMessage.Expected("a"))
                                       .With(FailureMessage.Expected("b"));

            var failure = (BacktrackFailureMessage)FailureMessage.Backtrack(position, failures);

            failure.Position.ShouldBe(position);
            failure.Failures.ShouldBe(failures);
            failure.ToString().ShouldBe("(3, 4): a or b expected");
        }
Beispiel #13
0
        public void CanMergeTwoLists()
        {
            var first = FailureMessages.Empty
                        .With(FailureMessage.Expected("A"))
                        .With(FailureMessage.Expected("B"))
                        .With(FailureMessage.Unknown())
                        .With(FailureMessage.Expected("C"));

            var second = FailureMessages.Empty
                         .With(FailureMessage.Expected("D"))
                         .With(FailureMessage.Expected("B"))
                         .With(FailureMessage.Unknown())
                         .With(FailureMessage.Expected("E"));

            first.Merge(second)
            .ToString().ShouldBe("A, B, C, D or E expected");
        }
Beispiel #14
0
        public void CanIncludeMultipleExpectations()
        {
            FailureMessages.Empty
            .With(FailureMessage.Expected("A"))
            .With(FailureMessage.Expected("B"))
            .ToString().ShouldBe("A or B expected");

            FailureMessages.Empty
            .With(FailureMessage.Expected("A"))
            .With(FailureMessage.Expected("B"))
            .With(FailureMessage.Expected("C"))
            .ToString().ShouldBe("A, B or C expected");

            FailureMessages.Empty
            .With(FailureMessage.Expected("A"))
            .With(FailureMessage.Expected("B"))
            .With(FailureMessage.Expected("C"))
            .With(FailureMessage.Expected("D"))
            .ToString().ShouldBe("A, B, C or D expected");
        }
Beispiel #15
0
        /// <inheritdoc/>
        public override IGeneralReply ParseGenerally(TokenStream tokens)
        {
            if (tokens == null)
            {
                throw new ArgumentNullException(nameof(tokens));
            }

            var oldPosition = tokens.Position;
            var reply       = _item.ParseGenerally(tokens);
            var newPosition = reply.UnparsedTokens.Position;

            var times = 0;

            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 GeneralFailure(
                                   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 GeneralFailure(
                                   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 GeneralFailure(
                                   reply.UnparsedTokens,
                                   FailureMessages.Empty.With(FailureMessage.Expected($"{_item.Expression} occurring no more than {_n} times"))));
                    }
                    break;
                }

                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.ParseGenerally(unparsedTokens);

                if (!reply.Success && separatorParserIsPresent)
                {
                    return(new GeneralFailure(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 GeneralFailure(reply.UnparsedTokens, reply.FailureMessages));
            }

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

            case QuantificationRule.ExactlyN:
                if (times != _n)
                {
                    return(new GeneralFailure(
                               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 GeneralFailure(
                               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 GeneralFailure(
                               reply.UnparsedTokens,
                               FailureMessages.Empty.With(FailureMessage.Expected($"{_item.Expression} occurring no more than {_n} times"))
                               ));
                }
                break;
            }

            return(new GeneralSuccess(reply.UnparsedTokens));
        }
Beispiel #16
0
 public void CanIndicateErrorsAtTheCurrentPosition()
 {
     new Failure <object>(endOfInput, FailureMessage.Unknown()).FailureMessages.ToString().ShouldBe("Parsing failed.");
     new Failure <object>(endOfInput, FailureMessage.Expected("statement")).FailureMessages.ToString().ShouldBe("statement expected");
 }
Beispiel #17
0
 /// <summary>
 /// Creates a new instance of <see cref="LabeledParser{TValue}"/>.
 /// </summary>
 /// <param name="parser">The `p parser. Not null.</param>
 /// <param name="expectation">Expectation message. Not null.</param>
 public LabeledParser(IParser <TValue> parser, string expectation)
 {
     _parser   = parser ?? throw new ArgumentNullException(nameof(parser));
     _failures = FailureMessages.Empty.With(FailureMessage.Expected(expectation));
 }