Search code examples
scalaparser-combinators

Scala parser combinator reduce/foldLeft


I'm trying to make the following, from a dynamically filled List:

val primitives = "x" | "y" | "z" // what I want

val primitives2 = List("x", "y", "z") // what I need to transform from

I figured something like this might work:

primitives2.reduce(_|_)

But no go. I then found this snippet, which works:

primitives2.foldRight(failure("no matching delimiter"): Parser[Any])(_|_)

However, the base case failure("no matching delimiter") is confusing. Is that just the equivalent Nil case for Parser objects?


Solution

  • I'm going to assume that you're working with RegexParsers or one of its descendants. If so, then the issue is just that the implicit conversion from String to Parser[String] won't kick in automatically with reduce(_ | _). If you explicitly convert every item in your list first, like this:

    val anyPrimitive = primitives2.map(literal).reduce(_ | _)
    

    You'll be perfectly fine—except that this will leave you with slightly confusing error messages, like this:

    scala> parser.parseAll(parser.anyPrimitive, "a")
    res8: parser.ParseResult[Any] = 
    [1.1] failure: `z' expected but `a' found
    
    a
    ^
    

    If you want a clearer error message, then you'll need to provide your own starting value using the fold approach.