public void CreatesNewCollectionWhenAddingItems() { FailureMessages list = FailureMessages.Empty.With(FailureMessage.Expected("expectation")); list.ToString().ShouldBe("expectation expected"); list.ShouldNotBeSameAs(FailureMessages.Empty); }
public void CanIndicateSpecificExpectation() { var failure = (ExpectationFailureMessage)FailureMessage.Expected("statement"); failure.Expectation.ShouldBe("statement"); failure.ToString().ShouldBe("statement expected"); }
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]]"); }
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"); }
public void CanIndicatePotentialErrors() { var potentialErrors = FailureMessages.Empty .With(FailureMessage.Expected("A")) .With(FailureMessage.Expected("B")); new Success <object>("x", _unparsed, potentialErrors).FailureMessages.ShouldBe(potentialErrors); }
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"); }
/// <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))); }
/// <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())); }
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"); }
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"); }
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"); }
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"); }
/// <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)); }
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"); }
/// <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)); }