/* This program determines if a sequence of characters represents a
   valid C++ decimal integer, by simulating a finite state automaton.

   Input (keyboard): A sequence of characters
   Output (screen):  User prompts and messages indicating whether
                     inputs represent valid integers
------------------------------------------------------------------*/

#include <iostream.h>

#include "Set.h"
#include "Boolean.h"

Boolean IntRecognized(void);                         // the recognizer

int main(void)
{
   char
      Response;                                     // query response
   Set
      YesResponsesSet(2, 'y', 'Y');                 // "Yes" responses

   do                                               // Loop:
   {
      cout << "\nEnter the string to be analyzed: ";//   input prompt

      if (IntRecognized())                          //   scan string
         cout << "-- Valid integer recognized.\n";  //     and display 
      else                                          //     appropriate
         cout << "-- Not a valid integer.\n";       //     message
 
      cout << "More data (y or n)? ";               //   query user
      cin >> Response;                              //   get response
   }
   while (YesResponsesSet.Contains(Response));      // as long as 
                                                    // user wants
   return 0;
}

/*----- This function simulates the behavior of a finite state
           automaton that recognizes decimal integer constants.

   Input (keyboard): A line of characters
   Return:           True iff that line comprises a valid
                        decimal integer constant
------------------------------------------------------------------*/

#include <limits.h>                            // INT_MAX

Boolean IntRecognized(void)
{
  const int                                    // constant values:
    AcceptState = 2,                           //   accept state
    RejectState = 99;                          //   reject state

  char
    Symbol;                                    // input symbol
  int                                          // current state,
    State = 0;                                 //   initially the
                                               //   start state
  Set
    WhiteSpaceSet(3, ' ', '\t', '\n'),         // set of white spaces
    DigitSet(10, '0', '1', '2', '3', '4',      // set of digit chars
                 '5', '6', '7', '8', '9'),
    DelimiterSet(1, '\n'),                     // valid int followers
    FinalStateSet(2, AcceptState, RejectState);// terminal states

  do                                           // Loop:
  {
    cin.get(Symbol);                           //   get the next char

    switch (State)                             //   if in:
    {
      case 0:                                  //    State 0:
        if (WhiteSpaceSet.Contains(Symbol))    //      if it's a space
           State = 0;                          //        stay here
        else if (DigitSet.Contains(Symbol))    //      if it's a digit
	   State = 1;                          //        goto state 1
        else                                   //      otherwise
        {
          cin.ignore(INT_MAX, '\n');           //        skip the line
          State = RejectState;                 //        REJECT
        }
        break;

      case 1:                                   //   State 1:
        if (DigitSet.Contains(Symbol))          //     if it's a digit
           State = 1;                           //       stay in 1
        else if (DelimiterSet.Contains(Symbol)) //     if it's a delim
           State = AcceptState;                 //       ACCEPT
        else                                    //     otherwise
        {
           cin.ignore(INT_MAX, '\n');           //       skip the line
           State = RejectState;                 //       REJECT
        }
        break;

      default:                                  //  shouldn't happen
          cerr << "\n*** Main error: invalid state "
               << State << " entered!\n";       //    but just in case
          State = RejectState;                  //     REJECT
    }
  }                                             // until State is
  while (!FinalStateSet.Contains(State));       //   a final state

  return (State == AcceptState);
}

