%{
#define YYDEBUG 1
  #define yyerror printf
  #include <stdlib.h>
  #include "pii-03.04.h"
  extern int line_number;

  geom_object* variables[128];

%}

%left '+' '-'
%left '*' '/'

%union
{   float float_value;
    char* string_value;
    geom_object* geom_value;
};

%type <geom_value> expr, dim, point, segment, circle;
%type <string_value> ID
%type <float_value> NUM

%token DIM POINT LINE SEGMENT CIRCLE DRAW MED INTERSECT DISTANCE ID NUM CIRCLEPRECISION



%%
program : statements 
        ;

statements : statements statement
           |
           ;

statement  : DIM dims ';'
           | POINT points ';'
           | SEGMENT segments ';'
           | CIRCLE circles ';'
           | ID '=' expr ';'
             {   if (variables[*$1]->type!=$3->type)
                     yyerror("Error in line %d\n",line_number);
                 else 
                    variables[*$1]=$3;
             } 
           | DRAW '(' draw_expressions ')' ';'
           | CIRCLEPRECISION '=' NUM ';'
           ; 

dims       :  dims ',' dim
           |  dim
           ;

dim         : ID '=' expr 
	      {  if ($3->type==DIM_T)
                       variables[*$1]=$3;
                 else
                      yyerror("Error initializing dimension %s in line %d\n",$1,line_number);
              }
              | ID
              {   variables[*$1]=malloc(sizeof(geom_object));
                  variables[*$1]->type=DIM_T;
              }
              ;


points     : points ',' point
           | point
           ;

point  : ID '=' expr
       {   if ($3->type==POINT_T)
               variables[*$1]=$3;
           else
                yyerror("Error initializing point $s in line %d\n",$1,line_number);
       }          
       | ID '(' expr ',' expr ')' 
       {    variables[*$1]=make_point($3,$5);
            if (variables[*$1]==NULL)
            	yyerror("Error initializing point %s in line %d\n",$1,line_number);                    
       }
       | ID
              {   variables[*$1]=malloc(sizeof(geom_object));
                  variables[*$1]->type=POINT_T;
              }
       ;

segments   : segments ',' segment
           | segment
           ;

segment  : ID '=' expr
         {   if ($3->type==SEGMENT_T)
                variables[*$1]=$3;
             else
                yyerror("Error initializing segment $s in line %d\n",$1,line_number);
         }          
         | ID '(' expr ',' expr ')' 
     	 {    variables[*$1]=make_segment($3,$5);
              if ($$==NULL)
                 yyerror("Error initializing segment %s in line %d\n",$1,line_number);                    
         }
         | ID
              {   variables[*$1]=malloc(sizeof(geom_object));
                  variables[*$1]->type=SEGMENT_T;
              }

         ;


circles    : circles ',' circle
           | circle
           |
           ;

circle   : ID '=' expr
         {   if ($3->type==CIRCLE_T)
                variables[*$1]=$3;
             else
                yyerror("Error initializing circle $s in line %d\n",$1,line_number);
         }          
         | ID '(' expr ',' expr ')' 
    	 {    variables[*$1]=make_circle($3,$5);
              if (variables[*$1]==NULL)
                 yyerror("Error initializing circle %s in line %d\n",$1,line_number);                    
         }
         | ID
              {   variables[*$1]=malloc(sizeof(geom_object));
                  variables[*$1]->type=CIRCLE_T;
              }

         ;



draw_expressions : draw_expressions ',' expr 
                   {  draw($3); }
                 | expr
                   {  draw($1); }
                 ;

expr  :   expr '+' expr 
      |   expr '-' expr 
      |   expr '*' expr
      |   expr '/' expr
      |   MED '(' expr ')'
      {    $$=med($3);
           if ($$==NULL)
           	yyerror("Error finding med in line %d\n",line_number);   
           free($3);
      }      
      |   INTERSECT '(' expr ',' expr ')'
      {    $$=intersect($3,$5);
           if ($$==NULL)
           	yyerror("Error finding intersection in line %d\n",line_number);                    
           free($3);free($5);
      }
      |   DISTANCE '(' expr ',' expr ')'
      {    $$=distance($3,$5);
           if ($$==NULL)
           	yyerror("Error finding distance in line %d\n",line_number);                    
           free($3);free($5);
      }
      |   POINT '(' expr ',' expr ')'
      {    $$=make_point($3,$5);
           if ($$==NULL)
           	yyerror("Error initializing point in line %d\n",line_number);                    
           free($3);free($5);
      }
      |   SEGMENT '(' expr ',' expr ')'
      {    $$=make_segment($3,$5);
           if ($$==NULL)
               yyerror("Error initializing segment in line %d\n",line_number);                    
           free($3);free($5);
      }
      |   CIRCLE '(' expr ',' expr ')'
      {    $$=make_circle($3,$5);
           if ($$==NULL)
                 yyerror("Error initializing circle in line %d\n",line_number);                    
           free($3);free($5);
      }
      |   ID
          {   $$=malloc(sizeof(geom_object));
              memcpy($$, variables[*$1], sizeof(geom_object));
          }
      |   NUM 
          {    $$=(geom_object*)malloc(sizeof(geom_object));
               $$->type=DIM_T;
               $$->num.value=$1;
          }
      ;
%%

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

}
