Add repitition as list in case class (scala parser)

97 views Asked by At

I have following parser:

import scala.util.parsing.combinator.RegexParsers

class SimpleParser extends RegexParsers {

  override val skipWhitespace = false

  private val eol = sys.props("line.separator")

  def word: Parser[String] = "[a-z]+".r ^^ { _.toString }

  def freq: Parser[List[String]] = repsep(word, eol) ^^ {
    case word => word
  }

}

object TestSimpleParser extends SimpleParser {
  def main(args: Array[String]) = {
    parse(freq,
      """mike
        |john
        |sara
      """.stripMargin) match {
      case Success(matched,_) => println(matched)
      case Failure(msg,_) => println(msg)
      case Error(msg,_) => println(msg)
    }
  }
}

The result of this execution will be List(mike, john, sara) but it isn't what i want.

I'd like to have the following case class:

case class SomeEntity(list: List[String])

And the result will be the following:

SomeEntity(List(mike), List(john), List(sara)).

I want to add as much Lists as there are words with new lines. Please, don't put a big attention on the fact that there is just one word in a list. It is just a simplified version of my issue. So, what should i change in the parser or in case class?

1

There are 1 answers

4
Alexis C. On BEST ANSWER

The case class definition does not match your expected output. You're looking for this:

case class SomeEntity(list: List[String]*) {
    override def toString = this.getClass.getSimpleName+"("+list.mkString(", ")+")"
}

Now if, you want to get back a SomeEntity instance, the type of the Parser will be Parser[SomeEntity].

As repsep will give you back a List[String], you need to map each element in the list into a singleton list (so that you get a List[List[String]]) and then you forces it to see it as a varargs type with :_*

 def freq: Parser[SomeEntity] = 
     repsep(word, eol) ^^ (list => new SomeEntity(list.map(List(_)) : _*))

Given your input, it outputs:

SomeEntity(List(mike), List(john), List(sara))

Your case class could also take a List[List[String]] as parameter. Although a List[String] would be the most correct type in my opinion, but you certainly have reasons to require this.

Note that your mapping with the word parser is redundant, you could remove it.