Parser of only optionals
Closed this issue · 1 comments
I'm wondering if it's possible to build a parser of only optional values using the Optionally
parser. I've tried the following:
let parser = Parse {
Optionally { Int.parser() }
Optionally { Bool.parser() }
}
but the compiler complains about an ambiguous use of 'buildExpression'
on the first Optionally
statement. If I add a string literal parser inside of the first Optionally
block or inside of the top-level Parse
block the error goes away.
let parser = Parse {
Optionally { ""; Int.parser() }
Optionally { Bool.parser() }
}
// or
let parser = Parse {
""
Optionally { Int.parser() }
Optionally { Bool.parser() }
}
I get a bit lost when there are lots of generics and lots of type inference is happening but it seems to me like Swift is just having a hard time inferring the type of Input
so it doesn't know which overload of buildExpression
to use.
The parsers that I'm building are usually pulling values out of the middle of a string, and the string may not contain the value at all, which could also be part of the problem since what's talked about in the early videos of the Parsing collection of episodes is just parsing the start of a Substring
so I'm wondering how much that influenced the final API design for this library.
As an example of the parsers I'm building, here's one I wrote to parse video resolution from a string:
private static let threeSixtyParser = ContainsTitleWord(string: "360p")
.flatMap { if $0 { Always(Resolution.threeSixty) } else { Fail<Substring, Resolution>() } }
private static let fourEightyParser = ContainsTitleWord(pattern: #/480p|640x480|848x480/#)
.flatMap { if $0 { Always(Resolution.fourEighty) } else { Fail<Substring, Resolution>() } }
private static let fiveFourtyParser = ContainsTitleWord(string: "540p")
.flatMap { if $0 { Always(Resolution.fiveFourty) } else { Fail<Substring, Resolution>() } }
private static let fiveSeventySixParser = ContainsTitleWord(string: "576p")
.flatMap { if $0 { Always(Resolution.threeSixty) } else { Fail<Substring, Resolution>() } }
private static let sevenTwentyParser = ContainsTitleWord(pattern: #/720p|1280x720|960p/#)
.flatMap { if $0 { Always(Resolution.threeSixty) } else { Fail<Substring, Resolution>() } }
private static let tenEightyParser = ContainsTitleWord(pattern: #/1080p|1920x1080|1440p|FHD|1080i|4kto1080p/#)
.flatMap { if $0 { Always(Resolution.threeSixty) } else { Fail<Substring, Resolution>() } }
private static let twentyOneSixtyParser = ContainsTitleWord(pattern: #/(?:2160p|3840x2160|4k[-_. ](?:UHD|HEVC|BD|H265)|(?:UHD|HEVC|BD|H265)[-_. ]4k)|(?:UHD|\[4K\])/#)
.flatMap { if $0 { Always(Resolution.threeSixty) } else { Fail<Substring, Resolution>() } }
static let parser = OneOf {
fourEightyParser
fiveFourtyParser
fiveSeventySixParser
sevenTwentyParser
tenEightyParser
twentyOneSixtyParser
}
Closing as stale and I was able to implement a Failable
parser that met my needs