//---------------------------------------------------------------------------
#include "lexan_kiss.h"
#include "config.h"
using namespace std;
//---------------------------------------------------------------------------
void LexanKiss::init(std::istream& istr, const std::string& filename) {
    Lexan::init(istr, filename);
    if( keywords.size() == 0 ) kw_init();
}
//---------------------------------------------------------------------------
int LexanKiss::NextToken() {
    int state=0;
    char c;

    (*in_) >> noskipws;
    while (true) {
        (*in_) >> c;
        if( c == '\n' ) rowcount_++;
        switch( state ) {
            case 0:
                if (!(*in_)) return LEX_KISS_NULL;
                if (isspace(c)) break;
                if (c == '*') { Lex_AStr = "*";  return LEX_KISS_STATE_DONTCARE; }
                if (c == '#') { state = 1; break;  }
                if (c == '.' ) { state = 2; Lex_AStr = c; break; }
                if (isdigit(c) ) { Lex_AStr = c;  Lex_AInt = c - '0'; state = 4;  break; }
                if (c == '-' ) { Lex_AStr = c; state = 3; break; }
                if (isalpha(c) || c == '_' ) { state = 5; Lex_AStr = c;  break; }
                break;

            case 1:
                if (c == '\n') state = 0;
                break;

            case 2:
                if (isalpha(c) ) { Lex_AStr += c; break; }
                if( c != '\n' ) in_->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_KISS_ERROR;

            case 3:
                if( c != '\n' && c != ' ' ) { Lex_AStr += c;  break; }
                else state = 0;
                return LEX_KISS_INFO;

            case 4:
                if (isdigit(c)) { Lex_AInt = Lex_AInt*10 + c - '0'; Lex_AStr += c; break; }
                if (c == '-') { Lex_AStr += c; state = 3; break; }
                if( c != '\n' ) in_->unget();
                return LEX_KISS_NUMB;

            case 5:
                if( isalpha(c) ||  c == '_' || isdigit(c) ) { Lex_AStr += c; break;  }
                if( c != '\n' ) in_->unget();
                return LEX_KISS_STATEID;
        }
    }
}
//---------------------------------------------------------------------------
void LexanKiss::kw_init()
{
  symbols.clear();
  symbols.push_back(std::pair<int,std::string>(LEX_KISS_NULL, "(eof)"));
  keywords.clear();
  keywords.push_back(std::pair<int,std::string>(LEX_KISS_INPUT,".i"));
  keywords.push_back(std::pair<int,std::string>(LEX_KISS_OUTPUT,".o"));
  keywords.push_back(std::pair<int,std::string>(LEX_KISS_PRODUCT,".p"));
  keywords.push_back(std::pair<int,std::string>(LEX_KISS_STATENUMBER,".s"));
  keywords.push_back(std::pair<int,std::string>(LEX_KISS_RESET,".r"));
}
//---------------------------------------------------------------------------
