Not ordered parsers in Scala parser combinators

Viewed 147

I need to parse the words in not ordered way. For now i can see that following

def first: Parser[String] = ???    
def second: Parser[String] = ???
def unordered = (first ~ second) | (second ~ first)

But i'm wondering if there's any native solution for that?

2 Answers

I achieved this by combining ~ and | parsers into custom parser named $

It looks similar to ~

trait ExtParsers extends JavaTokenParsers {
  def unordered[T,U](tp: Parser[T], tu: Parser[U]): Parser[$[T, U]] =
    tp ~ tu ^^ { case (x ~ y) => $(x, y) } | tu ~ tp ^^
      { case (x ~ y) => $(y, x) }

  case class $[+a, +b](_1: a, _2: b)

  implicit class ExtParser[+T](val parser: Parser[T]) {
    def $[U](tu: Parser[U]): Parser[$[T, U]] = unordered(parser, tu)
  }
}

object MyParser extends ExtParsers {
  def unord: Parser[String] =
    (ident $ stringLiteral $ wholeNumber $ floatingPointNumber) ^^ {
      case (id $ sl $ wn $ fpn) =>
      s"ident=$id string=$sl int=$wn float=$fpn"
    }
}

And passed test:

  @Test def test() {
    val expected = "ident=value string=\"test\" int=10 float=10.99"

    assertEquals(expected,
      MyParser.parseAll(MyParser.unord, "value \"test\" 10 10.99").get)

    assertEquals(expected,
      MyParser.parseAll(MyParser.unord,"\"test\" value  10 10.99").get)

    assertEquals(expected,
      MyParser.parseAll(MyParser.unord,"10 value \"test\" 10.99").get)
  }
Related