progs/re4.scala
changeset 422 5deefcc8cffa
parent 415 4ae59fd3b174
child 425 d14a9bdac26f
equal deleted inserted replaced
417:e74c696821a2 422:5deefcc8cffa
     1 import scala.annotation.tailrec    
       
     2 import scala.language.implicitConversions
       
     3     
     1     
     4 abstract class Rexp {
     2 abstract class Rexp
     5   def simp : Rexp = this
       
     6 }
       
     7 
       
     8 case object ZERO extends Rexp
     3 case object ZERO extends Rexp
     9 case object ONE extends Rexp
     4 case object ONE extends Rexp
    10 case class CHAR(c: Char) extends Rexp
     5 case class CHAR(c: Char) extends Rexp
    11 case class ALT(r1: Rexp, r2: Rexp) extends Rexp {
     6 case class ALT(r1: Rexp, r2: Rexp) extends Rexp 
    12   override def simp = (r1.simp, r2.simp) match {
     7 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp 
    13     case (ZERO, r) => r
     8 case class STAR(r: Rexp) extends Rexp 
    14     case (r, ZERO) => r
     9 case class NTIMES(r: Rexp, n: Int) extends Rexp 
    15     case (r, ONE) => if (nullable(r)) r else ALT(r, ONE)
       
    16     case (ONE, r) => if (nullable(r)) r else ALT(r, ONE)
       
    17     case (r1, r2) => if (r1 == r2) r1 else ALT(r1, r2)
       
    18   }
       
    19 }
       
    20 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp {
       
    21   override def simp = (r1.simp, r2.simp) match {
       
    22     case (ZERO, _) => ZERO
       
    23     case (_, ZERO) => ZERO
       
    24     case (ONE, r) => r
       
    25     case (r, ONE) => r
       
    26     case (r1, r2) => SEQ(r1, r2)
       
    27   }
       
    28 }
       
    29 case class STAR(r: Rexp) extends Rexp {
       
    30   override def simp = r.simp match {
       
    31     case ZERO => ONE
       
    32     case ONE => ONE
       
    33     case r => STAR(r)
       
    34   }
       
    35 }
       
    36 case class NTIMES(r: Rexp, n: Int) extends Rexp {
       
    37   override def simp = if (n == 0) ONE else 
       
    38     r.simp match {
       
    39       case ZERO => ZERO
       
    40       case ONE => ONE
       
    41       case r => NTIMES(r, n)
       
    42     }
       
    43 }
       
    44 
       
    45 // some convenience for typing in regular expressions
       
    46 def charlist2rexp(s : List[Char]) : Rexp = s match {
       
    47   case Nil => ONE
       
    48   case c::Nil => CHAR(c)
       
    49   case c::s => SEQ(CHAR(c), charlist2rexp(s))
       
    50 }
       
    51 implicit def string2rexp(s : String) : Rexp = charlist2rexp(s.toList)
       
    52 
       
    53 
    10 
    54 // nullable function: tests whether the regular 
    11 // nullable function: tests whether the regular 
    55 // expression can recognise the empty string
    12 // expression can recognise the empty string
    56 def nullable (r: Rexp) : Boolean = r match {
    13 def nullable (r: Rexp) : Boolean = r match {
    57   case ZERO => false
    14   case ZERO => false
    75   case STAR(r) => SEQ(der(c, r), STAR(r))
    32   case STAR(r) => SEQ(der(c, r), STAR(r))
    76   case NTIMES(r, i) => 
    33   case NTIMES(r, i) => 
    77     if (i == 0) ZERO else SEQ(der(c, r), NTIMES(r, i - 1))
    34     if (i == 0) ZERO else SEQ(der(c, r), NTIMES(r, i - 1))
    78 }
    35 }
    79 
    36 
    80 // derivative w.r.t. a string (iterates der)
    37 def simp(r: Rexp) : Rexp = r match {
    81 @tailrec
    38   case ALT(r1, r2) => (simp(r1), simp(r2)) match {
    82 def ders (s: List[Char], r: Rexp) : Rexp = s match {
    39     case (ZERO, r2s) => r2s
    83   case Nil => r
    40     case (r1s, ZERO) => r1s
    84   case c::s => ders(s, der(c, r).simp)
    41     case (r1s, r2s) => if (r1s == r2s) r1s else ALT (r1s, r2s)
       
    42   }
       
    43   case SEQ(r1, r2) =>  (simp(r1), simp(r2)) match {
       
    44     case (ZERO, _) => ZERO
       
    45     case (_, ZERO) => ZERO
       
    46     case (ONE, r2s) => r2s
       
    47     case (r1s, ONE) => r1s
       
    48     case (r1s, r2s) => SEQ(r1s, r2s)
       
    49   }
       
    50   case NTIMES(r1, n) => simp(r1) match {
       
    51     case ZERO => ZERO
       
    52     case ONE => ONE
       
    53     case r1s => NTIMES(r1s, n)
       
    54   }
       
    55   case r => r
    85 }
    56 }
    86 
    57 
    87 
    58 // derivative w.r.t. a string (iterates der)
       
    59 def ders2(s: List[Char], r: Rexp) : Rexp = (s, r) match {
       
    60   case (Nil, r) => r
       
    61   case (s, ZERO) => ZERO
       
    62   case (s, ONE) => if (s == Nil) ONE else ZERO
       
    63   case (s, CHAR(c)) => if (s == List(c)) ONE else 
       
    64                        if (s == Nil) CHAR(c) else ZERO
       
    65   case (s, ALT(r1, r2)) => ALT(ders2(s, r2), ders2(s, r2))
       
    66   case (c::s, r) => ders2(s, simp(der(c, r)))
       
    67 }
    88 
    68 
    89 // main matcher function
    69 // main matcher function
    90 def matcher(r: Rexp, s: String) : Boolean = nullable(ders(s.toList, r))
    70 def matcher(r: Rexp, s: String) : Boolean = nullable(ders2(s.toList, r))
    91 
    71 
    92 
    72 
    93 //one or zero
    73 //one or zero
    94 def OPT(r: Rexp) = ALT(r, ONE)
    74 def OPT(r: Rexp) = ALT(r, ONE)
    95 
    75 
    96 def EVIL1(n: Int) = SEQ(NTIMES(OPT("a"), n), NTIMES("a", n))
    76 def EVIL1(n: Int) = SEQ(NTIMES(OPT(CHAR('a')), n), NTIMES(CHAR('a'), n))
    97 val EVIL2 = SEQ(STAR("a"), "b")
    77 val EVIL2 = SEQ(STAR(CHAR('a')), CHAR('b'))
       
    78 
    98 
    79 
    99 def time_needed[T](i: Int, code: => T) = {
    80 def time_needed[T](i: Int, code: => T) = {
   100   val start = System.nanoTime()
    81   val start = System.nanoTime()
   101   for (j <- 1 to i) code
    82   for (j <- 1 to i) code
   102   val end = System.nanoTime()
    83   val end = System.nanoTime()
   104 }
    85 }
   105 
    86 
   106 val i = 5000
    87 val i = 5000
   107 println(i + " " + "%.5f".format(time_needed(10, matcher(EVIL1(i), "a" * i))))
    88 println(i + " " + "%.5f".format(time_needed(10, matcher(EVIL1(i), "a" * i))))
   108 
    89 
   109 for (i <- 1 to 9001 by 1000) {
    90 for (i <- 1 to 7000001 by 1000000) {
   110   println(i + " " + "%.5f".format(time_needed(2, matcher(EVIL1(i), "a" * i))))
    91   println(i + " " + "%.5f".format(time_needed(2, matcher(EVIL1(i), "a" * i))))
   111 }
    92 }
   112 
    93 
   113 for (i <- 1 to 7500001 by 500000) {
    94 for (i <- 1 to 7500001 by 500000) {
   114   println(i + " " + "%.5f".format(time_needed(2, matcher(EVIL2, "a" * i))))
    95   println(i + " " + "%.5f".format(time_needed(2, matcher(EVIL2, "a" * i))))