package jp.ymir.taskReporter.core import scala.collection._ import scala.collection.immutable.StringLike import scala.language.higherKinds import scala.language.implicitConversions import scala.language.reflectiveCalls import scalaz._ import Scalaz._ abstract class TSVTypes { implicit val ParserFunctor = new Functor[Parser] { def map[A, B](m: Parser[A])(f: A => B) = new Parser[B] { def runParser[F[_], R](kf: Failure[F, R], ks: Success[B, F, R]): F[R] = { def ks_(a: A) = ks(f(a)) return m.runParser(kf, ks_) } } } implicit val ParserApplicative = new Applicative[Parser] { def point[A](a: => A) = new Parser[A] { def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R] = ks(a) } def ap[A, B](m: => Parser[A])(fm: => Parser[A => B]) = new Parser[B] { def runParser[F[_], R](kf: Failure[F, R], ks: Success[B, F, R]): F[R] = { def ks_(f: A => B): F[R] = { def ks__(a: A) = ks(f(a)) return m.runParser(kf, ks__) } return fm.runParser(kf, ks_) } } } implicit val ParserMonad = new Monad[Parser] { def point[A](a: => A) = a.point[Parser] def bind[A, B](m: Parser[A])(f: A => Parser[B]) = new Parser[B] { def runParser[F[_], R](kf: Failure[F, R], ks: Success[B, F, R]): F[R] = { def ks_(a: A) = f(a).runParser(kf, ks) return m.runParser(kf, ks_) } } } implicit val ParserMonadError = new MonadError[({type λ[String, α] = Parser[α]})#λ, String] { def point[A](a: => A) = a.point[Parser] def bind[A, B](m: Parser[A])(f: A => Parser[B]) = m.flatMap(f) def handleError[A](m: Parser[A])(f: String => Parser[A]) = new Parser[A] { def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R] = { def kf_(e: String) = f(e).runParser(kf, ks) return m.runParser(kf_, ks) } } def raiseError[A](e: String) = new Parser[A] { def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R] = kf(e) } } implicit def ToMonadErrorOps[A](m: Parser[A]) = new { def handleError(f: String => Parser[A]): Parser[A] = implicitly[MonadError[({type λ[String, α] = Parser[α]})#λ, String]].handleError(m)(f) } implicit def ToMonadErrorIdOps(e: String) = new { def raiseError[A]: Parser[A] = implicitly[MonadError[({type λ[String, α] = Parser[α]})#λ, String]].raiseError(e) } type Header = Seq[Symbol] case class Field(value: String) { def parseField[A: FromField] = implicitly[FromField[A]].parseField(Field(value)) } case class Record(value: Map[Symbol, Field]) { def parseRecord[A: FromRecord] = implicitly[FromRecord[A]].parseRecord(Record(value)) def lookup[A: FromField](name: Symbol): Parser[A] = value.get(name).fold(("no field named " + name.name).raiseError[A])(_.parseField[A]) def lookup[A: FromField](name: Symbol, default: String): Parser[A] = value.get(name).getOrElse(Field(default)).parseField[A] } type Failure[ F[_], R] = String => F[R] type Success[A, F[_], R] = A => F[R] trait Parser[+A] { def runParser[F[_], R](kf: Failure[F, R], ks: Success[A, F, R]): F[R] } def runParser[A](p: Parser[A]): Either[String, A] = { type F[R] = Either[String, R] def left (e: String): F[A] = Left(e) def right(x: A ): F[A] = Right(x) return p.runParser(left, right) } trait FromRecord[A] { def parseRecord(r: Record): Parser[A] } trait FromField[A] { def parseField(f: Field): Parser[A] } trait ToRecord[A] { def toRecord(a: A): Record } trait ToField[A] { def toField(a: A): Field } class DecodeFailedException private(e: RuntimeException) extends RuntimeException(e) { def this(msg: String) = this(new RuntimeException(msg)) def this(msg: String, cause: Throwable) = this(new RuntimeException(msg, cause)) } // Option[A] implicit def OptionFromField[A: FromField] = new FromField[Option[A]] { def parseField(f: Field): Parser[Option[A]] = { if (f.value.isEmpty) { return None.point[Parser] } else { f.parseField[A].map { Some(_) } } } } // String implicit val StringFromField = new FromField[String] { def parseField(f: Field): Parser[String] = f.value.point[Parser] } // Int implicit val IntFromField = new FromField[Int] { def parseField(f: Field): Parser[Int] = { try { f.value.toInt.point[Parser] } catch { case e: NumberFormatException => e.getMessage().raiseError[Int] } } } } trait TSVFunctions extends TSVTypes { def decode[A: FromRecord](tsv: StringLike[_]): Seq[A] = { val lines = tsv.split('\n').filter(!_.isEmpty) val header = lines.head.split('\t').map(Symbol(_)) val records = lines.tail.map(line => Record((header zip line.split('\t').map { Field(_) }).toMap)) return records.map { r => runParser(r.parseRecord[A]) match { case Right(a) => a case Left(e) => throw new DecodeFailedException(e) } } } } object TSV extends TSVTypes with TSVFunctions