| author | Christian Urban <christian.urban@kcl.ac.uk> | 
| Mon, 22 Nov 2021 11:24:08 +0000 | |
| changeset 850 | 7fb643cb3d9d | 
| parent 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))  | 
| 753 | 42  | 
dfa.accepts("aaabbb".toList)    // true
 | 
| 
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  |