%{
#define SIZE 200
typedef struct foo {
  char str[SIZE];
  int needparen;
} *X;
#include <stdio.h>
#include <string.h>

#define YYSTYPE X 

%}

%left "+"
%left "*"
%token I

%%
  S : S E  ';'   {printf("%s\n", $2->str);}
    | 
;
 E: E'+'E {
   $$ = (X) malloc (sizeof (struct foo));
   $$->needparen=1;
   sprintf($$->str, "%s + %s", $1->str, $3->str);
   free ($1);
   free ($3);
 }

| E '*' E {
  char temp[SIZE];
  $$ = (X ) malloc (sizeof (struct foo));
  $$->needparen=0;
  if ($1->needparen) {
    sprintf(temp, "( %s )", $1->str);
  } else
    strcpy (temp, $1->str);

  if ($3->needparen) {
    sprintf($$->str, "%s * ( %s )", temp, $3->str);
  } else
    sprintf ($$->str, "%s * %s", temp, $3->str);

  free ($1);
  free ($3);
}

| '(' E ')' {
  $$ = $2;
}

| I {
  $$ = (X )malloc(sizeof (struct foo));
  $$->needparen=0;
  sprintf($$->str,"%s",$1->str);
}

;

%%
#include "lex.yy.c"
main () {
  yyparse();
}
yyerror(  s)
char *s;
{ printf("%s\n", s);
}
