| author | Christian Urban <christian.urban@kcl.ac.uk> | 
| Tue, 01 Sep 2020 12:44:07 +0100 | |
| changeset 750 | 40b7efa5fbed | 
| parent 733 | 4d37ccc8c5be | 
| child 753 | 30ea6b01db46 | 
| permissions | -rw-r--r-- | 
| 733 | 1 | // DFAs in Scala using partial functions | 
| 480 | 2 | import scala.util.Try | 
| 479 | 3 | |
| 623 | 4 | // a type abbreviation for partial functions | 
| 480 | 5 | type :=>[A, B] = PartialFunction[A, B] | 
| 479 | 6 | |
| 733 | 7 | // main DFA class | 
| 623 | 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
 | |
| 479 | 11 | |
| 480 | 12 |   def deltas(q: A, s: List[C]) : A = s match {
 | 
| 13 | case Nil => q | |
| 14 | case c::cs => deltas(delta(q, c), cs) | |
| 145 
920f675b4ed1
added
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: diff
changeset | 15 | } | 
| 479 | 16 | |
| 480 | 17 | def accepts(s: List[C]) : Boolean = | 
| 733 | 18 | Try(fins(deltas(start, s))).getOrElse(false) | 
| 479 | 19 | } | 
| 20 | ||
| 487 | 21 | // the example shown in the handout | 
| 145 
920f675b4ed1
added
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: diff
changeset | 22 | abstract class State | 
| 480 | 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 | |
| 145 
920f675b4ed1
added
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: diff
changeset | 28 | |
| 480 | 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 } | |
| 145 
920f675b4ed1
added
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: diff
changeset | 40 | |
| 480 | 41 | val dfa = DFA(Q0, delta, Set[State](Q4)) | 
| 576 | 42 | dfa.accepts("aaabbb".toList) 
 | 
| 145 
920f675b4ed1
added
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: diff
changeset | 43 | |
| 480 | 44 | dfa.accepts("bbabaab".toList)   // true
 | 
| 45 | dfa.accepts("baba".toList)      // false
 | |
| 576 | 46 | dfa.accepts("abc".toList)       // false
 | 
| 487 | 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 | ||
| 623 | 55 | // a transition function with a sink state | 
| 487 | 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 |