Here's a sample state machine:
The code is at http://code.google.com/p/razie/source/browse/trunk/razie/src/razie/SM.scala
The basic structure is:
(state, event-matcher) -> newstate + callback ++ unitcalback... + callback :: NilThe event-matcher can be:
- an event
- a sequence of events
- a function taking an event and returning...Boolean, of course
- def push (sm:StateMachine, t:Transition, e:Event) - use + for these
- def reset : Unit - use ++ for these (hey, I'm still getting my head around advanced scala stuff)
Enjoy, and if you likee, contribute, eh?
Here's the definition (in-work) of the high-level telnet state machine, a little more complicated but not much.
The picture (thanks to http://tomi.vanek.sk/index.php?page=telnet):

The state machine (when it's ready I'll post the link to the entire code):
Enjoy and, more importantly, have fun!
// based on diagram at http://tomi.vanek.sk/index.php?page=telnet
implicit val sm = this
val sstates @ (data, cmd, app, param, neg, subneg) = ("data", "cmd", "app", "param", "neg", "subneg")
override def start = state("data")
override val transitions : Seq[Transition] =
(data, IAC) -> cmd ::
(data, 0) -> data :: // NOP - don't know why i get these after CR
(data, 10) -> data :: // NOP - LF ignored?
(data, 13) -> data + eatLine + echo ("") :: // CR
(data, {_:Event=>true}) -> data + eatChar + echo ("") :: // remaining chars
(cmd, IAC) -> data ::
(cmd, Seq(WILL, WONT, DO, DONT)) -> neg + push ::
// TODO 3-2 should negociate stuff, i.e. reply with will/won't
(neg, {_:Event=>last==SM(DO)}) -> data + mode(true) + pop ::
(neg, {_:Event=>last==SM(DONT)}) -> data + mode(false) + pop ::
(neg, AnyEvent) -> data + echo("interesting sequence...") + pop :: // What is this?
(cmd, SB) -> subneg ::
(""".*""".r, CR) -> data :: // it's important to reset the thing on ENTRE
Nil
def eatChar (sm:StateMachine, t:Transition, e:Event)
def eatLine (sm:StateMachine, t:Transition, e:Event)
If you'd like to read more of my rants about scala, see http://wiki.homecloud.ca/thinking-in-scala