--- a/progs/automata/der.sc Sat Oct 11 08:33:35 2025 +0100
+++ b/progs/automata/der.sc Sat Oct 11 09:12:13 2025 +0100
@@ -1,4 +1,4 @@
-// Another automaton construction
+// Another "automaton" construction
//================================
import $file.dfa, dfa._
@@ -48,3 +48,8 @@
println(pseudo.accepts("a".toList)) // true
println(pseudo.accepts("aa".toList)) // true
println(pseudo.accepts("bb".toList)) // false
+
+// Moral: this is not really a construction of an automaton, because
+// it can potentially have infinitely many states. Our implementation
+// of an automaton does not prevent this. It takes some additional
+// wprk to make this method to work.
--- a/progs/automata/thompson.sc Sat Oct 11 08:33:35 2025 +0100
+++ b/progs/automata/thompson.sc Sat Oct 11 09:12:13 2025 +0100
@@ -9,12 +9,12 @@
// states for Thompson construction
case class TState(i: Int) extends State
-object TState {
+object TSt {
var counter = 0
- def apply() : TState = {
+ def next() : TState = {
counter += 1;
- new TState(counter)
+ TState(counter)
}
}
@@ -27,20 +27,20 @@
// NFA that does not accept any string
def NFA_ZERO(): NFAt = {
- val Q = TState()
+ val Q = TSt.next()
NFA(Set(Q), { case _ => Set() }, Set())
}
// NFA that accepts the empty string
def NFA_ONE() : NFAt = {
- val Q = TState()
+ val Q = TSt.next()
NFA(Set(Q), { case _ => Set() }, Set(Q))
}
// NFA that accepts the string "c"
def NFA_CHAR(c: Char) : NFAt = {
- val Q1 = TState()
- val Q2 = TState()
+ val Q1 = TSt.next()
+ val Q2 = TSt.next()
NFA(Set(Q1), { case (Q1, d) if (c == d) => Set(Q2) }, Set(Q2))
}
@@ -76,7 +76,7 @@
// star of a NFA
def NFA_STAR(nfa: NFAt) : NFAt = {
- val Q = TState()
+ val Q = TSt.next()
val new_delta : eNFAtrans =
{ case (Q, None) => nfa.starts
case (q, None) if nfa.fins(q) => Set(Q) }