open LambdaAst

%%
%eop EOF
%pos int

%name Lambda

%term INT of int | VAR of string | PLUS | MINUS | TIMES | EOF 
  | LPAREN | RPAREN | LBRACE | RBRACE | ZERO | HEAD | TAIL | CONS
  | FN | LETREC | AND | OR | TRUE | FALSE | IF | FOR | YIELD | PRINT

%nonterm e of expr
  | v of var
  | bin of binop
  | un  of unop

%verbose
%start e

%keyword ZERO HEAD TAIL CONS FN LETREC AND OR TRUE FALSE FOR YIELD IF PRINT

%value INT (1)
%value VAR ("")

%noshift EOF
 
%%

e : v						(Var(v))
  | TRUE                                        (True)
  | FALSE					(False)
  | INT                  			(Num(INT))
  | LPAREN FN LPAREN v RPAREN e RPAREN		(Lambda(v, e))
  | LPAREN IF e e e RPAREN                      (If(e1, e2, e3))
  | LPAREN e e RPAREN				(App(e1, e2))
  | LPAREN LETREC LPAREN v e RPAREN e RPAREN    (Letrec(v, e1, e2))
  | LPAREN bin e e RPAREN                       (Binop(bin, e1, e2))
  | LPAREN un e RPAREN                          (Unop(un, e))
  | LPAREN FOR v e e RPAREN                     (For(v, e1, e2))
  | LPAREN YIELD e RPAREN                       (Yield(e))
  | LPAREN PRINT e RPAREN                       (Print(e))

v : VAR                                         (VAR, ~1)

bin : PLUS					(Plus)
   | TIMES					(Times)
   | MINUS					(Minus)
   | CONS					(Cons)
   | AND					(And)
   | OR						(Or)

un : HEAD					(Head)
   | TAIL					(Tail)
   | ZERO					(ZeroP)
