%{
	#define YYDEBUG 1
	
	#include <math.h>
	#include <stdlib.h>
	#include <string.h>

	#define yyerror printf

	/* Funkcije za rad sa tabelom simbola koja je implementirana
		koriscenjem binarnog stabla */

	typedef struct _TREE
	{
		char* var;
		int val;
		struct _TREE *left, *right;
	} TREE;

	TREE* tree;

	void insert(TREE** tree, char* var, int val) 
	{
		int cmp;
		
		if (*tree == NULL)
		{	
			*tree = (TREE*)malloc(sizeof(TREE));
			(*tree)->left=(*tree)->right=NULL;
			(*tree)->var = var;
			(*tree)->val = val;
			return;
		}
		
		cmp = strcmp((*tree)->var, var);
		if (cmp < 0)
			insert(&((*tree)->left), var, val);
		else if (cmp > 0)
			insert(&((*tree)->right), var, val);
		else
			(*tree)->val = val;
		
	}
	
	int find(TREE* tree, char* var)
	{
		int cmp;

		if (tree == NULL)
			return 0;

		cmp = strcmp(tree->var, var);
		if (cmp < 0)
			return find(tree->left, var);
		else if (cmp > 0)
			return find(tree->right, var);
		else
			return tree->val;
	}

	void remove_tree(TREE* tree)
	{
		if (tree!=NULL)
		{	
			remove_tree(tree->left);
			remove_tree(tree->right);
			free(tree->var);
			free(tree);
		}		
	}

	/* Funkcija koja obrce string */
	void mirror(char s[], int n)
	{	int i, j;
		for (i=0, j=n-1; i<j; i++, j--)
		{
			char tmp = s[i];
			s[i]=s[j];
			s[j]=tmp;
		}
	}

	/* Funkcija konverzije dekadnog broja u osnovu 12 */
	void convert_10_to_12(int n, char s_12[])
	{
		int i = 0;

		do
		{	
			int mod = n%12;
			s_12[i++] = mod + ((0<=mod && mod<=9)?'0':'a'+10);
			n/=12;
		}
		while (n > 0);

		s_12[i] = '\0';
		
		mirror(s_12, i);
	}
	
	
%}

%token <str_value> ID
%token <int_value> NUM
%token ZEM DOM
%left '+' '-'
%left '*' '/'
%left '^' 

%type <int_value> expr

%union
{
	char* str_value;
	int   int_value;
};

%%

program : program stmt
	|
	;

stmt : 
	  ID '=' expr ';'
	{	insert(&tree, $1, $3);	}
 	| ZEM '(' ID ')' ';'
 	{	printf("$3 = \n\t0z%d\n",find(tree,$3));	} 	
 	| DOM '(' ID ')' ';'
 	{	char num_12[10];
		convert_10_to_12(find(tree,$3), num_12);
		printf("$3 = \n\t%s\n",num_12);
	} 	
 	;
 	
 	
	

expr : 	  expr '+' expr
	{	$$ = $1 + $3;	}
	| expr '-' expr
	{	$$ = $1 - $3;	}	
	| expr '*' expr
	{	$$ = $1 * $3;	}
	| expr '/' expr
	{  
		if ($3 == 0)
		{	
			printf("Divide by zero\n");
			$$ = 0;
		}
		else
			$$ = $1 / $3;
	}
	| expr '^' expr
	{ $$ = pow($1, $3); }
	| '(' expr ')'
	{ $$ = $2; }
	| NUM
	{ $$ = $1; }
	| ID
	{ $$ = find(tree, $1); }
	;
	
	

%%

main()
{
	yydebug = 0;
	yyparse();
	remove_tree(tree);
}
