Commit fa7d5469 authored by Haochen Xie's avatar Haochen Xie

add ch9/ParserCombinators.scala

parent 75a42c3e
package name.haochenxie.fpscala.ch9
import scala.util.matching.Regex
trait Parsers[ParserError, Parser[+_]] { self =>
def run[A](p: Parser[A])(s: String): Either[ParserError, A]
// --- --- ---
implicit def string(s: String): Parser[String]
implicit def regex(r: Regex): Parser[String]
// --- --- ---
def or[A](s1: Parser[A], s2: Parser[A]): Parser[A]
// def many[A](p: Parser[A]): Parser[List[A]]
// def map[A,B](a: Parser[A])(f: A => B): Parser[B]
def slice[A](p: Parser[A]): Parser[String]
// def product[A,B](p1: Parser[A], p2: Parser[B]): Parser[(A,B)]
def flatMap[A,B](p: Parser[A])(f: A => Parser[B]): Parser[B]
// --- --- ---
def char(c: Char): Parser[Char] = string(c.toString).map(_.charAt(0))
def succeed[A](a: A): Parser[A] = string("").map(_ => a)
// Exercise 9.1
// wow: this is inconvenient..
// def map2[A,B,C](p1: Parser[A], p2: Parser[B])(f: (A,B) => C): Parser[C] = map(product(p1, p2))({ case (a, b) => f(a, b) })
def many1[A](p: Parser[A]): Parser[List[A]] = map2(p, many(p))((a, as) => a::as)
// Exercise 9.3
def many[A](p: Parser[A]): Parser[List[A]] = or(map2(p, many(p))(_ :: _), succeed(Nil))
// Exercise 9.4
def listOfN[A](n: Int, p: Parser[A]): Parser[List[A]] =
if (n > 0) map(product(p, listOfN(n-1, p)))({ case (a, as) => a :: as })
else succeed(Nil)
// Exercise 9.7
def product[A,B](p1: Parser[A], p2: => Parser[B]): Parser[(A,B)] = flatMap(p1)(a => map(p2)((a, _)))
def map2[A,B,C](p1: Parser[A], p2: => Parser[B])(f: (A,B) => C): Parser[C] = flatMap(p1)(a => map(p2)(f(a, _)))
// Exercise 9.8
// why I cannot write def map[A,B](p: Parser[A])(f: A => B): Parser[B] = flatMap(p)(succeed(f(_))) instead?
def map[A,B](p: Parser[A])(f: A => B): Parser[B] = flatMap(p)(a => succeed(f(a)))
object Laws {
// def equal[A](p1: Parser[A], p2: Parser[A])(in: Gen[String]): Prop =
// forAll(in)(s => run(p1)(s) == run(p2)(s))
//
// def mapLaw[A](p: Parser[A](in: Gen[String])): Prop =
// equal(p, p.map(identity))(in)
//
// // Exercise 9.2
// def productLaw[A,B](p1: Parser[A], p2: Parser[B])(in1: Gen[String], in2: Gen[String]): Prop =
// forAll(in1, in2)((s1, s2) => implies(run(slice(p1))(s1 + s2) == s1)(
// run(product(p1, p2))(s1 + s2) == (run(p1)(s1), run(p2)(s2))))
}
implicit def operators[A](a: A)(implicit f: A => Parser[String]): ParserOps[String] = ParserOps(f(a))
case class ParserOps[A](p: Parser[A]) {
def |[B>:A](p2: Parser[B]): Parser[B] = self.or(p, p2)
def or[B>:A](p2: => Parser[B]): Parser[B] = self.or(p, p2)
def **[B>:A](p2: => Parser[B]): Parser[(A,B)] = self.product(p, p2)
def many = self.many(p)
def map[B](f: A => B): Parser[B] = self.map(p)(f)
def flatMap[B](f: A => Parser[B]): Parser[B] = self.flatMap(p)(f)
def slice = self.slice(p)
}
}
class ParserCombinatorsScratch(P: Parsers) {
import P._
val digitP = regex("[0-9]".r)
val intP = P.map(digitP.many)(l => l.reduce(_+_)).map(_.toInt)
// Exercise 9.6
val ex9_6 = P.flatMap(intP)(n => P.listOfN(n, char('a')))
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment