%{

let p0 = (0,0)

open FSharp.Text.Parsing
open AbSyn

%}

%token <(int*int)> IMPL
%token <(int*int)> AND OR
%token <(int*int)> NOT
%token <char*(int*int)> LITERAL
%token <bool*(int*int)> CONSTANT
%token <(int*int)> LPAR RPAR
%token EOF

%right IMPL
%left AND OR
%left NOT

%start start
%type <AbSyn.UntypedExp> start

%%

start: expr EOF { $1 }

expr:
  | NOT expr { AbSyn.Not ($2, $1) }
  | LPAR expr RPAR { $2 }
  | expr AND expr { AbSyn.And ($1, $3, $2) }
  | expr OR expr { AbSyn.Or ($1, $3, $2) }
  | expr IMPL expr { AbSyn.Impl ($1, $3, $2) }
  | LITERAL  { AbSyn.Literal $1 }
  | CONSTANT  { AbSyn.Constant $1 }

//
//Fun : Type ID LPAR Params RPAR EQ Exp
//           { FunDec (fst $2, $1, $4, $7, snd $2) }
//    | Type ID LPAR RPAR EQ Exp
//           { FunDec (fst $2, $1, [], $6, snd $2) }
//;
//
//Type :   INT                    { AbSyn.Int }
//     |   CHAR                   { AbSyn.Char }
//     |   BOOL                   { AbSyn.Bool }
//     |   LBRACKET Type RBRACKET { AbSyn.Array $2 }
//;
//
//Params : Type ID COMMA Params
//                       { Param (fst $2, $1) :: $4 }
//       | Type ID       { Param (fst $2, $1) :: [] }
//;
//
//
//BinOp : PLUS  { (Lambda
//                       (Int, [Param ("x", Int);
//                              Param ("y", Int)],
//                        Plus (Var ("x", $1),
//                              Var ("y", $1),
//                                        $1),$1))}
//;
//
/////////////////////////////////////////////////////////
//// TODO: project tasks 1,2,4:
////       add grammer rules for the new expressions
////       List func eq [DONE] maybe add BinOp to Scan
////
/////////////////////////////////////////////////////////
//
//Exp : NUM            { Constant (IntVal (fst $1), snd $1) }
//    | CHARLIT        { Constant (CharVal (fst $1), snd $1) }
//    | ID             { Var $1 }
//    | STRINGLIT      { StringLit $1 }
//    | TRUE           { Constant (BoolVal true, $1 )}
//    | FALSE          { Constant (BoolVal false, $1 )}
//    | LCURLY Exps RCURLY
//                     { ArrayLit ($2, (), $1) }
//    | NEGATE Exp     { Negate ($2, $1) }
//    | NOT Exp        { Not ($2, $1) }
//    | Exp PLUS  Exp  { Plus ($1, $3, $2) }
//    | Exp MINUS Exp  { Minus($1, $3, $2) }
//    | Exp DIVIDE Exp { Divide($1, $3, $2) }
//    | Exp MULTIPLY Exp { Times($1, $3, $2) }
//    | Exp DEQ   Exp  { Equal($1, $3, $2) }
//    | Exp LTH   Exp  { Less ($1, $3, $2) }
//    | IF Exp THEN Exp ELSE Exp %prec ifprec
//                     { If ($2, $4, $6, $1) }
//    | ID LPAR Exps RPAR
//                     { Apply (fst $1, $3, snd $1) }
//    | ID LPAR RPAR   { Apply (fst $1, [], snd $1) }
//    | READ LPAR Type RPAR
//                     { Read ($3, $1) }
//    | WRITE LPAR Exp RPAR
//                     { Write ($3, (), $1) }
//    | IOTA LPAR Exp RPAR
//                     { Iota ($3, $1) }
//    | MAP LPAR FunArg COMMA Exp RPAR
//                     { Map ($3, $5, (), (), $1) }
//    | REPLICATE LPAR Exp COMMA Exp RPAR
//                     { Replicate ($3, $5, (), $1) }
//    | FILTER LPAR FunArg COMMA Exp RPAR
//                     { Filter ($3, $5, (), $1) }
//    | SCAN LPAR FunArg COMMA Exp COMMA Exp RPAR
//                     { Scan ($3, $5, $7, (), $1) }
//    | REDUCE LPAR FunArg COMMA Exp COMMA Exp RPAR
//                     { Reduce ($3, $5, $7, (), $1) }
//    | REDUCE LPAR OP BinOp COMMA Exp COMMA Exp RPAR
//                     { Reduce ($4, $6, $8, (), $1) }
//    | LPAR Exp RPAR  { $2 }
//    | LET ID EQ Exp IN Exp %prec letprec
//                     { Let (Dec (fst $2, $4, $3), $6, $1) }
//    | ID LBRACKET Exp RBRACKET
//                     { Index (fst $1, $3, (), $2) }
//    | Exp OR Exp     { Or ($1, $3, $2) }
//    | Exp AND Exp    { And ($1, $3, $2) }
//;
//
//Exps : Exp COMMA Exps { $1 :: $3 }
//     | Exp            { $1 :: [] }
//;
//
//FunArg : ID    { FunName (fst $1 ) }
//       | FN Type LPAR RPAR ARROW Exp
//               { Lambda ($2, [], $6, $1) }
//       | FN Type LPAR Params RPAR ARROW Exp
//               { Lambda ($2, $4, $7, $1) }
//;
%%
