//---------------------------------------------------------------------------
#include "lexan_pla.h"
#include "config.h"
//---------------------------------------------------------------------------
LexanPla::LexanPla() {
  kw_init();
}
//---------------------------------------------------------------------------
void LexanPla::init(std::istream& istr, const std::string& input_file) {
  Lexan::init(istr, input_file);
  if( keywords.size() == 0 ) kw_init();
}
//---------------------------------------------------------------------------
void LexanPla::kw_init()
{
  symbols.clear();
  symbols.push_back(std::pair<int,std::string>(LEX_PLA_NULL, "(eof)"));
  keywords.clear();
  keywords.push_back(std::pair<int,std::string>(LEX_PLA_INPUT,".i"));
  keywords.push_back(std::pair<int,std::string>(LEX_PLA_OUTPUT,".o"));
  keywords.push_back(std::pair<int,std::string>(LEX_PLA_TYPE,".type"));
  keywords.push_back(std::pair<int,std::string>(LEX_PLA_PHASE,".phase"));
  keywords.push_back(std::pair<int,std::string>(LEX_PLA_PAIR,".pair"));
  keywords.push_back(std::pair<int,std::string>(LEX_PLA_KISS,".kiss"));
  keywords.push_back(std::pair<int,std::string>(LEX_PLA_P,".p"));
  keywords.push_back(std::pair<int,std::string>(LEX_PLA_E,".e"));
  keywords.push_back(std::pair<int,std::string>(LEX_PLA_E,".end"));
  keywords.push_back(std::pair<int,std::string>(LEX_PLA_INPUTNAMES,".ilb"));
  keywords.push_back(std::pair<int,std::string>(LEX_PLA_OUTPUTNAMES,".ob"));
}
//---------------------------------------------------------------------------
int LexanPla::NextToken() {
    int state=0;
    char c;
    (*in_) >> noskipws;
    while(true) {
        (*in_) >> c;
        if( c == '\n' ) rowcount_++;
        switch( state ) {
        case 0:
            if ( !(*in_) ) return LEX_PLA_NULL;
            if ( isspace(c) ) break;
            if ( c == '#' ) { state = 1; break; }
            if ( c == '.' ) { Lex_AStr = c; state = 2; break; }
            if ( isdigit(c) ) {Lex_AInt = c - '0'; Lex_AStr = c; state = 3; break; }
            if( isalpha(c) || c == '_' ) { Lex_AStr = c; state = 4; break; }
            if( c == '-' || c == '~' ) { Lex_AStr = c; state = 5; 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_PLA_ERROR;

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

        case 4:
            if( isalpha(c) || isdigit(c) || c == '_' ) { Lex_AStr += c; break;  }
            if( c != '\n' ) in_->unget();
            return LEX_PLA_IDENT;

        case 5:
            if( isdigit(c) || c == '-' || c == '~' || c == ' ' || c == '|' ) {
                Lex_AStr += c;
                break;
            }
            if( c != '\n' ) in_->unget();
            return LEX_PLA_MATRIXROW;
        }
    }
}
//---------------------------------------------------------------------------
