#include "stdafx.h"
#include "SyntaxAnalyser.h"
namespace Lex{
SyntaxAnalyser::SyntaxAnalyser()
{
}
SyntaxAnalyser::~SyntaxAnalyser()
{
}
void SyntaxAnalyser::checkid(void)
{
	int i=FindID(curr_lex.get_value(),ids);
	if(i>=0){if(ids[i].Declared()) S.push(ids[i].gettype());
	else ERR();}
	else 
	{
	char*type=new char[5];
	for(int ind=0;ind<5;ind++)type[ind]='\0';
	if(atoi1(curr_lex.get_value())||strcmp(curr_lex.get_value(),"0")==0)
	{
		strcpy(type,"int");
		S.push(type);
	}
	else {strcpy(type,"real");S.push(type);}
	}
}
char* SyntaxAnalyser::gettype(char*op,char*t1,char*t2)
{
	char* buf= new char [5];
	for(int ind=0;ind<5;ind++)buf[ind]='\0';
	if((strcmp(op,"and")==0)||(strcmp(op,"or")==0))
	{
		if(strcmp(t1,"real")==0||strcmp(t2,"real")==0)
		{
			strcpy(buf,"no"); return buf;
		}
		else strcpy(buf,"int"); return buf;
	}
	if((strcmp(op,"+"))==0||strcmp(op,"-")==0||strcmp(op,"*")==0||strcmp(op,"/")==0)
	{
		if(strcmp(t1,"real")==0||strcmp(t2,"real")==0)
		{
			strcpy(buf,"real"); return buf;
		}
		else strcpy(buf,"int"); return buf;
	}
	if(strcmp(op,">")==0||strcmp(op,"<")==0||strcmp(op,">=")==0||strcmp(op,"<=")==0||strcmp(op,"==")==0||strcmp(op,"!=")==0)
	{
		strcpy(buf,"int"); return buf;
	}
	if(strcmp(op,"=")==0)
	{
		if(strcmp(t1,"int")==0&&strcmp(t2,"int")==0){strcpy(buf,"int"); return buf;}
		else if (strcmp(t1,"real")==0&&strcmp(t2,"real")==0){strcpy(buf,"real"); return buf;}
		else if(strcmp(t1,"int")==0&&strcmp(t2,"real")==0){strcpy(buf,"int"); return buf;}
		else if(strcmp(t1,"real")==0&&strcmp(t2,"int")==0){strcpy(buf,"real"); return buf;}
	}
}
void SyntaxAnalyser::checkop(void)
{
	char*op;
	char*t1;char*t2;
	char*res;
	t2=S.pop();
	op=S.pop();
	t1=S.pop();
	res=gettype(op,t1,t2);
	if(strcmp(res,"no"))S.push(res);
	else ERR1();

}
void SyntaxAnalyser::checknot(void)
{
	if(strcmp(S.pop(),"int"))ERR();
	else S.push("int");
}
void SyntaxAnalyser::InsertBr(int br,int to)
{
	for(int ind=br;ind<Polis.size();ind++)
	{
		if(Polis[ind].get_syn()<0)Polis[ind].put_syn(to);
	}
}
void SyntaxAnalyser::InsertL(int l,int to)
{
	Polis[l].put_syn(to);
}
int SyntaxAnalyser::eq(char* s)
{
	if(strcmp(s,(curr_lex.get_value()))==0)return 1;
	else return 0;
}
Lexeme SyntaxAnalyser::getlex(vector <Lexeme> t)
{
if(t.size()!=0)return(t[cur++]);
else throw 0;
}
Lexeme SyntaxAnalyser::looklex(vector <Lexeme> t)
{
return(t[cur]);
}
int SyntaxAnalyser::num()//константа?
{
	if(((curr_lex.type==3)&&(atof(curr_lex.value)))||((curr_lex.type==3)&&(strcmp(curr_lex.value,"0")==0)))return 1;
	else return 0;
}

int SyntaxAnalyser::id()//идентефикатор?
{
	if(curr_lex.type==4)return 1;
	else return 0;
}
int SyntaxAnalyser::str()//строка?
{
	if((curr_lex.type==3)&&(!atof(curr_lex.value))&&(strcmp(curr_lex.value,"0")!=0))return 1;
	else return 0;
}
int SyntaxAnalyser::SAnalyse(const wchar_t*inf ,const wchar_t * ouf,int debug)
{
	ofstream fout(ouf);
	if(!fout){return(1);}
	try
	{
		Program(inf,ouf);
		CheckIfDeclared();
	//	fout<<"Нет синтаксических ошибок"<<endl;
		int ind=0;
		while(ind<Polis.size())
		{
			fout<<ind<<": "<<Polis[ind]<<endl;
			ind++;
		}
	}
	catch(int t){fout<<"Пустой файл"<<endl;if(debug)throw;}
	catch(Record id){fout<<"Переменная "<<id.getname()<<" не определена"<<endl;if(debug)throw;}
	catch(char* t){fout<<"Лексическая ошибка"<<endl;if(debug)throw;}
	catch(char t){if(t=='d')fout<<"Повторное определение переменной "<<curr_lex.get_value()<<endl;
	else if(t=='f')fout<<"Неправильный формат числовой константы "<<curr_lex.get_value()<<endl;
	else if(t=='m')fout<<"Несовместимость типов"<<endl;
	else fout<<"Синтаксическая ошибка "<<curr_lex.get_value()<<endl;
	if(debug)throw;
	}
	return(0);
}
void SyntaxAnalyser::Program(const wchar_t*inf ,const wchar_t * ouf)
{
	free=0;
	cur=0;
	LexAnalyser LA;
	LA.Analyze(inf,ouf,0);
	full(LA.ID);
	curr_lex=getlex(LA.LexArray);
	if(eq("program")) curr_lex=getlex(LA.LexArray);
	else ERR();
	if(eq("{")) curr_lex=getlex(LA.LexArray);
	else ERR();
	if(eq("int")||eq("real"))Discriptions(LA,LA.LexArray,inf,ouf);//описания переменных
	Operators(LA.LexArray);//операторы
	if(!eq("}")) ERR();
}
void SyntaxAnalyser::Discriptions(LexAnalyser LA,vector <Lexeme> t,const wchar_t*inf ,const wchar_t * ouf)//описания переменных
{
	char TempType[5];//временное хранилище текущегоо рассматриваемого типа
	for(int i=0;i<5;i++)TempType[i]='\0';

	if(!(eq("int")||(eq("real")))) ERR();
	else 
	{
		if(eq("int"))strcpy_s(TempType,"int");//тип int
		if(eq("real"))strcpy_s(TempType,"real");//тип real
		curr_lex=getlex(t);
	}
	int curr_id=0;
	if(!id()) ERR();
	else 
	{
		curr_id=AddTypeAndDeclaration(TempType);//функция которая проверяет на повторное описание и заполняет тип
		curr_lex=getlex(t);
	}
	if(eq("=")){
			curr_lex=getlex(t);//идентефикатор=константа
			float constant=1;
			if(eq("-")){curr_lex=getlex(t);//знак перед константой
			constant*=-1;}
			if(num())
			{
				if(strcmp(ids[curr_id].gettype(),"int")==0)constant*=atoi2(curr_lex.get_value());
				else constant*=atof1(curr_lex.get_value());
				curr_lex=getlex(t);
			}
			else ERR();
			ids[curr_id].SetValue(constant);
		}
	while(eq(","))
	{
		curr_lex=getlex(t);
		if(!id()) ERR();
		else 
		{
			AddTypeAndDeclaration(TempType);//функция которая проверяет на повторное описание и заполняет тип
			curr_lex=getlex(t);
		}
		if(eq("="))
		{
			curr_lex=getlex(t);//идентефикатор=константа
			if(eq("+")||eq("-"))curr_lex=getlex(t);//знак перед константой
			if(num())curr_lex=getlex(t);
			else ERR();
		}
	}

	if(!eq(";")) ERR();
	else
	{
		curr_lex=getlex(t);
		if(eq("int")||eq("real"))Discriptions(LA,t,inf ,ouf);
	}
}
void SyntaxAnalyser::Operators(vector<Lexeme> t,int kub,int *ub)
{
	while(eq("if")||eq("do")||eq("while")||eq("real")||eq("read")||eq("write")||eq("break")||id()||eq("-")||eq("{"))Operator(t,kub,ub);
}
void SyntaxAnalyser::Operator(vector <Lexeme> t,int kub,int *ub)
{
	if(eq("{"))
	{
		curr_lex=getlex(t);
		Operators(t,kub,ub);
		if(eq("}"))curr_lex=getlex(t);
		else ERR();
	}
	else if(eq("if"))
	{
		curr_lex=getlex(t);
		if(eq("("))curr_lex=getlex(t);
		else ERR();
		S.clear();
		Virageniye(t);
		if(eq(")"))curr_lex=getlex(t);
		else ERR();
		int a;
		a=Polis.size();//сюда вставим p2
		put_lex(make_op("!F"));
		Operator(t,kub,ub);
		int b;
		b=Polis.size();//сюза вставим p3
		put_lex(make_op("!"));
		put_lex0(Polis.size(),a);//переход если выражение ложь делаем +2 с учетом что встявляем 2 элемента перехода
		if(eq("else"))
		{
			curr_lex=getlex(t);
			//put_lex(temp2);
		    //put_lex(temp1);
			Operator(t,kub,ub);
		}
		put_lex0(Polis.size(),b+1);//переход если выражение правда
	}
	else if(eq("do"))
	{
		int br=Polis.size();
		curr_lex=getlex(t);
	//	int*k;
	//	int m=0;
	//	k=&m;
		int temp=Polis.size();
	//	Operator(t,true,k);
		Operator(t,true);
		if(eq("while"))curr_lex=getlex(t);
		else ERR();
		if(eq("("))curr_lex=getlex(t);
		else ERR();
		S.clear();
		Virageniye(t);
		if(eq(")"))curr_lex=getlex(t);
		else ERR();
		if(eq(";"))curr_lex=getlex(t);
		else ERR();
		int a;
		a=Polis.size();
		put_lex(make_op("!F"));
		int b;
		b=Polis.size();
		put_lex(make_op("!"));
		put_lex0(temp,b);
		put_lex0(Polis.size(),a);
		InsertBr(br,Polis.size());//везде где встретился break вставляет адрес конца цикла
	//	if(m){put_lex0(Polis.size(),it);

	}
	else if(eq("while"))
	{
		int br=Polis.size();
		curr_lex=getlex(t);
		if(eq("("))curr_lex=getlex(t);
		else ERR();
		int temp=Polis.size();//сюда переход по p1 с учетом вставки еще 1 перехода
		{S.clear();Virageniye(t);}
		int a;
		a=Polis.size();
		if(eq(")"))curr_lex=getlex(t);
		else ERR();
		//int*k;//
		//int m=0;//для break
		//k=&m;//
		put_lex(make_op("!F"));
		//Operator(t,true,k);
		Operator(t,true);
		int b;
		b=Polis.size();
		put_lex0(temp,b);//переход в начало цикла
		put_lex(make_op("!"));
		put_lex0(Polis.size(),a);
		//if(m)put_lex0(Polis.size(),it);
		InsertBr(br,Polis.size());//везде где встретился break вставляет адрес конца цикла

	}
	else if(eq("read"))
	{
		curr_lex=getlex(t);
		if(eq("("))curr_lex=getlex(t);
		else ERR();
		if(id())
		{
			put_lex5(curr_lex);
			curr_lex=getlex(t);
			put_lex(make_op("R"));
		}
		else ERR();
		if(eq(")"))curr_lex=getlex(t);
		else ERR();
		if(eq(";"))curr_lex=getlex(t);
		else ERR();
	}
	else if(eq("write"))
	{
		curr_lex=getlex(t);
		if(eq("("))curr_lex=getlex(t);
		else ERR();
		if(str()){put_lex(curr_lex);put_lex(make_op("W"));curr_lex=getlex(t);}
		else {S.clear();Virageniye(t);put_lex(make_op("W"));}
		while(eq(","))
		{
			curr_lex=getlex(t);
			if(str()){put_lex(curr_lex);curr_lex=getlex(t);}
			else {S.clear();Virageniye(t);}
			put_lex(make_op("W"));
		}
		if(eq(")"))curr_lex=getlex(t);
		else ERR();
		if(eq(";"))curr_lex=getlex(t);
		else ERR();
	}
	else if(eq("break"))//хз как реализовывать на самом деле- пока не работает
	{
		if(kub)
		{
			curr_lex=getlex(t);
			if(eq(";"))curr_lex=getlex(t);
			else ERR();
			Lexeme temp=Lexeme(0,0,-1);
			put_lex(temp);
			put_lex(make_op("!"));
			//if(ub!=NULL)*ub=true;
			//it=Polis.size();

		}
		else ERR();
	}
	else
	{
		S.clear();
		Virageniye(t);
		if(!eq(";"))ERR();
		else curr_lex=getlex(t);
	}
}
void SyntaxAnalyser::Virageniye(vector <Lexeme> t)
{

	if(id())
	{checkid();
		Lexeme temp=curr_lex;
		curr_lex=looklex(t);
		if(eq("="))
		{
			S.push(curr_lex.get_value());
			put_lex5(temp);
			curr_lex=getlex(t);
			curr_lex=getlex(t);
			Virageniye(t);
			checkop();
			Lexeme temp=curr_lex;
			if(eq(";")){put_lex(make_op("="));}
			//else if(eq(")"))
			//{
			//	put_lex(make_op("=$"));
			//}
			else put_lex(make_op("=$"));
			curr_lex=temp;
		}
		else 
		{
			curr_lex=temp;
			S.pop();//не то положили
			LogOR(t);
		}
	}
	else LogOR(t);
}
void SyntaxAnalyser::LogOR(vector <Lexeme> t)
{
LogAND(t);
while(eq("or"))
{	S.push(curr_lex.get_value());
	put_lex0(Polis.size()+2,Polis.size());
	put_lex(make_op("!F'"));
	int temp2=Polis.size();
	put_lex0(-1,Polis.size());
	put_lex(make_op("!"));
	Lexeme temp_lex=curr_lex;
	curr_lex=getlex(t);
	LogAND(t);
	InsertL(temp2,Polis.size()+2);
	checkop();
	put_lex(temp_lex);
}
}
void SyntaxAnalyser::LogAND(vector <Lexeme> t)
{
	Compare(t);
	while(eq("and"))
	{
		S.push(curr_lex.get_value());
		int temp2=Polis.size();
		put_lex0(-1,Polis.size());
		put_lex(make_op("!F'"));
		Lexeme temp_lex=curr_lex;
		curr_lex=getlex(t);
		Compare(t);
		InsertL(temp2,Polis.size()+2);
		checkop();
		put_lex(temp_lex);
	}
}
void SyntaxAnalyser::Compare(vector <Lexeme> t)
{
	PlusMinus(t);
	while(eq("<=")||eq(">=")||eq("<")||eq(">")||eq("==")||eq("!="))
	{
		S.push(curr_lex.get_value());
		Lexeme temp_lex=curr_lex;
		curr_lex=getlex(t);
		PlusMinus(t);
		checkop();
		put_lex(temp_lex);
	}
}

void SyntaxAnalyser::PlusMinus(vector <Lexeme> t)
{
	MulDiv(t);
	while(eq("+")||eq("-"))
	{
		S.push(curr_lex.get_value());
		Lexeme temp_lex=curr_lex;
		curr_lex=getlex(t);
		MulDiv(t);
		checkop();
		put_lex(temp_lex);
	}
}

void SyntaxAnalyser::MulDiv(vector <Lexeme> t)
{
	Final(t);
	while(eq("*")||eq("/"))
	{
		S.push(curr_lex.get_value());
		Lexeme temp_lex=curr_lex;
		curr_lex=getlex(t);
		Final(t);
		checkop();
		put_lex(temp_lex);
	}
}

void SyntaxAnalyser::Final(vector <Lexeme> t)
{
	if(eq("not")||eq("-"))
	{
		if(eq("not"))
		{
			Lexeme temp_lex=curr_lex;
			curr_lex=getlex(t);
			Virageniye(t);
			checknot();
			put_lex(temp_lex);
		}
		else 
		{
			Lexeme temp_lex=curr_lex;
			curr_lex=getlex(t);
			Virageniye(t);
			put_lex(make_op("-$"));
		}
	}
	else if(eq("("))
	{
		curr_lex=getlex(t);

		Virageniye(t);
		if(eq(")"))
		{
			curr_lex=getlex(t);
		}
		else ERR();
	}
	else if(id()||num()){checkid();put_lex(curr_lex);curr_lex=getlex(t);}
	else ERR();
}


void SyntaxAnalyser::ERR()
{
	throw 'e';
}
void SyntaxAnalyser::ERR1()
{
	throw 'm';
}

void SyntaxAnalyser::full(vector<char*>ID)
{
	size_t ind=0;
	while(ind<ID.size())
	{
		Record a;
		a.zero();
		a.putname(ID[ind]);
		ids.push_back(a);
		ind++;
	}
}
int SyntaxAnalyser::AddTypeAndDeclaration(char* TempType)
{
	for(unsigned int ind=0;ind<ids.size();ind++){
		if(strcmp(ids[ind].NAME(),(curr_lex.get_value()))==0)//нашли нашу лексемму в таблице
		{
			if(ids[ind].Declared())throw'd';//повторное объявление - ошибка
			else {ids[ind].Declare();//объявляем
			ids[ind].SetType(TempType);//устанавливваем тип
			}
			return ind;
		}
	}
	return 0;
}


}

