After looking at @ishaaq's answer I came up with a solution that I believe is a little more elegant.
implicit class ParserExtension[T](val p: Parser[T]) extends AnyVal {
def ?~[U](q: => Parser[U]): Parser[Option[T] ~ U] = {
((p ^^ Some.apply) ~ q) | (success(None) ~ q)
}
}
This implicit class adds a method to all my parsers so I can have an optional parser with back tracking. You can use it like so:
val a:Parser[String] = "a"
val parser:Parser[Option[String] ~ String] = a ?~ ( p2 | p1 )