
%{
#include "calc.h"
%}

  
%union {
  long integer;
  double real;
  char *string;
  Expression *expression;
  ExpressionList *expressionList;
  Statement *statement;
}

%token <integer> INTCONST
%token <real> REALCONST
%token <string> IDENT STRCONST

%type <expression> exp exp_as exp_pm exp_td exp_at exp_fc exp_um 
%type <expressionList> explist

%start top



%%

top: 
     { printf ("=>"); fflush(stdout); }
     | top exp ';'
     { printf ("Result: ");
       PrintExpression ($2); 
       printf ("=>"); fflush(stdout); }


exp: 	exp_as

exp_as:	exp_pm
	| exp_pm '=' exp_as
	{ $$=MakeBinaryExpression(EAssignment, $1, $3); }

exp_pm:	exp_td
	| exp_pm '+' exp_td
	{ $$=MakeBinaryExpression(ESum, $1, $3); }
	| exp_pm '-' exp_td
	{ $$=MakeBinaryExpression(EDifference, $1, $3); }


exp_td:	exp_um
	| exp_td '*' exp_um
	{ $$=MakeBinaryExpression(EProduct, $1, $3); }
	| exp_td '/' exp_um
	{ $$=MakeBinaryExpression(EQuotient, $1, $3); }

exp_um: exp_fc
	| '-' exp_um
	{ $$=MakeUnaryExpression(ENegation, $2); }
	| '*' exp_um
	{ $$=MakeUnaryExpression(EIndirection, $2); }

exp_fc: exp_at
	| exp_fc '(' explist ')'
	{ $$=MakeExpression(EFunctionCall); 
	  $$->data.functionCall.function = $1;
	  $$->data.functionCall.arglist = $3; }
	| exp_fc '[' exp ']'
	{ $$=MakeBinaryExpression (EArrayAccess, $1, $3); }
	

exp_at:	IDENT
	{ $$=MakeExpression(EVariable);
	  $$->data.variable = $1; }
	| REALCONST
	{ $$=MakeExpression(EConstant);
	  $$->data.constant.type = MakeType(Real);
	  $$->data.constant.data.real = $1; }
	| INTCONST
	{ $$=MakeExpression(EConstant);
	  $$->data.constant.type = MakeType(Integer);
	  $$->data.constant.data.integer = $1; }
	| '(' exp ')'		      
	{ $$=$2; }



explist: exp
	 { $$=make(ExpressionList);
	   $$->expression=$1;
	   $$->next=NULL; }

	 | explist ',' exp
	 { $1->next = make(ExpressionList);
	   $1->next->expression = $3;
	   $1->next->next = NULL;
	   $$=$1; }
	 |
	 { $$=NULL; }



%%
  

  
 