1 package jp.ymir.taskReporter.core
2 import scala.collection._
3 import scala.collection.immutable.StringLike
4 import scala.language.higherKinds
5 import scala.language.implicitConversions
6 import scala.language.reflectiveCalls
10 abstract class TSVTypes {
12 implicit val ParserFunctor = new Functor[Parser] {
13 def map[A, B](m: Parser[A])(f: A => B) = new Parser[B] {
14 def runParser[F[_], R](kf: Failure[F, R], ks: Success[B, F, R]): F[R] = {
15 def ks_(a: A) = ks(f(a))
16 return m.runParser(kf, ks_)
21 implicit val ParserApplicative = new Applicative[Parser] {
22 def point[A](a: => A) = new Parser[A] {
23 def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R]
26 def ap[A, B](m: => Parser[A])(fm: => Parser[A => B]) = new Parser[B] {
27 def runParser[F[_], R](kf: Failure[F, R], ks: Success[B, F, R]): F[R] = {
28 def ks_(f: A => B): F[R] = {
29 def ks__(a: A) = ks(f(a))
30 return m.runParser(kf, ks__)
32 return fm.runParser(kf, ks_)
37 implicit val ParserMonad = new Monad[Parser] {
38 def point[A](a: => A) = a.point[Parser]
40 def bind[A, B](m: Parser[A])(f: A => Parser[B]) = new Parser[B] {
41 def runParser[F[_], R](kf: Failure[F, R], ks: Success[B, F, R]): F[R] = {
42 def ks_(a: A) = f(a).runParser(kf, ks)
43 return m.runParser(kf, ks_)
48 implicit val ParserMonadError = new MonadError[({type λ[String, α] = Parser[α]})#λ, String] {
49 def point[A](a: => A) = a.point[Parser]
50 def bind[A, B](m: Parser[A])(f: A => Parser[B]) = m.flatMap(f)
52 def handleError[A](m: Parser[A])(f: String => Parser[A]) = new Parser[A] {
53 def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R] = {
54 def kf_(e: String) = f(e).runParser(kf, ks)
55 return m.runParser(kf_, ks)
59 def raiseError[A](e: String) = new Parser[A] {
60 def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R]
65 implicit def ToMonadErrorOps[A](m: Parser[A]) = new {
66 def handleError(f: String => Parser[A]): Parser[A]
67 = implicitly[MonadError[({type λ[String, α] = Parser[α]})#λ, String]].handleError(m)(f)
70 implicit def ToMonadErrorIdOps(e: String) = new {
71 def raiseError[A]: Parser[A]
72 = implicitly[MonadError[({type λ[String, α] = Parser[α]})#λ, String]].raiseError(e)
75 type Header = Seq[Symbol]
77 case class Field(value: String) {
78 def parseField[A: FromField]
79 = implicitly[FromField[A]].parseField(Field(value))
82 case class Record(value: Map[Symbol, Field]) {
83 def parseRecord[A: FromRecord]
84 = implicitly[FromRecord[A]].parseRecord(Record(value))
86 def lookup[A: FromField](name: Symbol): Parser[A]
87 = value.get(name).fold(("no field named " + name.name).raiseError[A])(_.parseField[A])
89 def lookup[A: FromField](name: Symbol, default: String): Parser[A]
90 = value.get(name).getOrElse(Field(default)).parseField[A]
93 type Failure[ F[_], R] = String => F[R]
94 type Success[A, F[_], R] = A => F[R]
97 def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R]
100 def runParser[A](p: Parser[A]): Either[String, A] = {
101 type F[R] = Either[String, R]
102 def left (e: String): F[A] = Left(e)
103 def right(x: A ): F[A] = Right(x)
104 return p.runParser(left, right)
107 trait FromRecord[A] {
108 def parseRecord(r: Record): Parser[A]
112 def parseField(f: Field): Parser[A]
116 def toRecord(a: A): Record
120 def toField(a: A): Field
123 class DecodeFailedException private(e: RuntimeException) extends RuntimeException(e) {
124 def this(msg: String) = this(new RuntimeException(msg))
125 def this(msg: String, cause: Throwable) = this(new RuntimeException(msg, cause))
129 implicit def OptionFromField[A: FromField] = new FromField[Option[A]] {
130 def parseField(f: Field): Parser[Option[A]] = {
131 if (f.value.isEmpty) {
132 return None.point[Parser]
135 f.parseField[A].map { Some(_) }
141 implicit val StringFromField = new FromField[String] {
142 def parseField(f: Field): Parser[String] = f.value.point[Parser]
146 implicit val IntFromField = new FromField[Int] {
147 def parseField(f: Field): Parser[Int] = {
149 f.value.toInt.point[Parser]
152 case e: NumberFormatException =>
153 e.getMessage().raiseError[Int]
159 trait TSVFunctions extends TSVTypes {
160 def decode[A: FromRecord](tsv: StringLike[_]): Seq[A] = {
161 val lines = tsv.split('\n').filter(!_.isEmpty)
162 val header = lines.head.split('\t').map(Symbol(_))
163 val records = lines.tail.map(line => Record((header zip line.split('\t').map { Field(_) }).toMap))
164 return records.map { r =>
165 runParser(r.parseRecord[A]) match {
167 case Left(e) => throw new DecodeFailedException(e)
173 object TSV extends TSVTypes with TSVFunctions