internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out T result) { var childExpecteds = new ExpectedCollector <TToken>(); var success = _parser.TryParse(ref state, ref childExpecteds, out result); expecteds.AddIf(ref childExpecteds, success); childExpecteds.Dispose(); if (!success) { return(false); } if (!_predicate(result)) { state.Error = new InternalError <TToken>( Maybe.Nothing <TToken>(), false, state.Location, _message(result) ); expecteds.Add(_expected); result = default; return(false); } return(true); }
private bool Rest(Parser <TToken, T> parser, ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, List <T> ts) { var lastStartingLoc = state.Location; var childExpecteds = new ExpectedCollector <TToken>(); var success = parser.TryParse(ref state, ref childExpecteds, out var result); while (success) { var endingLoc = state.Location; childExpecteds.Clear(); if (endingLoc <= lastStartingLoc) { childExpecteds.Dispose(); throw new InvalidOperationException("Many() used with a parser which consumed no input"); } ts.Add(result); lastStartingLoc = endingLoc; success = parser.TryParse(ref state, ref childExpecteds, out result); } var lastParserConsumedInput = state.Location > lastStartingLoc; expecteds.AddIf(ref childExpecteds, lastParserConsumedInput); childExpecteds.Dispose(); // we fail if the most recent parser failed after consuming input. // it sets state.Error for us return(!lastParserConsumedInput); }
internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out U result) { var success1 = _parser.TryParse(ref state, ref expecteds, out var result1); if (!success1) { // state.Error set by _parser result = default; return(false); } var chainer = _factory(); chainer.Apply(result1); var lastStartLoc = state.Location; var childExpecteds = new ExpectedCollector <TToken>(); var success = _parser.TryParse(ref state, ref childExpecteds, out var childResult); while (success) { var endLoc = state.Location; childExpecteds.Clear(); if (endLoc <= lastStartLoc) { childExpecteds.Dispose(); chainer.OnError(); throw new InvalidOperationException("Many() used with a parser which consumed no input"); } chainer.Apply(childResult); lastStartLoc = endLoc; success = _parser.TryParse(ref state, ref childExpecteds, out childResult); } var lastParserConsumedInput = state.Location > lastStartLoc; expecteds.AddIf(ref childExpecteds, lastParserConsumedInput); childExpecteds.Dispose(); if (lastParserConsumedInput) // the most recent parser failed after consuming input { // state.Error set by _parser chainer.OnError(); result = default; return(false); } result = chainer.GetResult(); return(true); }
internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out IEnumerable <T> result) { var success = _parser.TryParse(ref state, ref expecteds, out var result1); if (!success) { // state.Error set by _parser result = null; return(false); } var ts = new List <T> { result1 }; var childExpecteds = new ExpectedCollector <TToken>(); while (true) { var sepStartLoc = state.Location; var sepSuccess = _separator.TryParse(ref state, ref childExpecteds, out var _); var sepConsumedInput = state.Location > sepStartLoc; expecteds.AddIf(ref childExpecteds, !sepSuccess && sepConsumedInput); childExpecteds.Clear(); if (!sepSuccess) { childExpecteds.Dispose(); if (sepConsumedInput) { // state.Error set by _separator result = null; return(false); } result = ts; return(true); } var itemStartLoc = state.Location; var itemSuccess = _parser.TryParse(ref state, ref childExpecteds, out var itemResult); var itemConsumedInput = state.Location > itemStartLoc; expecteds.AddIf(ref childExpecteds, !itemSuccess && itemConsumedInput); childExpecteds.Clear(); if (!itemSuccess) { childExpecteds.Dispose(); if (itemConsumedInput) { // state.Error set by _parser result = null; return(false); } result = ts; return(true); } ts.Add(itemResult); } }