/*
 * main.cpp
 *
 * Version:
 *          0.01.9
 *
 * Previous Versions:
 *
 * 2010-09-29: 0.01.1
 * 2010-09-28: 0.00.5
 */

/**
  * Project Scanner:
  *          This project will create a simple c++ scanner,
  *          to be used later in completeing a c++ compiler for
  *          CSIT-433.
  *
  * @author Josh Galofaro
  * @date 2010-09-29
  */
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <stdlib.h>

using namespace std;

/* enum states: All FSM states, including sbegin as the only accept state
   enum tokens: All FSM tokens to be considered */
enum states{ sif, sint, swhile, selse, sreturn, svoid };
enum tokens{ tplus, tminus, tstar, tdiv, tgreater, tlesser, tass, tnot,
             tsemi, toparam, tcparam, tobracket, tcbracket };

void tokenizer( string, int );

/**
  * Main:
  *     Main will read in from the input file provided in the
  *     command line and output two arrays, toutput and soutput
  *     which will contain the proper set of tokens generated by
  *     the input file and their corrisponding string.
  *
  * @author Josh Galofaro
  *
  * @date 2010-09-28
  *
  * @param  int argc     Holds the size of the command line input
  * @param  char argv[]  Char array for the command line input
  *
  * @exception 101       Improper command line arguments submitted
  * @exception 102       File handle error, File not opened
  */
int main(int argc, char *argv[])
{
    const char * fName;         //File name given by command line args
    int curLine = 0;            //Keep track of where you are in the file

    cout << "Scanner activated..." << endl;

    /* Check command line:
         only the file name should be submitted */
    try
    {
        if( argc != 2 )
        {
            throw 101;      //Exception 101, command line arguments not proper
        }
       else if( argc == 2 )
        {
            fName = argv[1];
        }
    }
    catch (int e)
    {
        cerr << "An exception occured in program: " << argv[0]
                <<  endl << "Error No. " << e << endl;
        exit( 1 );
    }

    /* Check file:
            Throw exception if fails to open */
    try
      {
          if( argc != 2 )
          {
              throw 101; //Exception 101, command line arguments not proper
          }
         else if( argc == 2 )
          {
              fName = argv[1];
          }


          ifstream inputFile; //Data file
          inputFile.open( fName );

          /*
           * 2010-09-28: To do here:
           * Enter a loop;
           * Read in one line per loop,
           * Pass that line into parse method,
           * Parse method will generate the tokens and
           * add them to their proper arrays.
           * End of file, exit the loop
           */
          if( inputFile.is_open() )
          {
              string line; //Holds a single line of the input file

              cout << "File stream has opened..." << endl;

              cout << "Tokenizer activated for:" << endl;
              while( !inputFile.eof() )
              {
                  curLine++;

                  getline(inputFile, line);

                  tokenizer( line, curLine );
              }

              inputFile.close();
              cout << "File stream closed..." << endl;
          }
          else
          {
              throw 102; //Error 102, File not opened
          }
      }
      catch (int e)
      {
          cerr << "An exception occured in program: " << argv[0]
                  << endl << "Error No. " << e << endl;

          if( e == 101 )
          {
              cerr << "Improper command line arguments" << endl;
          }
          else if( e == 102 )
          {
              cerr << "File could not be found/opened" << endl;
          }

          exit( 1 );
      }

      cout << "Scanner deactivated..." << endl;
      return 0;
  }

/**
  * Tokenizer:
  *     Tokenizer will accept a single line of the input file in a string, and
  *     parse the string to generate the proper tokens. It will then dump the
  *     generated tokens into the toutput array and their corrisponding string
  *     into the soutput array.
  *
  * @author Josh Galofaro
  *
  * @date 2010-09-28
  *
  * @param string xLine     The given line from the input file
  * @param int lineNum      Integer to keep track of which line we are in
  */
void tokenizer( string xLine, int lineNum )
{
    /* To do here in this bitch:
     *          Take xLine and split it up into single characters,
     *          Toss those mother fuckers into an array
     *          character by character follow the FSM to generate each token
     *          Hitting a white space or symbol signifies the end
     *          of that particular token. Once created toss the token
     *          into the toutput array, and grab that hoe of a string
     *          and toss her into the soutput array where she belongs.
     *          Delete the character array.
     *          Have the string make me a sammach.
     */
    cout << "Entering line " << lineNum << "..." << endl;

    int charSize = 50, strSize = 10, curSize = 0;
    string str;
    string * strArray = new string[strSize];
    char ch;                     //Char to split the string with
    char * charArray = new char[charSize];       //Single character array

    istringstream iss(xLine, istringstream::in);

    /* Split the line into single words */
    while( iss >> str )
    {
        if( curSize >= strSize )
        {
            strSize = strSize * 2;
            strArray = (string *)realloc( strArray, strSize);
        }

        strArray[curSize] = str;
        curSize++;
    }

    for( int i = 0; i < curSize; i++)
    {
        cout << strArray[i] << endl;
    }
    delete strArray;

    cout << "Leaving line " << lineNum << "..." << endl;
}
