0xDEADBEEF

RSS odkazy

Vlastní kombinátory parserů

7. 9. 2020 #kód
trait Node[T, R] { self =>
  def apply(xs: Seq[T]): (R, Seq[T])

  def ~ [R2](n: Node[T, R2]) = Pair[T, R, R2](self, n)
  def | (n: Node[T, R]) = Alt[T, R](self, n)

  def ~> [R2](n: Node[T, R2]) = Pair[T, R, R2](self, n).map { case a ~ b => b }
  def <~ [R2](n: Node[T, R2]) = Pair[T, R, R2](self, n).map { case a ~ b => a }

  def map[S](f: R => S): Node[T, S] =  new Node[T, S] {
    def apply(xs: Seq[T]): (S, Seq[T]) =
      self.apply(xs) match {
        case null => null
        case (x, rest) => (f(x), rest)
      }
  }
}

case class One[T](f: T => Boolean) extends Node[T, T] {
  def apply(xs: Seq[T]): (T, Seq[T]) =
    if (xs.nonEmpty && f(xs.head)) (xs.head, xs.tail)
    else null
}

object One {
  def apply[T](x: T): One[T] = One[T] { (a: T) => a == x}
}

case class Rep[T, R](n: Node[T, R]) extends Node[T, Seq[R]] {
  def apply(xs: Seq[T]): (Seq[R], Seq[T]) =
    n(xs) match {
      case null => (Nil, xs)
      case (x, rest) =>
        val (x2, rest2) = apply(rest)
        (x +: x2, rest2)
    }
}

case class Pair[T, R1, R2](a: Node[T, R1], b: Node[T, R2]) extends Node[T, (R1, R2)] {
  def apply(xs: Seq[T]): ((R1, R2), Seq[T]) =
    a(xs) match {
      case null => null
      case (x, rest) =>
        b(rest) match {
          case null => null
          case (y, rest2) => ((x, y), rest2)
        }
    }
}

object ~ {
  def unapply[A, B](ab: (A, B)) = Some(ab)
}

case class Alt[T, R](a: Node[T, R], b: Node[T, R]) extends Node[T, R] {
  def apply(xs: Seq[T]): (R, Seq[T]) =
    a(xs) match {
      case null => b(xs)
      case res => res
    }
}

def Rec[T, R](n: => Node[T, R]) = new Node[T, R] {
  lazy val node = n
  def apply(xs: Seq[T]): (R, Seq[T]) =
    node.apply(xs)
}
píše k47 (@kaja47, k47)