#include "Parser.h"
#include "List.h"

typedef enum {lt_none, lt_plus, lt_minus, lt_var, lt_number,
	lt_mul, lt_div, lt_end, lt_inc, lt_open, lt_close, lt_unary} LexemType;


LexemType lexem;
int number;
char var;
char cur;

List vars;

void onError()
{
 printf("Bad expression.");
 getch();
 exit(0);
}


bool isDigit(char c)
{
	return (c >= '0' && c <= '9');
}

bool isLetter(char c)
{
	return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
}

unsigned addVariable(char var)
{
	ListNode *l = vars.first;
	unsigned id = vars.size;
	while (l != NULL)
	{
		id--;
		if (l->value == var) return id;
		l = l->next;		
	}
	
	ListPushFront(&vars, var);
	return vars.size - 1;
}

void nextChar()
{
	cur = getchar();
}

void nextLexem()
{
	bool noSpliter;
	if (lexem != lt_number) nextChar();
	
	noSpliter = cur != ' ';
	while (cur == ' ') nextChar();
	
	if (cur == '.')
	{
		lexem = lt_end;
		return;
	}
	
	if (isDigit(cur))
	{
		number = 0;
		lexem = lt_number;
		while (isDigit(cur))
		{
			number = number*10 + (int)cur - (int)'0';
			nextChar();
		}
		return;
	}
	
	if (isLetter(cur))
	{
		lexem = lt_var;
		var = cur;
		return;
	}
	
	switch (cur)
	{
		case '+':
		{
			if ((lexem == lt_plus || lexem == lt_inc) && noSpliter) lexem = lt_inc;
				else lexem = lt_plus;
			break;
		}
		
		case '-':
		{
			if (lexem == lt_none || lexem == lt_open) lexem = lt_unary;
				else lexem = lt_minus;
			break;
		}
		
		case '*': lexem = lt_mul; break;
		case '/': lexem = lt_div; break;
		case '(': lexem = lt_open; break;
		case ')': lexem = lt_close; break;
		
		default: onError();
	}
}

Tree createExpression(bool read);

Tree createMultipler(bool read)
{
	Tree r;
	if (read) nextLexem();
	
	switch (lexem)
	{
		case lt_number:
		{						
			r = ValueNode(nt_number, number);
			nextLexem();
			return r;
		}
		
		case lt_var:
		{			
			r = ValueNode(nt_var, addVariable(var));
			nextLexem();
			return r;
		}
		
		case lt_open:
		{		
			r = createExpression(true);
			if (lexem != lt_close) onError();
			nextLexem();
			return r;
		}
		
		case lt_plus: case lt_inc:
		{					
			nextLexem();
			if (lexem != lt_inc) onError();
			r = ValueNode(nt_operation, OPERATION_INC);
			nextLexem();
			if (lexem != lt_var) onError();
			r->left = ValueNode(nt_var, addVariable(var));
			nextLexem();
			return r;
		}
		
		case lt_unary:
		{
			r = CreateNode(nt_operation, OPERATION_MINUS, NULL, createMultipler(true));
			return r;
		}
		
		default: onError();
	}
	
	return NULL;
}

Tree createCompose(bool read)
{
	Tree l, u;
	if (read) nextLexem();
	l = createMultipler(false);
	while (lexem == lt_mul || lexem == lt_div)
	{
		u = ValueNode(nt_operation, (lexem == lt_mul) ? OPERATION_MUL : OPERATION_DIV);
		u->left = l;
		u->right = createMultipler(true);
		l = u;		
	}
	
	return l;
}

Tree createExpression(bool read)
{
	Tree l, u;
	if (read) nextLexem();
	l = createCompose(false);
	while (lexem == lt_plus || lexem == lt_minus)
	{
		u = ValueNode(nt_operation, (lexem == lt_plus) ? OPERATION_PLUS : OPERATION_MINUS);
		u->left = l;
		u->right = createCompose(true);
		l = u;		
	}
	
	return l;
}

TExpress GetExpression()
{	
	TExpress result;
	ListNode *node;
	int i;
	
	vars = ListNew();	
	lexem = lt_none;
	result.tree = createExpression(true);
	if (lexem != lt_end) onError();
	result.count = vars.size;
	result.vars = (char*)calloc(vars.size, sizeof(char));
	for (node = vars.first, i = vars.size - 1; node != NULL; node = node->next, i--)
		result.vars[i] = node->value;
		
	return result;
}
