Closed simme closed 4 years ago
Great question! It would probably be most correct to restore str
from the original if the first guard failed:
func zip<A, B>(_ a: Parser<A>, _ b: Parser<B>) -> Parser<(A, B)> {
return Parser<(A, B)> { str -> (A, B)? in
let original = str
guard let matchA = a.run(&str) else {
str = original
return nil
}
guard let matchB = b.run(&str) else {
str = original
return nil
}
return (matchA, matchB)
}
}
However, in practice, if a parser fails it (ideally) shouldn't consume any of the input. So if the first parser fails, and nothing in consumed, we don't really need to do any of the str = original
dance. We only need to do it in the second guard
because then the first parser would have consumed some of the input.
It's a little tricky, and we haven't explicitly made the requirement that parsers should never consume input if they fail. If this were turned into an open source library, such requirements should be made in a very obvious way.
But for now it's probably safest to just do the str = original
dance in the first guard.
Thanks!
Right, that makes sense. In a nutshell: there's an unspoken rule that parsers should not consume any of the input if it fails. But since that's hard to enforce it's better to be safe than sorry.
Thanks for a great resource!
Hello,
Quick question: why does a failure of
Parser<A>
not result in a restoration of the input string? https://github.com/pointfreeco/episode-code-samples/blob/master/0061-composable-parsing-zip/Composable%20Parsers.playground/Contents.swift#L202Best, Simon