Scala's source explains these operators:
~> is a parser combinator for sequential composition which keeps only the right result.
<~ is a parser combinator for sequential composition which keeps only the left result
I wrote the following two classes. Note that Daniel Spiewak's excellent article on this topic helped me very much to begin to understand Parser Combinators.
~>
class KeepRightParser[+A](left: =>Parser[A],
right: =>Parser[A]) extends Parser[A] {
def apply(s: Stream[Character]) = left(s) match {
case Success(_, rem) => right(rem)
case f: Failure => f
}
}
and <~
:
class KeepLeftParser[+A](left: =>Parser[A],
right: =>Parser[A]) extends Parser[A] {
def apply(s: Stream[Character]) = left(s) match {
case Success(a, rem) => right(rem) match {
case Success(_, _) => Success(a, rem)
case f: Failure => f
}
case f: Failure => f
}
}
Here's the test:
val s4 = Stream[Character]('f', 'o', 'o', 'b', 'a', 'r', 'b', 'u', 'z', 'z')
val krp = new KeepRightParser("foo", "bar")
println("~> test: " + krp(s4))
val klp = new KeepLeftParser("foo", "bar")
println("<~ test: " + klp(s4))
with output:
~> test: Success(bar,Stream(b, ?))
<~ test: Success(foo,Stream(b, a, r, b, ?))
As I understand, the second stream shows more than its head since bar
needed to be read for parsing the second half of the sequence.
Is this correct?
Yes you are correct. Stream
's toString
isn't immutable as you can verify in the REPL:
scala> val s = Stream(1,2,3,4,5,6,7,8)
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> s(3)
res5: Int = 4
scala> s
res6: scala.collection.immutable.Stream[Int] = Stream(1, 2, 3, 4, ?)