diff -r 70c307641d05 -r 1e4da6d2490c progs/re3.scala --- a/progs/re3.scala Mon Sep 22 13:42:14 2014 +0100 +++ b/progs/re3.scala Fri Sep 26 14:06:55 2014 +0100 @@ -1,57 +1,37 @@ -import scala.language.implicitConversions - -abstract class Rexp { - def simp : Rexp = this -} - +abstract class Rexp case object NULL extends Rexp case object EMPTY extends Rexp case class CHAR(c: Char) extends Rexp -case class ALT(r1: Rexp, r2: Rexp) extends Rexp { - override def simp = (r1.simp, r2.simp) match { - case (NULL, r) => r - case (r, NULL) => r - case (r, EMPTY) => if (nullable(r)) r else ALT(r, EMPTY) - case (EMPTY, r) => if (nullable(r)) r else ALT(r, EMPTY) - case (r1, r2) => if (r1 == r2) r1 else ALT(r1, r2) +case class ALT(r1: Rexp, r2: Rexp) extends Rexp +case class SEQ(r1: Rexp, r2: Rexp) extends Rexp +case class STAR(r: Rexp) extends Rexp +case class NTIMES(r: Rexp, n: Int) extends Rexp + +def simp(r: Rexp): Rexp = r match { + case ALT(r1, r2) => { + val r1s = simp(r1) + val r2s = simp(r2) + (r1s, r2s) match { + case (NULL, _) => r2s + case (_, NULL) => r1s + case _ => if (r1s == r2s) r1s else ALT(r1s, r2s) + } } -} -case class SEQ(r1: Rexp, r2: Rexp) extends Rexp { - override def simp = (r1.simp, r2.simp) match { - case (NULL, _) => NULL - case (_, NULL) => NULL - case (EMPTY, r) => r - case (r, EMPTY) => r - case (r1, r2) => SEQ(r1, r2) + case SEQ(r1, r2) => { + val r1s = simp(r1) + val r2s = simp(r2) + (r1s, r2s) match { + case (NULL, _) => NULL + case (_, NULL) => NULL + case (EMPTY, _) => r2s + case (_, EMPTY) => r1s + case _ => SEQ(r1s, r2s) + } } -} -case class STAR(r: Rexp) extends Rexp { - override def simp = r.simp match { - case NULL => EMPTY - case EMPTY => EMPTY - case r => STAR(r) - } -} -case class NTIMES(r: Rexp, n: Int) extends Rexp { - override def simp = if (n == 0) EMPTY else - r.simp match { - case NULL => NULL - case EMPTY => EMPTY - case r => NTIMES(r, n) - } + case NTIMES(r, n) => NTIMES(simp(r), n) + case r => r } -// some convenience for typing in regular expressions -def charlist2rexp(s : List[Char]) : Rexp = s match { - case Nil => EMPTY - case c::Nil => CHAR(c) - case c::s => SEQ(CHAR(c), charlist2rexp(s)) -} -implicit def string2rexp(s : String) : Rexp = charlist2rexp(s.toList) - - -// nullable function: tests whether the regular -// expression can recognise the empty string def nullable (r: Rexp) : Boolean = r match { case NULL => false case EMPTY => true @@ -62,7 +42,6 @@ case NTIMES(r, i) => if (i == 0) true else nullable(r) } -// derivative of a regular expression w.r.t. a character def der (c: Char, r: Rexp) : Rexp = r match { case NULL => NULL case EMPTY => NULL @@ -76,20 +55,18 @@ if (i == 0) NULL else SEQ(der(c, r), NTIMES(r, i - 1)) } -// derivative w.r.t. a string (iterates der) def ders (s: List[Char], r: Rexp) : Rexp = s match { case Nil => r - case c::s => ders(s, der(c, r).simp) + case c::s => ders(s, simp(der(c, r))) } -// main matcher function def matcher(r: Rexp, s: String) : Boolean = nullable(ders(s.toList, r)) //one or zero def OPT(r: Rexp) = ALT(r, EMPTY) -def EVIL(n: Int) = SEQ(NTIMES(OPT("a"), n), NTIMES("a", n)) +def EVIL(n: Int) = SEQ(NTIMES(OPT(CHAR('a')), n), NTIMES(CHAR('a'), n)) def time_needed[T](i: Int, code: => T) = { val start = System.nanoTime()