%{
open FSharp.Text.Parsing
%}

%token <int> INT
%token <string> VAR
%token LPAR RPAR EQ
// FIXME: You should declare tokens for:
//   + Operators
//   + Keywords
// The token for identifier (variable name) is
//     already provided ('VAR')
%token LET IN TO OF EOF
%token TIMES
%token PLUS MINUS
%token SUM PROD MAX ARGMAX

// FIXME: Add precedence rules here.

%nonassoc letprec overprec
%left PLUS MINUS
%left TIMES

%start Prog
%type <AbSyn.EXP> Prog
%type <AbSyn.EXP> Exp

%%

Prog : Exp EOF { $1 }
;

Exp : INT                                               { AbSyn.CONSTANT (AbSyn.INT $1) }
    | VAR                                               { AbSyn.VARIABLE $1 }
    | LPAR Exp RPAR                                     { $2 }
    | Exp PLUS Exp                                      { AbSyn.OPERATE (AbSyn.BPLUS, $1, $3) }
    | Exp MINUS Exp                                     { AbSyn.OPERATE (AbSyn.BMINUS, $1, $3) }
    | Exp TIMES Exp                                     { AbSyn.OPERATE (AbSyn.BTIMES, $1, $3) }
    | LET VAR EQ Exp IN Exp %prec letprec               { AbSyn.LET_IN ($2, $4, $6) }
    | SUM VAR EQ Exp TO Exp OF Exp %prec overprec       { AbSyn.OVER (AbSyn.RSUM, $2, $4, $6, $8) }
    | PROD VAR EQ Exp TO Exp OF Exp %prec overprec      { AbSyn.OVER (AbSyn.RPROD, $2, $4, $6, $8) }
    | MAX VAR EQ Exp TO Exp OF Exp %prec overprec       { AbSyn.OVER (AbSyn.RMAX, $2, $4, $6, $8) }
    | ARGMAX VAR EQ Exp TO Exp OF Exp %prec overprec    { AbSyn.OVER (AbSyn.RARGMAX, $2, $4, $6, $8) }
// FIXME: You should implement parsing for:
//   + infix opeators
//   + let ... = ... in ...
//   + sum ... = ... to ... of ...  [and likewise for prod, ...]
;

%%
