//---------------------------------------------------------------------------
#ifdef _BCPLUSPLUS_
#pragma hdrstop
#endif
#include <stdexcept>
#include <ctype.h>
#include "lexan_edif.h"
#include <math.h>
#include <iostream>	//debug
#include "config.h"

//---------------------------------------------------------------------------
void LexanEdif::init(std::istream& in, const std::string& fi) {
   Lexan::init (in, fi);
   if (keywords.size() == 0)  kw_init();
   rowcount_=1;
}
//---------------------------------------------------------------------------
int LexanEdif::NextToken() {
    if(!qtoken.empty()) {
	    int k=qtoken.front();
	    qtoken.pop();
	    return k;
    }
    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_++; 
            if (rowcount_ % 1000 == 0)  std::cerr << ".." << rowcount_;
            if (rowcount_ % 10000 == 0) std::cerr << std::endl; 
        }
	    switch (state) {
	    // ------------------ symbol start -------------------------
	    case 0:
            if (!*in_) { std::cerr << std::endl; return LEX_E_NULL; }
		    if (isspace (c)) break;
		    if (c=='(') return LEX_E_LPA;
		    if (c==')') return LEX_E_RPA;
            if (c=='\"') { state=13; Lex_AStr = ""; break; }
		    if ( isdigit (c)) { state=5; Lex_AInt=c-'0'; Lex_AReal=c-'0'; break; }
            if (c=='#') { state=1; break; }
		if (isalpha (c) || c=='_' || c=='&') {
		    state=14;
		    Lex_AStr=c;
		    break;
		}
		return LEX_E_ERROR;
		
	    // ------------------- comment ---------------------------------	
        case 1:
//          if(!*in_) return LEX_E_ERROR;
            if(c=='\n') state=0;
            break;
	    // ------------------- number ---------------------------------    
        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_E_INTEGERTOKEN;

	    // ------------------ frac part of number ---------------------    
        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_E_REALTOKEN;

	    // ------------------ exponent sign ---------------------------   
        case 7:
            state=8;
            if (c=='+' || c=='-') { ExpSign=(c=='-')?-1:1; break; }

	    // ------------------ exponent start -------------------------
        case 8:
	        if (isdigit (c)) { state=9; Exp*=10; Exp+=c-'0'; break; }
	        return LEX_E_ERROR;

	    // ------------------ exponent ------------------------------    
        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_E_REALTOKEN;

	    // ----------------- string --------------------------------   
        case 13:
            if(c=='\"') return LEX_E_STRINGTOKEN;
            Lex_AStr += c;
            break;

	    // ----------------- ident --------------------------------
        case 14:
            if (isalpha(c) || isdigit(c) || c=='_' || c=='&') { Lex_AStr+=c; break; }
            if(c!='\n') in_->unget();
	        // -------------- keyword decode 
            for(std::list<std::pair<int,std::string> >::iterator 
		        i=keywords.begin();
		        i!=keywords.end();
		        i++) {
		        std::string s1 =i->second;
		        std::string s2 =Lex_AStr;
		        if(!stricmp(i->second.c_str(),Lex_AStr.c_str())) return i->first;
            }
            return LEX_E_IDENT;
      }
   }  //end while
}
// ------------------------------------------------------------------
int LexanEdif::LookAhead() {
    int k=NextToken();
    qtoken.push(k);
    return k;
}
// ------------------------------------------------------------------
void LexanEdif::kw_init() {
    keywords.clear();
    keywords.push_back (std::pair<int,std::string>(LEX_E_EDIF,"edif"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_NAME,"name"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_RENAME,"rename"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_STATUS,"status"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_EDIFVERSION,"edifVersion"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_EDIFLEVEL,"edifLevel"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_KEYWORDMAP,"keywordMap"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_KEYWORDLEVEL,"keywordLevel"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_WRITTEN,"written"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_TIMESTAMP,"timestamp"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_AUTHOR,"author"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_PROGRAM,"program"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_DATAORIGIN,"dataOrigin"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_VERSION,"version"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_LIBRARY,"library"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_TECHNOLOGY,"technology"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_NUMBERDEFINITION,"numberDefinition"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_CELL,"cell"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_CELLTYPE,"cellType"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_TIE,"tie"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_RIPPER,"ripper"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_GENERIC,"generic"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_VIEW,"view"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_NETLIST,"netList"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_VIEWTYPE,"viewType"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_INTERFACE,"interface"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_PORT,"port"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_ARRAY,"array"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_CONTENTS,"contents"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_INSTANCE,"instance"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_INSTANCEREF,"instanceRef"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_VIEWREF,"viewRef"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_CELLREF,"cellRef"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_LIBRARYREF,"libraryRef"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_NET,"net"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_JOINED,"joined"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_PORTREF,"portRef"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_MEMBER,"member"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_DESIGN,"design"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_PROPERTY,"property"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_STRING,"string"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_OWNER,"owner"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_INPUT,"INPUT"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_OUTPUT,"OUTPUT"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_INOUT,"INOUT"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_DIRECTION,"direction"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_VIEWLIST,"viewList"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_EXTERNAL,"external"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_SIMULATIONINFO,"simulationInfo"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_LOGICVALUE,"logicValue"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_BOOLEANMAP,"booleanMap"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_BOOLEANVALUE,"booleanValue"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_BOOLEAN,"boolean"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_INTEGER,"integer"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_FALSE,"false"));
    keywords.push_back (std::pair<int,std::string>(LEX_E_TRUE,"true"));
    symbols.clear();
    symbols.push_back (std::pair<int,std::string>(LEX_E_NULL, "(eof)"));
    symbols.push_back (std::pair<int,std::string>(LEX_E_ERROR,"(unknown)"));
    symbols.push_back (std::pair<int,std::string>(LEX_E_INTEGERTOKEN,"int number"));
    symbols.push_back (std::pair<int,std::string>(LEX_E_REALTOKEN,"real number"));
    symbols.push_back (std::pair<int,std::string>(LEX_E_LPA,"("));
    symbols.push_back (std::pair<int,std::string>(LEX_E_RPA,")"));
    symbols.push_back (std::pair<int,std::string>(LEX_E_IDENT,"identifier"));
}
//---------------------------------------------------------------------------
