progs/automata/der.sc
changeset 784 7dac4492b0e6
parent 779 5385c8342f02
equal deleted inserted replaced
783:06cbaaad3ba8 784:7dac4492b0e6
       
     1 // Another automaton construction
       
     2 //================================
       
     3 
       
     4 import $file.dfa, dfa._ 
       
     5 
       
     6 // regular expressions
       
     7 abstract class Rexp
       
     8 case object ZERO extends Rexp                    // matches nothing
       
     9 case object ONE extends Rexp                     // matches the empty string
       
    10 case class CHAR(c: Char) extends Rexp            // matches a character c
       
    11 case class ALT(r1: Rexp, r2: Rexp) extends Rexp  // alternative
       
    12 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp  // sequence
       
    13 case class STAR(r: Rexp) extends Rexp            // star
       
    14 
       
    15 // the nullable function: tests whether the regular 
       
    16 // expression can recognise the empty string
       
    17 def nullable (r: Rexp) : Boolean = r match {
       
    18   case ZERO => false
       
    19   case ONE => true
       
    20   case CHAR(_) => false
       
    21   case ALT(r1, r2) => nullable(r1) || nullable(r2)
       
    22   case SEQ(r1, r2) => nullable(r1) && nullable(r2)
       
    23   case STAR(_) => true
       
    24 }
       
    25 
       
    26 // the derivative of a regular expression w.r.t. a character
       
    27 def der (c: Char, r: Rexp) : Rexp = r match {
       
    28   case ZERO => ZERO
       
    29   case ONE => ZERO
       
    30   case CHAR(d) => if (c == d) ONE else ZERO
       
    31   case ALT(r1, r2) => ALT(der(c, r1), der(c, r2))
       
    32   case SEQ(r1, r2) => 
       
    33     if (nullable(r1)) ALT(SEQ(der(c, r1), r2), der(c, r2))
       
    34     else SEQ(der(c, r1), r2)
       
    35   case STAR(r1) => SEQ(der(c, r1), STAR(r1))
       
    36 }
       
    37 
       
    38 
       
    39 def flaw(r: Rexp) : DFA[Rexp, Char] = {
       
    40   DFA(r, 
       
    41       { case (r, c) => der(c, r) }, 
       
    42       nullable(_))
       
    43 }
       
    44 
       
    45 val r = STAR(CHAR('a'))
       
    46 val pseudo = flaw(r)
       
    47 println(pseudo.accepts("".toList))    // true
       
    48 println(pseudo.accepts("a".toList))   // true
       
    49 println(pseudo.accepts("aa".toList))  // true
       
    50 println(pseudo.accepts("bb".toList))  // false