Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parser of only optionals #346

Open
JacobHearst opened this issue Apr 11, 2024 · 0 comments
Open

Parser of only optionals #346

JacobHearst opened this issue Apr 11, 2024 · 0 comments

Comments

@JacobHearst
Copy link

JacobHearst commented Apr 11, 2024

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
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant