#include "StdAfx.h"
#include "Executer.h"
using namespace std;
namespace Lex{
Executer::Executer(void)
{
}

Executer::~Executer(void)
{
}
void Executer::Execute(const wchar_t*inf ,const wchar_t * ouf)
{try{
	SyntaxAnalyser SA;
	SA.SAnalyse(inf,ouf,1);
	SA.SetCur(0);
for (int ind = 0; SA.GetCur()<SA.GetPolisSize(); ind++)
{
curr_lex=SA.getlex();
switch (curr_lex.get_type())
{
case 0:
	{// метку ПОЛИЗ - в стек
SType temp=SType(curr_lex.get_syn(),1);
S.push(temp);
break;}
case 2:
if (eq ("+"))
{SType temp2=S.pop();
SType temp1=S.pop();
// выполнили операцию сложения, результат - в стек
S.push(SType(temp1.getvalue()+temp2.getvalue(),temp1.gettype()*temp2.gettype()));
break;
};
if(eq ("-"))
{SType temp2=S.pop();
SType temp1=S.pop();
// выполнили операцию вычетания, результат - в стек
S.push( SType(temp1.getvalue()-temp2.getvalue(),temp1.gettype()*temp2.gettype()));
break;
};
if(eq ("*"))
{SType temp2=S.pop();
SType temp1=S.pop();
// выполнили операцию умножения, результат - в стек
S.push( SType(temp1.getvalue()*temp2.getvalue(),temp1.gettype()*temp2.gettype()));
break;
};
if(eq ("/"))
{SType temp2=S.pop();
SType temp1=S.pop();
int*k;
if(temp2.getvalue()==0)throw k;
// выполнили операцию деления, результат - в стек
S.push( SType(temp1.getvalue()/temp2.getvalue(),temp1.gettype()*temp2.gettype()));
break;
};
if(eq (">"))
{SType temp2=S.pop();
SType temp1=S.pop();
// выполнили операцию >, результат - в стек
S.push( SType(temp1.getvalue()>temp2.getvalue(),1));
break;
};
if(eq ("<"))
{SType temp2=S.pop();
SType temp1=S.pop();
// выполнили операцию <, результат - в стек
S.push( SType(temp1.getvalue()<temp2.getvalue(),1));
break;
};
if(eq (">="))
{SType temp2=S.pop();
SType temp1=S.pop();
// выполнили операцию >=, результат - в стек
S.push( SType(temp1.getvalue()>=temp2.getvalue(),1));
break;
};
if(eq ("<="))
{SType temp2=S.pop();
SType temp1=S.pop();
// выполнили операцию <=, результат - в стек
S.push( SType(temp1.getvalue()<=temp2.getvalue(),1));
break;
};
if(eq ("=="))
{SType temp2=S.pop();
SType temp1=S.pop();
// выполнили операцию ==, результат - в стек
S.push( SType(temp1.getvalue()==temp2.getvalue(),1));
break;
};
if(eq ("!="))
{SType temp2=S.pop();
SType temp1=S.pop();
// выполнили операцию !=, результат - в стек
S.push( SType(temp1.getvalue()!=temp2.getvalue(),1));
break;
};
if(eq ("and"))
{SType temp2=S.pop();
SType temp1=S.pop();
// выполнили операцию ==, результат - в стек
S.push( SType(temp1.getvalue()&&temp2.getvalue(),1));
break;
};
if(eq ("or"))
{SType temp2=S.pop();
SType temp1=S.pop();
// выполнили операцию ==, результат - в стек
S.push( SType(temp1.getvalue()||temp2.getvalue(),1));
break;
};
if (eq ("not"))
{
	SType temp=S.pop();
	S.push (SType(!(temp.getvalue()),temp.gettype()));
	break;
}
if (eq ("-$"))
{
	SType temp=S.pop();
	S.push (SType(-(temp.getvalue()),temp.gettype()));
	break;
}
if (eq ("!"))
{
// интерпретация будет продолжена с j-го элемента
// ПОЛИЗа
SType temp=S.pop();
SA.SetCur(int(temp.getvalue()));
break;
}
if (eq ("!F"))
{
SType j=S.pop();
SType arg=S.pop();
if (!int(arg.getvalue()))
// если значение arg ложно, то интерпретация будет
// продолжена с j -го элемента ПОЛИЗа, иначе порядок
// не изменится
SA.SetCur(int(j.getvalue()));
break;
}
if (eq ("!F'"))
{
SType j=S.pop();
SType arg=S.pop();
if (!int(arg.getvalue()))
// если значение arg ложно, то интерпретация будет
// продолжена с j -го элемента ПОЛИЗа, иначе порядок
// не изменится
SA.SetCur(int(j.getvalue()));
S.push(arg);
break;
}
if (eq ("="))
{
SType temp = S.pop();
SType arg=S.pop();
if(!arg.gettype())SA.ids[int(arg.getvalue())].SetValue(temp.getvalue());//адрес переменной-ее номер в массиве ids
else SA.ids[int(arg.getvalue())].SetValue(int(temp.getvalue()));
break;
};
if (eq ("=$"))
{
SType temp = S.pop();
SType arg=S.pop();
if(!arg.gettype())SA.ids[int(arg.getvalue())].SetValue(temp.getvalue());//адрес переменной-ее номер в массиве ids
else SA.ids[int(arg.getvalue())].SetValue(int(temp.getvalue()));
S.push(temp);
break;
};
if (eq ("R"))
{
// "R" - обозначение операции ввода
//ip = (*int) ipop();
//scanf("%d", ip);
	char Buf[80];
	this->NewLine();
	char *s = this->Input(Buf, 80);
	SType temp=S.pop();
	int * t;
	if(!(atoi(Buf))&&(!(atof(Buf)))&&strcmp(Buf,"0")!=0) throw t;
	if(!temp.gettype())SA.ids[int(temp.getvalue())].SetValue(atof(Buf));
	else SA.ids[int(temp.getvalue())].SetValue(atoi(Buf));
	//sscanf(Buf, "%d", &iVal);
break;
};
if (eq ("W"))
{
	char buf[80];
	for(int ind=0;ind<80;ind++)buf[ind]='\0';
	ostrstream s1 (buf,80);
// "W" - обозначение операции вывода

	// arg = ipop();
	SType temp=S.pop();

	//int arg = 777;
	//char Buf[80];
	//sprintf(Buf,"%d", arg);
	if(temp.gettype()<0){
	this->NewLine();
	strcpy(buf,temp.GETSTR());
	strcpy(buf,buf+1);
	buf[strlen(buf)-1]='\0';
	this->Write(buf);}
	else 
	{
		this->NewLine();
		if(temp.gettype()==0)
		{
			s1<<temp.getvalue();
		}
		else {
			s1<<int(temp.getvalue());
		}
		this->Write(buf);
	}
	
break;
}
case 3:
// значение константы - в стек
	if(SA.atoi1(curr_lex.get_value()))S.push(SType(atoi(curr_lex.get_value()),1));
	else if(strcmp(curr_lex.get_value(),"0")==0)S.push(SType(atoi(curr_lex.get_value()),1));
	else if(SA.atof1(curr_lex.get_value()))S.push(SType(SA.atof1(curr_lex.get_value()),0));
	else {S.push(SType(-1,-1,curr_lex.get_value()));}// придумать для строковых констант
break;
case 4:{
// значение переменной - в стек
int k=SA.FindID(curr_lex.get_value(),SA.ids);//todo FindID ищет в таблице новых идентефикаторов такой ид и возвращает его номер
if(strcmp(SA.ids[k].gettype(),"real")==0)S.push(SType(SA.ids[k].getvalue(),0));
else S.push(SType(SA.ids[k].getvalue(),1));
break;}
case 5:
	{
// адрес переменной - в стек
int k=SA.FindID(curr_lex.get_value(),SA.ids);
if(strcmp(SA.ids[k].gettype(),"real")==0)S.push(SType(k,0));
else S.push(SType(k,1));
break;}
} // конец switch
} // конец for
}
catch(int){this->Write("Empty file");}
catch(int*){this->NewLine();this->Write("Error");}
catch(char*){this->Write("Lexical Error");}
catch(char){this->Write("Syntax Error");}
catch(Record id){this->Write("Syntax Error");}
catch(...){this->Write("Execution Error");}
}
}