#include "lexan_bench.h"
#include <math.h>
#include <stdexcept>
#include <ctype.h>
#include "err.h"
#include "config.h"
//---------------------------------------------------------------------------
LexanBench :: LexanBench (const char *input_file,int m):
   Lexan(input_file) {
   mode=m;
   kw_init();
}
//---------------------------------------------------------------------------
void LexanBench :: init(const char *n,int m)
{
   Lexan :: init (n);
   if (keywords.size() == 0)  kw_init();
   mode=m;
}
//---------------------------------------------------------------------------
bool LexanBench :: isFunc (int sym) {
	return sym <= LEX_MAX_FUNC && sym >= LEX_MIN_FUNC;
}
//---------------------------------------------------------------------------
int LexanBench :: NextToken()
{
   int Exp=0,ExpSign=1;
   double DmsPos=0.1;
   int state=0;
   char c;
   F>>noskipws;
   while(true)
   {
      F>>c;
      if(c=='\n') rowcount++;
      switch(state)
      {
       case 0:
         if(!F) { return LEX_B_NULL; }
	 if (isspace(c)) break;
         if(c=='=') return LEX_B_ASSIGN;
         if(c=='(') return LEX_B_LPA;
         if(c==')') return LEX_B_RPA;
         if(c==',') return LEX_B_COMMA;
         if(isdigit(c))
         {
            state=5;
            Lex_AInt=c-'0';
            Lex_AReal=c-'0';
            break;
         }
            if(c=='#')
            {
               state=1;
               break;
            }
            if(isalpha(c) || c=='_')
            {
               state=14;
               Lex_AStr=c;
               break;
            }
            return LEX_B_ERROR;
         case 1:
//            if(!F) return LEX_B_ERROR;
            if(c=='\n') state=0;
            break;
         case 5:
            if(isdigit(c))
            {
               Lex_AInt*=10;
               Lex_AReal*=10;
               Lex_AInt+=c-'0';
               Lex_AReal+=c-'0';
               break;
            }
            if(c=='.')
            {
               state=6;
               break;
            }
            if(c=='e' || c=='E')
            {
               state=7;
               break;
            }
            if(c!='\n') F.unget();
            return LEX_B_INTEGER;
         case 6:
            if(isdigit(c))
            {
               Lex_AReal+=DmsPos*(c-'0');
               DmsPos*=.1;
               break;
            }
            if(c=='e' || c=='E')
            {
               state=7;
               break;
            }
            if(c!='\n') F.unget();
            return LEX_B_REAL;
         case 7:
            state=8;
            if(c=='+' || c=='-')
            {
               ExpSign=(c=='-')?-1:1;
               break;
            }
         case 8:
            if(isdigit(c))
            {
               state=9;
               Exp*=10;
               Exp+=c-'0';
               break;
            }
            return LEX_B_ERROR;
         case 9:
            if(isdigit(c))
            {
               Exp*=10;
               Exp+=c-'0';
               break;
            }
            if(c!='\n') F.unget();
            Lex_AReal*=pow(10.0,Exp*ExpSign);
            return LEX_B_REAL;
//         case 10:
//            if(c=='=') return LEX_B_ASSIGN;
//            if(c!='\n') F.unget();
//            return LEX_B_COLON;
         case 14:
            if(isalpha(c) || isdigit(c) || c=='_')
            {
               Lex_AStr+=c;
               break;
            }
            if(c!='\n') F.unget();
            for(list<pair<int,std::string> >::iterator i=keywords.begin();i!=keywords.end();i++)
               if(!stricmp(i->second.c_str(),Lex_AStr.c_str())) return i->first;
            return LEX_B_IDENT;
      }
   }  //end while
}
// -----------------------------------------------------------------------------
void LexanBench :: kw_init()
{
   keywords.clear();
   keywords.push_back(pair<int,std::string>(LEX_B_INPUT,"input"));
   keywords.push_back(pair<int,std::string>(LEX_B_OUTPUT,"output"));
   keywords.push_back(pair<int,std::string>(LEX_B_DFF,"dff"));
   keywords.push_back(pair<int,std::string>(LEX_B_NOT,"not"));
   keywords.push_back(pair<int,std::string>(LEX_B_AND,"and"));
   keywords.push_back(pair<int,std::string>(LEX_B_OR,"or"));
   keywords.push_back(pair<int,std::string>(LEX_B_NAND,"nand"));
   keywords.push_back(pair<int,std::string>(LEX_B_NOR,"nor"));
   keywords.push_back(pair<int,std::string>(LEX_B_XOR,"xor"));
   keywords.push_back(pair<int,std::string>(LEX_B_XNOR,"xnor"));
   keywords.push_back(pair<int,std::string>(LEX_B_BUFF,"buf"));
   keywords.push_back(pair<int,std::string>(LEX_B_BUFF,"buff"));
   symbols.clear();
   symbols.push_back(pair<int,std::string>(LEX_B_NULL, "(eof)"));
   symbols.push_back(pair<int,std::string>(LEX_B_ERROR,"(unknown)"));
   symbols.push_back(pair<int,std::string>(LEX_B_INTEGER,"int number"));
   symbols.push_back(pair<int,std::string>(LEX_B_REAL,"real number"));
   symbols.push_back(pair<int,std::string>(LEX_B_ASSIGN,"="));
   symbols.push_back(pair<int,std::string>(LEX_B_LPA,"("));
   symbols.push_back(pair<int,std::string>(LEX_B_RPA,")"));
   symbols.push_back(pair<int,std::string>(LEX_B_IDENT,"identifier"));
   symbols.push_back(pair<int,std::string>(LEX_B_COMMA,","));
   symbols.push_back(pair<int,std::string>(LEX_B_ANY_FUNC,"logic symbol"));
}
