%{
#include <iostream>
#include <string>
#include <math.h>
#include "mpfitAST.h"

int mpfitlex();
void mpfiterror(const char *s);
%}

%union { double i; std::string *s; int f; mpfitASTNode *astnode; }

%token BATATA
%token ENTER
%token<i> REAL
%token<s> FUNC
%token<s> VAR
%type<astnode> expr
 
%right '='
%left '+' '-'
%left '*' '/'
%left '^'
%right BATATA
 
%%
 
list: stmt
    | list stmt
    ;
 
stmt: expr ';'          { mpfitAST = $1; }
    | expr ENTER        { std::cout << $1->evaluate() << std::endl; delete $1; }
    | ENTER             { std::cout << std::endl; }
		| VAR '=' expr      { mpfitassignmentNode *a = new mpfitassignmentNode(*$1, $3); a->evaluate(); delete $1; delete a; }
    ;
 
expr: REAL              { $$ = new mpfitnumberNode($1); }
    | VAR               { $$ = new mpfitvariableNode(*$1);      delete $1; }
    | expr '+' expr     { $$ = new mpfitplusNode($1, $3); }
    | expr '-' expr     { $$ = new mpfitminusNode($1, $3); }
    | expr '*' expr     { $$ = new mpfitmultiplyNode($1, $3); }
    | expr '/' expr     { $$ = new mpfitdivideNode($1, $3); }
    | expr '^' expr     { $$ = new mpfitpowerNode($1, $3); }
    | '+' expr  %prec BATATA    { $$ =  $2; }
    | '-' expr  %prec BATATA    { $$ = new mpfitunaryMinusNode($2); }
    | '(' expr ')'              { $$ =  $2; }
		| FUNC expr ')'     { $$ = new mpfitfunctionNode(*$1, $2); delete $1; }
		| FUNC expr ',' expr ')'     { $$ = new mpfitfunctionNode2(*$1, $2, $4); delete $1; }
		| FUNC expr ',' expr ',' expr ')'     { $$ = new mpfitfunctionNode3(*$1, $2, $4, $6); delete $1; }
    ;
 
%%
