# 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>