finite_state_machine(n) 1.0 "flibs"

NAME

finite_state_machine - Support for building finite state machines

TABLE OF CONTENTS

    TABLE OF CONTENTS
    SYNOPSIS
    DESCRIPTION
    DATA TYPES AND ROUTINES
    EXAMPLE
    COPYRIGHT

SYNOPSIS

call fsm_loop( data, machine )
call fsm_loop_int( data, machine )
call fsm_loop_print( data, machine, print_debug )
call fsm_loop_print_int( data, machine, print_debug )
call fsm_get_state( fsm, state )
call fsm_set_state( fsm, state )
call fsm_set_lurep( fsm, lurep )
lurep = fsm_get_lurep( fsm )
call fsm_finish( fsm )

DESCRIPTION

The finite_state.f90 source file defines a set of subroutines that allow you to build a so-called finite state machine. This is basically a way to structure a program or a part of a program that takes input (from a file or from some other source) and reacts to that input depending on the "state" it is in. A simple example could be a heating device with a thermostat: if the ambient temperature is high enough, there is no need to heat the room, so the system is in a rest state. If the temperature is lower than the set temperature, the heater should be turned on.

Finite state machines are encountered in many different areas in one form or other. Lexical analysers are another, more complicated example. When analysing an arithmetic expression like "1+2*3", the "+" that follows the "1" will probably bring the analyser in a different state: the literal number has terminated, it now needs to deal with an operator. This type of programming is used in the test/demo program to show how to use the finite_state.f90 source file to build a non-trivial FSM.

DATA TYPES AND ROUTINES

The source code expects a data type, STATE_DATA, that contains all information describing the finite state machine. The contents is entirely up to the application though. The state data are passed to the subroutine that implements the actual state machine, so that you can use this argument to prepare the computation.

The type must be defined in a module called "fsm_data_definitions":

 
module MYDATA_POOL

type POOLDATA
    integer :: pool_index          ! For private use by pool_acquire/pool_release
    real, dimension(100) :: work   ! The actual work space
end type

include "mem_pool.f90"

end module MYDATA_POOL

The code defines the following routines:
call fsm_loop( data, machine )
Run a finite state machine, implemented by the subroutine "machine" that uses character strings to define the state. The first state is always set to the parameter FSM_INIT_CHAR (="INIT"), the initial state, and should be used to initialise the computation.

type(STATE_DATA) data
The data defining the current state of the machine

subroutine machine
Subroutine that does the actual computation. Its interface is:

 
    subroutine machine( fsm, data, curstate )
        use fsm_data_definitions
        implicit none
        type(FSM_STATE),  intent(inout) :: fsm
        type(STATE_DATA), intent(inout) :: data
        character(len=*), intent(in)    :: curstate
    end subroutine



call fsm_loop_int( data, machine )
Similar to fsm_loop but the machine's state is an integer now. The first state is represented by the parameter FSM_INIT (=0).

It has the same interface as fsm_loop

call fsm_loop_print( data, machine, print_debug )
Like fsm_loop, but the third argument is a routine that allows you to print intermediate results. It's interface is:

 
    subroutine print_debug( lurep, data, oldstate, curstate )
        use fsm_data_definitions
        implicit none
        integer, intent(in)             :: lurep
        type(STATE_DATA), intent(inout) :: data
        character(len=*), intent(in)    :: oldstate
        character(len=*), intent(in)    :: curstate
    end subroutine



call fsm_loop_print_int( data, machine, print_debug )
Like fsm_loop_int, but the third argument is a routine that allows you to print intermediate results. It's interface is:

 
    subroutine print_debug( lurep, data, oldstate, curstate )
        use fsm_data_definitions
        implicit none
        integer, intent(in)             :: lurep
        type(STATE_DATA), intent(inout) :: data
        integer, intent(in)             :: oldstate
        integer, intent(in)             :: curstate
    end subroutine



call fsm_get_state( fsm, state )
Get the current state from the FSM data structure

type(FSM_DATA) fsm
The data maintained by the FSM loop

integer/character(len=*), intent(out) state
Current state of the finite state machine - either as integer or as character string.
call fsm_set_state( fsm, state )
Set the current state in the FSM data structure

type(FSM_DATA) fsm
The data maintained by the FSM loop

integer/character(len=*), intent(in) state
The new state of the finite state machine - either as integer or as character string.
call fsm_set_lurep( fsm, lurep )
Set the LU-number for the print routine (by default: 0, to be interpreted as output to screen).

lurep = fsm_get_lurep( fsm )
Return the LU-number for the print routine.

call fsm_finish( fsm )
Instruct the FSM loop to stop.

EXAMPLE

The use of the source code in the two files "finite_state.f90"and "fsm_state.f90" is illustrated by the following example:

 
module fsm_data_definitions
    implicit none

    include 'fsm_state.f90'

    type STATE_DATA
        integer :: position           ! Current position in the string
        integer :: open_parens        ! Number of open parentheses
        character(len=80)              :: string ! String holding the expression
    end type STATE_DATA

end module fsm_data_definitions

This module defines the STATE_DATA derived type and includes the file with the (private) definitions.

The module that actually implements the finite state machine looks like this (the included file "finite_state.f90"contains the contains keyword):

 
module analyse_string
    use fsm_data_definitions
    include 'finite_state.f90'

!
! Here is the actual routine that implements the finite state machine
!
! analyse_expression --
!     Analyse an arithmetic expression
! Arguments:
!     fsm           Private data structure for the FSM machinery
!     data          Evaluation data structure
!     state_name    Current state of the machine
!
subroutine analyse_expression( fsm, data, state_name )
    type(FSM_STATE),  intent(inout)  :: fsm
    type(STATE_DATA), intent(inout)  :: data
    character(len=*), intent(in)     :: state_name

    ...

end subroutine analyse_expression

end module

(You can find the complete source code in the file "tst_finite_state.f90" in the source distribution)

COPYRIGHT

Copyright © 2006 Arjen Markus <arjenmarkus@sourceforge.net>