// see comment about expecteds in ParseState.Error.cs internal sealed override InternalResult <T> Parse(ref ParseState <TToken> state) { var firstTime = true; var err = new InternalError <TToken>( Maybe.Nothing <TToken>(), false, state.Location, "OneOf had no arguments" ); state.BeginExpectedTran(); foreach (var p in _parsers) { state.BeginExpectedTran(); var thisResult = p.Parse(ref state); if (thisResult.Success) { // throw out all expecteds state.EndExpectedTran(false); state.EndExpectedTran(false); return(thisResult); } // we'll usually return the error from the first parser that didn't backtrack, // even if other parsers had a longer match. // There is some room for improvement here. if (thisResult.ConsumedInput) { // throw out all expecteds except this one var expected = state.ExpectedTranState(); state.EndExpectedTran(false); state.EndExpectedTran(false); state.AddExpected(expected.AsSpan()); expected.Dispose(clearArray: true); return(thisResult); } state.EndExpectedTran(true); // choose the longest match, preferring the left-most error in a tie, // except the first time (avoid returning "OneOf had no arguments"). if (firstTime || state.Error.ErrorLocation > err.ErrorLocation) { err = state.Error; } firstTime = false; } state.Error = err; state.EndExpectedTran(true); return(InternalResult.Failure <T>(false)); }
// see comment about expecteds in ParseState.Error.cs internal override InternalResult <T> Parse(ref ParseState <TToken> state) { state.BeginExpectedTran(); var result = _parser.Parse(ref state); if (result.Success) { state.EndExpectedTran(false); return(result); } var parserExpecteds = state.ExpectedTranState(); state.EndExpectedTran(false); var recoverParser = _errorHandler(state.BuildError(parserExpecteds.AsEnumerable())); parserExpecteds.Dispose(clearArray: true); return(recoverParser.Parse(ref state)); }
// see comment about expecteds in ParseState.Error.cs internal override InternalResult <IEnumerable <T> > Parse(ref ParseState <TToken> state) { var ts = _keepResults ? new List <T>() : null; var firstItemResult = _parser.Parse(ref state); if (!firstItemResult.Success) { // state.Error set by _parser return(InternalResult.Failure <IEnumerable <T> >(firstItemResult.ConsumedInput)); } if (!firstItemResult.ConsumedInput) { throw new InvalidOperationException("Until() used with a parser which consumed no input"); } ts?.Add(firstItemResult.Value); while (true) { state.BeginExpectedTran(); var terminatorResult = _terminator.Parse(ref state); if (terminatorResult.Success) { state.EndExpectedTran(false); return(InternalResult.Success <IEnumerable <T> >(ts, true)); } if (terminatorResult.ConsumedInput) { // state.Error set by _terminator state.EndExpectedTran(true); return(InternalResult.Failure <IEnumerable <T> >(true)); } state.BeginExpectedTran(); var itemResult = _parser.Parse(ref state); if (!itemResult.Success) { if (!itemResult.ConsumedInput) { // get the expected from both _terminator and _parser state.EndExpectedTran(true); state.EndExpectedTran(true); } else { // throw out the _terminator expecteds and keep only _parser var itemExpected = state.ExpectedTranState(); state.EndExpectedTran(false); state.EndExpectedTran(false); state.AddExpected(itemExpected.AsSpan()); itemExpected.Dispose(); } return(InternalResult.Failure <IEnumerable <T> >(true)); } // throw out both sets of expecteds state.EndExpectedTran(false); state.EndExpectedTran(false); if (!itemResult.ConsumedInput) { throw new InvalidOperationException("Until() used with a parser which consumed no input"); } ts?.Add(itemResult.Value); } }