PROGRAM Lexical_Analysis
!-----------------------------------------------------------------------------
! This program implements a simple lexical analyzer for Fortran integer
! constants. A finite-state machine that recognizes integer constants was
! used in designing the program.  Identifiers used:
!   DeadState          : dead state
!   CurrentState       : current state
!   I                  : index
!   InputString        : input string to be checked
!   Symbol             : a character in InputString
!   End_of_String_Mark : character used to indicate the end of the string
!   Response           : user response to "more data" query
!
! Input:  InputString, Response
! Output: User prompt, message indicating if string is a valid integer
!-----------------------------------------------------------------------------

  INTEGER, PARAMETER :: DeadState = 99
  INTEGER :: CurrentState, I
  CHARACTER(1) :: Symbol, End_of_String_Mark = ";", Response, InputString*80


  ! Repeat the following until no more strings to check
  DO
     PRINT *, "Enter the string to be checked (end with ", &
              End_of_String_Mark, ") "
     READ '(A)', InputString
     I = 1

     ! Begin in initial state
     CurrentState = 0

     DO
        IF (InputString(I:I) == End_of_String_Mark) EXIT
        ! If Ith symbol in InputString is the end-of-string mark
        ! terminate repetion

        ! Otherwise continue processing InputString

        Symbol = InputString(I:I)

        SELECT CASE (CurrentState)
          CASE(0)
             IF (Symbol == " ") THEN                          ! blank
                CurrentState = 0
             ELSE IF (Symbol == "+" .OR. Symbol ==  "-") THEN ! sign
                CurrentState = 1
             ELSE IF (Symbol >= "0" .AND. Symbol <= "9") THEN ! digit
                CurrentState = 2
             ELSE                                             ! other char
                CurrentState = DeadState
             END IF
          CASE(1, 2)
             IF (Symbol >= "0" .AND. Symbol <= "9") THEN      ! digit
                CurrentState = 2
             ELSE                                             ! other char
                CurrentState = DeadState
             END IF
        END SELECT

       I = I + 1
     END DO

     IF (CurrentState == 2) THEN
        PRINT *, "Valid integer"
     ELSE
        PRINT *, "Not a valid integer"
     END IF

     WRITE (*, '(/ 1X, A)', ADVANCE = "NO") "More data (Y or N)? "
     READ *, Response
     IF (Response /= "Y") EXIT
  END DO

END PROGRAM Lexical_Analysis
