Question

Is there a cleaner way to map a string to an Enumeration value in a parser combinator?

object Mode extends Enumeration {
  type Mode = Value
  val View, Add, Modify, Delete  = Value
}

import Mode._

object ModeParser extends JavaTokenParsers {
  def mode: Parser[Mode] = ("^(" + Mode.values.mkString("|") + ")$").r ^^ { 
    Mode.withName(_) 
  }
}
Was it helpful?

Solution

Parsers are composable, so as soon as you can build a parser reading one Mode.Value, you may compose all such variants with | :

object ModeParser extends JavaTokenParsers {
  val mode: Parser[Mode.Value] = Mode.values.toList map{m =>
    literal(m.toString) ^^^ m
  } reduceLeft {_ | _}
}

You would use it like so:

scala> ModeParser.parseAll(ModeParser.mode, "Viewx")

OTHER TIPS

You could use ^? method to convert ident parser to mode parser:

object ModeParser extends JavaTokenParsers {
  val modes = Mode.values.map{v => v.toString -> v}.toMap
  def mode: Parser[Mode.Value] = ident ^? ( 
    { case s if modes.contains(s) => modes(s) },
    s => s"Mode expected, but '$s' found."
  )
}

Usage:

scala> ModeParser.parseAll(ModeParser.mode, "Modify")
res0: ModeParser.ParseResult[Mode.Value] = [1.7] parsed: Modify

scala> ModeParser.parseAll(ModeParser.mode, "modify")
res1: ModeParser.ParseResult[Mode.Value] =
[1.7] failure: Mode expected, but 'modify' found.

modify
      ^
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top