%{
#define YYDEBUG 1
#define yyerror printf
extern int yylex();

#include <string>
using namespace std;
#include "lambda.hpp"

%}

%union {
	string* string_attr;
	int int_attr;
	LambdaExpression* expression_attr;	
}

%token<int_attr> NUM
%token<string_attr> ID
%type<expression_attr> expr lambda_expr

%left '+'
%left '*'

%%

lines : lines lambda_expr {
		LambdaExpression* e1 = $2;
		LambdaExpression* e2;
		while(e1->betaConversion(e2)) {
			delete e1;
			e1 = e2;
		}
		delete e1;
		e1 = e2;
		e1->print();
		cout << endl;
		delete e1;
      }
      |
      ;

lambda_expr : '(' lambda_expr lambda_expr ')' {
	$$ = new Application($2, $3);
    }
    | '(' '%' ID '.' lambda_expr ')' {
	$$ = new LambdaAbstraction(*$3, $5);	
    }
    | expr {
	$$ = $1;
    }
    ;

expr : ID {
	$$ = new Variable(*$1);	
	delete $1;
    }
    | NUM {
	$$ = new Constant($1);
    }
    | expr '+' expr {
	$$ = new Plus($1, $3);
    }
    | expr '*' expr {}
    ;

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