progs/automata/dfa.sc
changeset 733 022e2cb1668d
parent 623 47a299e7010f
child 753 d94fdbef1a4f
equal deleted inserted replaced
732:c7bdd7eac4cb 733:022e2cb1668d
       
     1 // DFAs in Scala using partial functions
       
     2 import scala.util.Try
       
     3 
       
     4 // a type abbreviation for partial functions
       
     5 type :=>[A, B] = PartialFunction[A, B]
       
     6 
       
     7 // main DFA class
       
     8 case class DFA[A, C](start: A,               // the starting state
       
     9                      delta: (A, C) :=> A,    // transitions (partial fun)
       
    10                      fins:  A => Boolean) {  // the final states
       
    11 
       
    12   def deltas(q: A, s: List[C]) : A = s match {
       
    13     case Nil => q
       
    14     case c::cs => deltas(delta(q, c), cs)
       
    15   }
       
    16 
       
    17   def accepts(s: List[C]) : Boolean = 
       
    18     Try(fins(deltas(start, s))).getOrElse(false)
       
    19 }
       
    20 
       
    21 // the example shown in the handout 
       
    22 abstract class State
       
    23 case object Q0 extends State
       
    24 case object Q1 extends State
       
    25 case object Q2 extends State
       
    26 case object Q3 extends State
       
    27 case object Q4 extends State
       
    28 
       
    29 val delta : (State, Char) :=> State = 
       
    30   { case (Q0, 'a') => Q1
       
    31     case (Q0, 'b') => Q2
       
    32     case (Q1, 'a') => Q4
       
    33     case (Q1, 'b') => Q2
       
    34     case (Q2, 'a') => Q3
       
    35     case (Q2, 'b') => Q2
       
    36     case (Q3, 'a') => Q4
       
    37     case (Q3, 'b') => Q0
       
    38     case (Q4, 'a') => Q4
       
    39     case (Q4, 'b') => Q4 }
       
    40 
       
    41 val dfa = DFA(Q0, delta, Set[State](Q4))
       
    42 dfa.accepts("aaabbb".toList) 
       
    43 
       
    44 dfa.accepts("bbabaab".toList)   // true
       
    45 dfa.accepts("baba".toList)      // false
       
    46 dfa.accepts("abc".toList)       // false
       
    47 
       
    48 // another DFA test with a Sink state
       
    49 abstract class S
       
    50 case object S0 extends S
       
    51 case object S1 extends S
       
    52 case object S2 extends S
       
    53 case object Sink extends S
       
    54 
       
    55 // a transition function with a sink state
       
    56 val sigma : (S, Char) :=> S = 
       
    57   { case (S0, 'a') => S1
       
    58     case (S1, 'a') => S2
       
    59     case _ => Sink
       
    60   }
       
    61 
       
    62 val dfa1a = DFA(S0, sigma, Set[S](S2))
       
    63 
       
    64 dfa1a.accepts("aa".toList)        // true
       
    65 dfa1a.accepts("".toList)          // false
       
    66 dfa1a.accepts("ab".toList)        // false
       
    67