%{ let p0 = (0,0) open FSharp.Text.Parsing open AbSyn (* parse-error function *) let mutable ErrorContextDescriptor : string = "" let parse_error_rich = Some (fun (ctxt: ParseErrorContext<_>) -> ErrorContextDescriptor <- match ctxt.CurrentToken with | None -> "At beginning of input\n" | Some token -> sprintf "at token %A\n" token ) %} %token NUM %token CHARLIT %token ID STRINGLIT %token IF THEN ELSE LET IN EOF %token INT CHAR BOOL %token PLUS MINUS LESS %token DEQ LTH EQ OP MAP REDUCE IOTA ARROW %token FUN FN COMMA SEMICOLON READ WRITE %token LPAR RPAR LBRACKET RBRACKET LCURLY RCURLY %token TIMES DIVIDE NUMNEG %token NOT AND OR %token BOOLVAL %token FILTER SCAN REPLICATE %nonassoc ifprec letprec %left AND OR %nonassoc NOT %left DEQ LTH %left PLUS MINUS %left TIMES DIVIDE %nonassoc NUMNEG %start Prog %type Prog %type FunDecs %type Fun %type Type %type Exp %type Exps %type FunArg %type MultiLet %% Prog : FunDecs EOF { $1 } ; FunDecs : FUN Fun FunDecs { $2 :: $3 } | FUN Fun { $2 :: [] } ; 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))} ; Exp : NUM { Constant (IntVal (fst $1), snd $1) } | CHARLIT { Constant (CharVal (fst $1), snd $1) } | ID { Var $1 } | STRINGLIT { StringLit $1 } | LCURLY Exps RCURLY { ArrayLit ($2, (), $1) } | Exp PLUS Exp { Plus ($1, $3, $2) } | Exp MINUS Exp { Minus($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) } | 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) } | 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) } | LPAR Exp RPAR { $2 } | LET ID EQ Exp MultiLet %prec letprec { Let (Dec (fst $2, $4, $3), $5, $1) } | ID LBRACKET Exp RBRACKET { Index (fst $1, $3, (), $2) } | Exp TIMES Exp { Times ($1, $3, $2) } | Exp DIVIDE Exp { Divide ($1, $3, $2) } | NUMNEG Exp { Negate ($2, $1) } | Exp AND Exp { And ($1, $3, $2) } | Exp OR Exp { Or ($1, $3, $2) } | NOT Exp { Not ($2, $1) } | BOOLVAL { Constant (BoolVal (fst $1), snd $1) } ; MultiLet : IN Exp { $2 } | SEMICOLON ID EQ Exp MultiLet { Let (Dec (fst $2, $4, $3), $5, $1) } ; 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) } ; %%