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); }
/// <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 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)); }
public static IGeneralReply Parses(this IGeneralParser parser, IEnumerable <Token> tokens) { return(parser.ParseGenerally(new TokenStream(tokens)).Succeeds().AtEndOfInput()); }
public static IGeneralReply PartiallyParses(this IGeneralParser parser, IEnumerable <Token> tokens) { var stream = new TokenStream(tokens); return(parser.ParseGenerally(stream).Succeeds()); }