/// <inheritdoc/> public override IReply <TValue> Parse(TokenStream tokens) { var left = _left.ParseGenerally(tokens); if (!left.Success) { return(Failure <TValue> .From(left)); } var item = _item.Parse(left.UnparsedTokens); if (!item.Success) { return(item); } var right = _right.ParseGenerally(item.UnparsedTokens); if (!right.Success) { return(Failure <TValue> .From(right)); } return(new Success <TValue>(item.ParsedValue, right.UnparsedTokens, right.FailureMessages)); }
/// <inheritdoc/> public override IReply <KeyValuePair <TName, TValue> > Parse(TokenStream tokens) { var name = _name.Parse(tokens); if (!name.Success) { return(Failure <KeyValuePair <TName, TValue> > .From(name)); } var delimiter = _delimiter.ParseGenerally(name.UnparsedTokens); if (!delimiter.Success) { return(Failure <KeyValuePair <TName, TValue> > .From(delimiter)); } var value = _value.Parse(delimiter.UnparsedTokens); if (!value.Success) { return(Failure <KeyValuePair <TName, TValue> > .From(value)); } return(new Success <KeyValuePair <TName, TValue> >(new KeyValuePair <TName, TValue>(name.ParsedValue, value.ParsedValue), value.UnparsedTokens, value.FailureMessages)); }
/// <inheritdoc/> public override IReply <TValue> Parse(TokenStream tokens) { var skip = _skip.ParseGenerally(tokens); if (!skip.Success) { return(Failure <TValue> .From(skip)); } return(_take.Parse(skip.UnparsedTokens)); }
/// <inheritdoc/> public override IReply <TResult> Parse(TokenStream tokens) { var reply = _parser.Parse(tokens); if (!reply.Success) { return(Failure <TResult> .From(reply)); } var parsedValue = _resultContinuation(reply.ParsedValue); return(new Success <TResult>(parsedValue, reply.UnparsedTokens)); }
/// <inheritdoc/> public override IReply <TValue> Parse(TokenStream tokens) { var take = _take.Parse(tokens); if (!take.Success) { return(Failure <TValue> .From(take)); } var skip = _skip.ParseGenerally(take.UnparsedTokens); if (!skip.Success) { return(Failure <TValue> .From(skip)); } return(new Success <TValue>(take.ParsedValue, skip.UnparsedTokens, skip.FailureMessages)); }
/// <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)); }
/// <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)); }