#include "LexAn.h"


void LexAn::Error(char* errorMessage) // matoda vypisujici chybovou hlasku
{
        cout << "\n" << errorMessage << " , na radku : " << CisloRadku << endl;
        exit(1);
}


void LexAn::InitVstup(char *jmeno){  //inicializuje vstupu
    CisloRadku=1;
    Vstupf=fopen(jmeno,"r");
    if(!Vstupf){
      cout << "\n Chyba - vstupni soubor " <<jmeno << " nenalezen(pravdepodobne neexistuje)" << endl;
      exit(1);
    }
}


int LexAn::CtiZnak(){
  Aktualni=fgetc(Vstupf);
  if(Aktualni!=EOF){
    if(Aktualni=='\n' || Aktualni=='\r'){
      CisloRadku++;
      }
    return Aktualni;
  }
  return EOF;
}


void LexAn::CtiVstup(void) {
  Znak=CtiZnak();
  if(isalpha(Znak)){
     Vstup=Pismeno;
  }else{
      if(isdigit(Znak) ||  Znak=='-'){
        Vstup=Cislice;
      }else{
         if(Znak==' ' || Znak=='\n' || Znak=='\r' || Znak==EOF){
           Vstup=Konec;
         }else{
            Vstup=Jiny;
         }
     }
   }
}


void LexAn::readIK(){ // p\u00F8e\u00E8te identifikátor nebo klí\u00E8ové slovo
   id="";
   while(true){
   switch(Vstup){
      case Pismeno:
      case Cislice:
      case Jiny:
                   id=id+(char)Znak;
                   CtiVstup();
                   break;
      case Konec:
                 break;
      default:
              Error("Chyba - Identifikator/Klicove slovo obsahuje nepovoleny znak ");
              break;
   }
   if(Vstup==Konec) break;
   }
   if(Znak=='\n' || Znak=='\r') CisloRadku--;
    ungetc(Znak,Vstupf);
}



void LexAn::readNUMBER(){ // p\u00F8e\u00E8te identifikátor nebo klí\u00E8ové slovo
  bool minus=false;
    if(Znak=='-'){
      minus=true;
      CtiVstup();
    }

    if(isdigit(Znak)){
    Cislo=Znak - '0';
    symb=NUMB;
    CtiVstup();
    while(Vstup==Cislice){
        Cislo=10*Cislo+(Znak-'0');
        CtiVstup();
    }
     if(minus==true){
       Cislo=Cislo-(2*Cislo);
     }
    }else{
      Error("Chyba - cislo obsahuje nepovoleny znak");
    }

   if(isalpha(Znak)){
       Error("Chyba - Cislo obsahuje pismeno/a ");
    }
    if(Vstup==Konec){
      if(Znak=='\n' || Znak=='\r')CisloRadku--;
        ungetc(Znak,Vstupf);
   }
}



LexSymbol LexAn::KeyWord(){ // kontroluje jestli je identifikator v tabulce klíčových slov a pokud ano tak vraci klicove slovo - jinak identifikátor
   int i=0;
   while(TabKS[i].slovo && i<3){   /// musi tam bzt i<3 jinak je to chzba ?????????
    if(id==((string)TabKS[i].slovo))return TabKS[i].symb;
     else i++;
   }
   return IDENT;
}



void LexAn::vypis(){
 switch(symb){
    case IDENT:
               cout <<" " << id << " "; //<< endl;
               break;
    case kwC:
             cout <<"  " << id << " ";// << endl;
             break;
    case kwP:
             cout <<"  " << id << " " ;//<< endl;
             break;
    case kwCNF:
               cout <<"  " << id << " ";// << endl;
               break;
    case NUMB:
              cout <<"  " << Cislo << " ";// << endl;
              break;
    case EOL:
              cout <<"  EOL  " << endl;
              break;
    default:
           cout << "\n Znak :" << (char)Znak << endl;
           cout << "\n Cislo :" << Cislo << endl;
           cout << "\n Ident :" << id << endl;
 }
}





void LexAn::Element(void){ // podle precteneho cisla rozhodne jestli jde o identifikator/keyword, cislici,spec znak, chybu a podle toho se pak postupuje
   CtiVstup();

//   cout << " "<< Cislo << " " <<endl;

   while(Znak==' ' )CtiVstup();
   switch(Vstup){
      case Pismeno:
                   readIK();
                   symb=KeyWord();
                   break;
      case Cislice:
                   readNUMBER();
                   break;
      case Konec:
                 if(Znak==' '){
                   Element();
                 }else{
                   if(Znak=='\n' || Znak=='\r')symb=EOL;
                 }
                  break;
      case Jiny:
                readIK();
                symb=IDENT;
                break;
      default:
        Error("Chyba - Symbol neodpovida zadnemu lexikalnimu elementu : ");
   }
}



















