internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out TToken result) { if (!state.HasCurrent) { state.Error = new InternalError <TToken>( Maybe.Nothing <TToken>(), true, state.Location, null ); expecteds.Add(Expected); result = default; return(false); } var token = state.Current; if (!EqualityComparer <TToken> .Default.Equals(token, _token)) { state.Error = new InternalError <TToken>( Maybe.Just(token), false, state.Location, null ); expecteds.Add(Expected); result = default; return(false); } state.Advance(); result = token; return(true); }
// see comment about expecteds in ParseState.Error.cs internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out T result) { var firstTime = true; var err = new InternalError <TToken>( Maybe.Nothing <TToken>(), false, state.Location, "OneOf had no arguments" ); var childExpecteds = new ExpectedCollector <TToken>(); // the expecteds for all loop iterations var grandchildExpecteds = new ExpectedCollector <TToken>(); // the expecteds for the current loop iteration foreach (var p in _parsers) { var thisStartLoc = state.Location; var success = p.TryParse(ref state, ref grandchildExpecteds, out result); if (success) { // throw out all expecteds grandchildExpecteds.Dispose(); childExpecteds.Dispose(); return(true); } // 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 (state.Location > thisStartLoc) { // throw out all expecteds except this one expecteds.Add(ref grandchildExpecteds); childExpecteds.Dispose(); grandchildExpecteds.Dispose(); result = default; return(false); } childExpecteds.Add(ref grandchildExpecteds); grandchildExpecteds.Clear(); // 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; expecteds.Add(ref childExpecteds); childExpecteds.Dispose(); grandchildExpecteds.Dispose(); result = default; return(false); }
internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out TEnumerable result) { var span = state.LookAhead(_valueTokens.Length); // span.Length <= _valueTokens.Length var errorPos = -1; for (var i = 0; i < span.Length; i++) { if (!EqualityComparer <TToken> .Default.Equals(span[i], _valueTokens[i])) { errorPos = i; break; } } if (errorPos != -1) { // strings didn't match state.Advance(errorPos); state.Error = new InternalError <TToken>( Maybe.Just(span[errorPos]), false, state.Location, null ); expecteds.Add(new Expected <TToken>(_valueTokens)); result = default; return(false); } if (span.Length < _valueTokens.Length) { // strings matched but reached EOF state.Advance(span.Length); state.Error = new InternalError <TToken>( Maybe.Nothing <TToken>(), true, state.Location, null ); expecteds.Add(new Expected <TToken>(_valueTokens)); result = default; return(false); } // OK state.Advance(_valueTokens.Length); result = _value; return(true); }
internal sealed override bool TryParse(ref ParseState <char> state, ref ExpectedCollector <char> expecteds, out string result) { var span = state.LookAhead(_value.Length); // span.Length <= _valueTokens.Length var errorPos = -1; for (var i = 0; i < span.Length; i++) { if (!char.ToLowerInvariant(span[i]).Equals(char.ToLowerInvariant(_value[i]))) { errorPos = i; break; } } if (errorPos != -1) { // strings didn't match state.Advance(errorPos); state.Error = new InternalError <char>( Maybe.Just(span[errorPos]), false, state.Location, null ); expecteds.Add(Expected); result = null; return(false); } if (span.Length < _value.Length) { // strings matched but reached EOF state.Advance(span.Length); state.Error = new InternalError <char>( Maybe.Nothing <char>(), true, state.Location, null ); expecteds.Add(Expected); result = null; return(false); } // OK state.Advance(_value.Length); result = span.ToString(); return(true); }
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); }
internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out T result) { state.Error = new InternalError <TToken>( Maybe.Nothing <TToken>(), false, state.Location, _message ); expecteds.Add(_expected); result = default; return(false); }
internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out T result) { var childExpecteds = new ExpectedCollector <TToken>(true); var success = _parser.TryParse(ref state, ref childExpecteds, out result); childExpecteds.Dispose(); if (!success) { expecteds.Add(_expected); } return(success); }
// see comment about expecteds in ParseState.Error.cs internal sealed override bool TryParse(ref ParseState <TToken> state, ref ExpectedCollector <TToken> expecteds, out IEnumerable <T>?result) { var ts = _keepResults ? new List <T>() : null; var firstItemStartLoc = state.Location; var firstItemSuccess = _parser.TryParse(ref state, ref expecteds, out var result1); if (!firstItemSuccess) { // state.Error set by _parser result = null; return(false); } if (state.Location <= firstItemStartLoc) { throw new InvalidOperationException("Until() used with a parser which consumed no input"); } ts?.Add(result1); var terminatorExpecteds = new ExpectedCollector <TToken>(); var itemExpecteds = new ExpectedCollector <TToken>(); while (true) { var terminatorStartLoc = state.Location; var terminatorSuccess = _terminator.TryParse(ref state, ref terminatorExpecteds, out var terminatorResult); if (terminatorSuccess) { terminatorExpecteds.Dispose(); itemExpecteds.Dispose(); result = ts; return(true); } if (state.Location > terminatorStartLoc) { // state.Error set by _terminator expecteds.Add(ref terminatorExpecteds); terminatorExpecteds.Dispose(); itemExpecteds.Dispose(); result = null; return(false); } var itemStartLoc = state.Location; var itemSuccess = _parser.TryParse(ref state, ref itemExpecteds, out var itemResult); var itemConsumedInput = state.Location > itemStartLoc; if (!itemSuccess) { if (!itemConsumedInput) { // get the expected from both _terminator and _parser expecteds.Add(ref terminatorExpecteds); expecteds.Add(ref itemExpecteds); } else { // throw out the _terminator expecteds and keep only _parser expecteds.Add(ref itemExpecteds); } terminatorExpecteds.Dispose(); itemExpecteds.Dispose(); result = null; return(false); } // throw out both sets of expecteds terminatorExpecteds.Clear(); itemExpecteds.Clear(); if (!itemConsumedInput) { throw new InvalidOperationException("Until() used with a parser which consumed no input"); } ts?.Add(itemResult); } }