%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define yyerror printf
extern char* yytext;

enum VRSTAIZRAZA {MULTIPLIKATIVNI,ADITIVNI,PROM,BROJ};

/* Struktura internog steka koja odgovara
   aritmetickom izrazu */

typedef struct _IZRAZ
{
   /* Vrednost izraza */
   int vrednost;

   /* Tekstualna reprezentacija izraza
      bez viska zagrada, sa zamenjenim
      vrednostima promenjivih */
   char string[255];

   /* Vrsta operacije "na vrhu" ovog izraza.
      Koristimo ga za oslobadjanje suvisnih
      zagrada */
   int vrsta;

} IZRAZ;

#define YYSTYPE IZRAZ*


/* Niz vrednosti promenjivih */
int vrednosti[26];

/* Pomocna promenjiva u kojoj cuvamo
   ime promenjive kojoj dodeljujemo vrednost */
char pamtiprom;
%}

%left PLUS MINUS
%left PUTA PODELJENO
%token PROM BROJ

%%

nizdodela : nizdodela dodela
          |
          ;


dodela : PROM
         { /*Pamtimo ime promenjive sa leve strane dodele */
              pamtiprom=yytext[0]; }

         '=' izraz ';'

         { /* Ukoliko je izraz samo broj ne pisemo
              medjurezultat */
           if ($4->vrsta==BROJ)
               printf("%c=%d;\n",pamtiprom,$4->vrednost);
           else
               printf("%c=%s=%d;\n",pamtiprom,$4->string,$4->vrednost);

           /* Pamtimo vrednost promenjive u nizu vrednosti */
           vrednosti[pamtiprom-'a']=$4->vrednost;

           /* Struktura koja odgovara ovom izrazu nam vise
              nije potrebna, pa je oslobadjamo */
              free($4);
         }

izraz : izraz PLUS izraz
               { /* Novi izraz gradimo na osnovu dva vec izgradjena */
                 $$=(IZRAZ*)malloc(sizeof(IZRAZ));
                 $$->vrsta=ADITIVNI;
                 $$->vrednost=$1->vrednost+$3->vrednost;
                 sprintf($$->string,"%s+%s",$1->string,$3->string);

                 /* Vise nam nisu potrebni podaci o dva podizraza */
                 free($1);
                 free($3);
               }
      | izraz MINUS izraz
               { /* Novi izraz gradimo na osnovu dva vec izgradjena */
                 $$=(IZRAZ*)malloc(sizeof(IZRAZ));
                 $$->vrsta=ADITIVNI;
                 $$->vrednost=$1->vrednost-$3->vrednost;

                 /* Zagrade su potrebne samo ako je umanjenik
                    "aditivni" izraz */
                 if ($3->vrsta==ADITIVNI)
                         sprintf($$->string,"%s-(%s)",$1->string,$3->string);
                 else
                         sprintf($$->string,"%s-%s",$1->string,$3->string);

                 /* Vise nam nisu potrebni podaci o dva podizraza */
                 free($1);
                 free($3);
               }
      | izraz PUTA izraz
               {  /* Novi izraz gradimo na osnovu dva vec izgradjena */
                  $$=(IZRAZ*)malloc(sizeof(IZRAZ));
                  $$->vrsta=MULTIPLIKATIVNI;
                  $$->vrednost=$1->vrednost*$3->vrednost;

                  /* Zagrade oko svakog od cinioca su potrebne samo ako su
                     cinioci aditivni */
                  if ($1->vrsta==ADITIVNI)
                     if ($3->vrsta==ADITIVNI)
                         sprintf($$->string,"(%s)*(%s)",$1->string,$3->string);
                     else
                         sprintf($$->string,"(%s)*%s",$1->string,$3->string);
                  else
                     if ($3->vrsta==ADITIVNI)
                         sprintf($$->string,"%s*(%s)",$1->string,$3->string);
                     else
                         sprintf($$->string,"%s*%s",$1->string,$3->string);

                 /* Vise nam nisu potrebni podaci o dva podizraza */
                 free($1);
                 free($3);
               }

      | izraz PODELJENO izraz
               {  /* Novi izraz gradimo na osnovu dva vec izgradjena */
                  $$=(IZRAZ*)malloc(sizeof(IZRAZ));
                  $$->vrsta=MULTIPLIKATIVNI;

                  /* Da li mozda vrsimo deljenje nulom? */
                  if ($3->vrednost==0)
                  {   yyerror("Deljenje sa 0!");
                      exit(1);
                  }
                  $$->vrednost=$1->vrednost/$3->vrednost;

                  /* Zagrade oko svakog od cinioca su potrebne samo ako su
                     cinioci aditivni */
                  if ($1->vrsta==ADITIVNI)
                     if ($3->vrsta==ADITIVNI)
                         sprintf($$->string,"(%s)/(%s)",$1->string,$3->string);
                     else
                         sprintf($$->string,"(%s)/%s",$1->string,$3->string);
                  else
                     if ($3->vrsta==ADITIVNI)
                         sprintf($$->string,"%s/(%s)",$1->string,$3->string);
                     else
                         sprintf($$->string,"%s/%s",$1->string,$3->string);

                 /* Vise nam nisu potrebni podaci o dva podizraza */
                 free($1);
                 free($3);
               }

      | '(' izraz ')'
              {  /* U ovom slucaju samo kopiramo pokazivac na
                    vec postojeci izraz */
                 $$=$2; }

     |  BROJ  {   /* Elementarni izraz koji predstavlja brojevnu
                     konstantu */
                  $$=(IZRAZ*)malloc(sizeof(IZRAZ));
                  $$->vrsta=BROJ;
                  $$->vrednost=atoi(yytext);
                  strcpy($$->string,yytext);
              }

     |  PROM  {   /* Elementarni izraz koji predstavja promenjivu.
                     Na ovom mestu se promenjiva zamenjuje svojom
                     vrednoscu, procitanom iz niza vrednosti */
                  $$=(IZRAZ*)malloc(sizeof(IZRAZ));
                  $$->vrsta=PROM;
                  $$->vrednost=vrednosti[yytext[0]-'a'];
                  itoa($$->vrednost,$$->string,10);
              }
   ;


%%

main()
{  int i;
   /* postavljamo vrednosti svih promenjivih na 0 */
   for (i=0; i<26; i++)
      vrednosti[i]=0;

   /* Vrsimo parsiranje */
   yyparse();
}
