//---------------------------------------------------------------------------



#include "incl.h"
#include "CError.h"

Token PToken;

// * * * IMPLEMENTATIONEN * * *
double StrToDbl (std::string Str)
{
	unsigned int i = -1;
   double Faktor = 1.0;
   double Ergebnis = 0.0;

	while (1)
   {
   	i++;
      if (i == Str.length())
      {
      	return StrToInt (Str);
      }
   	if (DEZ)
      	break;
   }

   int DezPos = i;	//Zahl vor Komma umrechnen
   while (i)
   {
   	i--;
      if (Str[i] >='0' && Str[i] <= '9')
      {
   	   Ergebnis += Faktor * (Str[i] - '0');
         Faktor *= 10;
      }
   }

   i = DezPos;			//Zahl nach Komma umrechnen
   Faktor = 0.1;
   while (i+1 < Str.length())
   {
   	i++;
      if (Str[i] >='0' && Str[i] <= '9')
      {
         Ergebnis += Faktor * (Str[i] - '0');
         Faktor /= 10;
      }
   }
   return Ergebnis;
}

double StrToInt (std::string Str)
{
   double Faktor = 1.0;
   int i = Str.length();
   double Ergebnis = 0;
   while (i)
   {
   	i--;
      if (Str[i] >='0' && Str[i] <= '9')
      {
   	   Ergebnis += Faktor * (Str[i] - '0');
         Faktor *= 10;
      }
   }
   return Ergebnis;
}


double hoch (int term1,int term2)
{
	int temp =1;
	for (int i=0; i<term1; i++)
   {
   		temp *= term2;
   }
   return temp;
}

double div (double term1, double term2)
{
   if (term2 == 0)
      throw DivThrZero();
   return term1 / term2;
}

double hoch (double term1, double term2)
{
   return pow(term1,term2);
   //wer will kann sich hier eine eigene Routine schreiben!
}

double operation (std::string Str)
{
	unsigned int OpPos = 0;
   unsigned int i;
   double temp1, temp2;
	while (1)
   {
   	OpPos++;
      if (OpPos >= Str.length())
      {
         OpPos = Str.npos;
         throw Nicht();
      }
      i = OpPos;
      if (ISOP)   //darf man hier verwenden, da '(' usw ausgeschlossen ist
      	break;
   }
   
   std::string t1;
   t1.append(Str,0,OpPos);
   if (t1[0] != TOK)
      temp1 = StrToDbl(t1);
   else
      temp1 = PToken.GetToken(t1);

   std::string t2;
   t2.append(Str,OpPos+1,Str.length());
   if (t2[0] != TOK)
      temp2 = StrToDbl(t2);
   else
      temp2 = PToken.GetToken(t2);

   switch (Str[OpPos])
   {
   case '+':
   	return temp1+temp2;
   case '-':
   	return temp1-temp2;
   case '*':
   	return temp1*temp2;
   case '/':
   	return div (temp1,temp2);
   case '^':
   	return hoch(temp1,temp2);
   }
   return 0;
}

std::string parser(std::string & Str, char Op1, char Op2)
{

	unsigned int OpPos = 0;	//Position von Operator bestimmen
   unsigned int FiPos = 0;	//Erste Position von String
   unsigned LaPos = 0; //Letzte Position von String

   unsigned int i     = 0;

   unsigned x= Str.find_first_of(Op1);
   unsigned y= Str.find_first_of(Op2);

   OpPos =  x<y ? x : y;

   if (OpPos == Str.npos)
      throw Nicht();


   i = OpPos;
   while (!FiPos)
   {
   	i--;
      if (ISOP)
      	FiPos = i;
      if (i <= 0)
      {
         FiPos = -1;
         break;
      }
   }
   i = OpPos;
   while (!LaPos)
   {
   	i++;

      if (ISOP)
      	LaPos = i;
      if (i>=Str.length())
      {
         LaPos = Str.length();
         break;
      }
   }
   std::string t;

   t.append(Str,FiPos+1,LaPos-FiPos-1);
   std::string TokenName = PToken.NewToken(operation(t));
   Str.erase(FiPos+1,LaPos-FiPos-1);
   Str.insert(FiPos+1,TokenName);
   return t;
}

double operationparser(std::string & Str)
{
   MyChar op='^';
   std::string T;

   double erg = 0;

   while (1)
   {
      try
      {
         erg = operation(parser(Str,op.op1(),op.op2()));
      }
      catch (Nicht)
      {
         op++;
         if (op == '\0')
            break;
      }
   }
   return erg;
}

double klammerparser (std::string & Str)
{
   unsigned int FiPos = Str.length();
   unsigned int LaPos = Str.length();

   while (1)
   {
      FiPos = Str.find_last_of('(');
      LaPos = Str.find_first_of(')',FiPos);

      std::string t;
      if (FiPos == Str.npos || LaPos == Str.npos)
      {
         return operationparser(Str);
      }

      t.append(Str,FiPos+1,LaPos-FiPos-1);
      Str.erase(FiPos,LaPos-FiPos+1);

      operationparser(t);   //test
      Str.insert(FiPos,t);
   }
}



 

