#include "lexan_bench.h"
#include <math.h>
#include <stdexcept>
#include <ctype.h>
#include "hub/err.h"
#include "config.h"
//---------------------------------------------------------------------------
   void LexanBench :: init(std::istream& in,  const std::string& fi, int m) {
   Lexan :: init (in, fi);
   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;
   *in_ >> std::noskipws;
   while(true) {
      *in_ >> c;
      if(c=='\n') rowcount_++;
      switch(state) {
      case 0:
         if (! *in_) { 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 (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') in_->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') in_->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') in_->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') in_->unget();
         for(std::list <std::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(std::pair<int,std::string>(LEX_B_INPUT,"input"));
   keywords.push_back(std::pair<int,std::string>(LEX_B_OUTPUT,"output"));
   keywords.push_back(std::pair<int,std::string>(LEX_B_DFF,"dff"));
   keywords.push_back(std::pair<int,std::string>(LEX_B_NOT,"not"));
   keywords.push_back(std::pair<int,std::string>(LEX_B_AND,"and"));
   keywords.push_back(std::pair<int,std::string>(LEX_B_OR,"or"));
   keywords.push_back(std::pair<int,std::string>(LEX_B_NAND,"nand"));
   keywords.push_back(std::pair<int,std::string>(LEX_B_NOR,"nor"));
   keywords.push_back(std::pair<int,std::string>(LEX_B_XOR,"xor"));
   keywords.push_back(std::pair<int,std::string>(LEX_B_XNOR,"xnor"));
   keywords.push_back(std::pair<int,std::string>(LEX_B_BUFF,"buf"));
   keywords.push_back(std::pair<int,std::string>(LEX_B_BUFF,"buff"));
   symbols.clear();
   symbols.push_back(std::pair<int,std::string>(LEX_B_NULL, "(eof)"));
   symbols.push_back(std::pair<int,std::string>(LEX_B_ERROR,"(unknown)"));
   symbols.push_back(std::pair<int,std::string>(LEX_B_INTEGER,"int number"));
   symbols.push_back(std::pair<int,std::string>(LEX_B_REAL,"real number"));
   symbols.push_back(std::pair<int,std::string>(LEX_B_ASSIGN,"="));
   symbols.push_back(std::pair<int,std::string>(LEX_B_LPA,"("));
   symbols.push_back(std::pair<int,std::string>(LEX_B_RPA,")"));
   symbols.push_back(std::pair<int,std::string>(LEX_B_IDENT,"identifier"));
   symbols.push_back(std::pair<int,std::string>(LEX_B_COMMA,","));
   symbols.push_back(std::pair<int,std::string>(LEX_B_ANY_FUNC,"logic symbol"));
}
