The run operation is used as a user interface. Thanks to this operation, we are going to display information about the finite state machine, read user input and process steps.
The step operation is used to go to an other state depending on the user's input and the transitions available from the current state.
The fire operation is used to change the current state and to get the produced string.
Let us see the behavior of these three operations.
The run algorithm
Behavior :
1 – initialize current state
2 – loop until the user's input equal to "quit"
print the current state
read a string
process a step
catch exceptions if there are some and exit the program displaying the error.
Here is the code of the operation :
operation run() : Void raises FSMException is do // reset if there is no current state if self.currentState == void then self.currentState := self.initialState end self from var str : String init "init" until str == "quit" loop stdio.writeln("Current state : " + self.currentState.name) str := stdio.read("give me a letter : ") if str == "quit" then stdio.writeln("") stdio.writeln("quitting ...") else if str == "print" then stdio.writeln("") else stdio.writeln(str) stdio.writeln("stepping...") do var textRes : String textRes := self.currentState.step(str) if( textRes == void or textRes == "" ) then textRes := "NC" end stdio.writeln("string produced : " + textRes) rescue (err : ConstraintViolatedPre) stdio.writeln(err.toString) stdio.writeln(err.message) str := "quit" rescue (err : ConstraintViolatedPost) stdio.writeln(err.toString) stdio.writeln(err.message) str := "quit" rescue(err : NonDeterminism) stdio.writeln(err.toString) str := "quit" rescue(err : NoTransition) stdio.writeln(err.toString) str := "quit" end end end end end
The step algorithm
In this operation, there are pre and post conditions. These are conditions checked each time the operation is called. If they are evaluated to false an exception is raised. You can choose to check them or not. Please refer to the corresponding tutorial on how to use run configurations.
Behavior :
1 – Select the possible transitions.
2 – If there is none raise a NoTransition exception.
If there is more than one raise a NonDeterminism exception.
3 – If there is only one transition, call its fire operation and return its result.
// Go to the next state operation step(c : String) : String raises FSMException // Declaration of the pre-condition pre notVoidInput is c != void and c != "" // Declaration of the post-condition post notVoidOutput is result != void and result != "" is do // Get the valid transitions var validTransitions : Collection<Transition> validTransitions := outgoingTransition.select { t | t.input.equals(c) } // Check if there is one and only one valid transition if validTransitions.empty then raise NoTransition.new end if validTransitions.size > 1 then raise NonDeterminism.new end // Fire the transition result := validTransitions.one.fire end
The fire algorithm
Behavior :
1 – change the current state of the FSM
2 – return the produced string
// Fire the transition operation fire() : String is do // update FSM current state source.owningFSM.currentState := target result := output end