%{

#define YYDEBUG 1

#include "funkcija.h"
#include <map>
#include <iostream>
using namespace std;

extern int yylex();

map<string, Funkcija*> vars;

void yyerror(char* s)
{
	cerr<<s<<endl;
}

%}

%union {
	Funkcija* fun_attr;
	float	num_attr;
	char*   str_attr;
}

%left '+'
%left '*'
%token SIN COS EXP
%token<num_attr> NUM
%token<str_attr> ID
%type<fun_attr> expr


%%
program : program linija '\n'
	|
	;

linija : ID '=' expr 
	{
		map<string, Funkcija*>::iterator i = vars.find($1);
		if (i != vars.end())
			delete i->second;
			
		vars[$1] = $3;

		$3->print(cout);
		cout<<endl;
		
	}
	| ID '[' NUM ']'
	{
		map<string, Funkcija*>::iterator i = vars.find($1);
		if (i == vars.end())
		{
			cerr<<"Unknown function : "<<$1<<endl;
		}
		else
		{
			cout<<i->second->vrednost($3)<<endl;
		}
	}
	| ID '\''
	{
		map<string, Funkcija*>::iterator i = vars.find($1);
		if (i == vars.end())
		{
			cerr<<"Unknown function : "<<$1<<endl;
		}
		else
		{
			Funkcija* izvod = i->second->izvod();
			izvod->print(cout);
			cout<<endl;
			delete izvod;
		}
	}
	| ID
	{
		map<string, Funkcija*>::iterator i = vars.find($1);
		if (i == vars.end())
		{
			cerr<<"Unknown function : "<<$1<<endl;
		}
		else
		{
			i->second->print(cout);
			cout<<endl;
		}
	}
	|
	;

expr : 'x' 
	{$$ = new IdentickaFunkcija();}
	| NUM 
	{ $$ = new KonstantnaFunkcija($1); }
	| expr '+' expr
	{ $$ = new Plus($1, $3); }
	| expr '*' expr
	{ $$ = new Puta($1, $3); }
	| SIN '(' expr ')'
	{ $$ = new Sin($3); }
	| COS '(' expr ')'
	{ $$ = new Cos($3); }
	| EXP '(' expr ')'
	{ $$ = new Exp($3); }
	| '(' expr ')' 
	{ $$ = $2;	}
	| ID '(' expr ')'
	{ 
		map<string, Funkcija*>::iterator i = vars.find($1);
		if (i == vars.end())
		{
			cerr<<"Unknown function : "<<$1<<endl;
			exit(1);
		}
		else
		{
			$$ = i->second->kompozicija($3);
			delete $3;
		}

	}
	
	; %%

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