|
1 // epsilon NFAs...immediately translated into NFAs |
|
2 // (needs nfa.scala) |
|
3 |
|
4 // fixpoint construction |
|
5 import scala.annotation.tailrec |
|
6 @tailrec |
|
7 def fixpT[A](f: A => A, x: A): A = { |
|
8 val fx = f(x) |
|
9 if (fx == x) x else fixpT(f, fx) |
|
10 } |
|
11 |
|
12 // translates eNFAs directly into NFAs |
|
13 def eNFA[A, C](starts: Set[A], // starting states |
|
14 delta: (A, Option[C]) :=> Set[A], // epsilon-transitions |
|
15 fins: A => Boolean) : NFA[A, C] = { // final states |
|
16 |
|
17 // epsilon transitions |
|
18 def enext(q: A) : Set[A] = |
|
19 applyOrElse(delta, (q, None)) |
|
20 |
|
21 def enexts(qs: Set[A]) : Set[A] = |
|
22 qs | qs.flatMap(enext(_)) |
|
23 |
|
24 // epsilon closure |
|
25 def ecl(qs: Set[A]) : Set[A] = |
|
26 fixpT(enexts, qs) |
|
27 |
|
28 // "normal" transitions |
|
29 def next(q: A, c: C) : Set[A] = |
|
30 applyOrElse(delta, (q, Some(c))) |
|
31 |
|
32 def nexts(qs: Set[A], c: C) : Set[A] = |
|
33 ecl(ecl(qs).flatMap(next(_, c))) |
|
34 |
|
35 // result NFA |
|
36 NFA(ecl(starts), |
|
37 { case (q, c) => nexts(Set(q), c) }, |
|
38 q => ecl(Set(q)) exists fins) |
|
39 } |