/* Use the expression datatype defined in expressions.ml: */ %{ open Expressions let rec braceListContentsIntoExp seq = match seq with [] -> Const "nil" | e :: s -> App(App(Const "cons",e),braceListContentsIntoExp s) %} /* Define the tokens of the language: */ %token NAT %token BOOL %token STRING VAR %token DBLSEMI LET DOT EQUALS NEQ LPAREN RPAREN COMMA SEMI LBRAC RBRAC FIX PLUS MINUS DIV MOD CARET TIMES OR AND LT GEQ LEQ GT NOT DBLCOLON IF THEN ELSE IN FUN RARROW PIPE LARROW UNIT DUMMY FST SND HEAD TAIL NIL /* Define the "goal" nonterminal of the grammar: */ %start prog %type prog %type exp %type decl %type list_contents %% prog: seqOfDecl DBLSEMI { $1 } seqOfDecl: decl { [$1] } | decl seqOfDecl { $1 :: $2 } decl: LET VAR EQUALS exp { Let($2,$4) } exp: construct_exp { $1 } | other { $1 } construct_exp: IF exp THEN exp ELSE exp { App(App(App(Const "if", $2),$4),$6) } | decl IN exp { Comp($1,$3) } | FIX VAR DOT exp { Rec($2,$4) } | FUN VAR RARROW exp { Fun($2,$4) } other: nonCompar { $1 } | other EQUALS nonCompar { App(App(Const("eq"),$1),$3) } | other LEQ nonCompar { App(App(Const("leq"),$1),$3) } | other LT nonCompar { App(App(Const("lt"),$1),$3) } | other GEQ nonCompar { App(App(Const("geq"),$1),$3) } | other GT nonCompar { App(App(Const("gt"),$1),$3) } nonCompar: nonComma { $1 } | nonCompar COMMA nonComma { App(App(Const("comma"),$1),$3) } nonComma: nonDCol { $1 } | nonDCol DBLCOLON nonComma { App(App(Const("cons"),$1),$3) } nonDCol: nonOr { $1 } | nonDCol OR nonOr { App(App(Const("or"),$1),$3) } nonOr: nonAnd { $1 } | nonOr AND nonAnd { App(App(Const("and"),$1),$3) } nonAnd: nonPlMin { $1 } | nonAnd PLUS nonPlMin { App(App(Const("plus"), $1),$3) } | nonAnd MINUS nonPlMin { App(App(Const("minus"),$1),$3) } nonPlMin: nonTmDvCn { $1 } | nonPlMin TIMES nonTmDvCn { App(App(Const("times"),$1),$3) } | nonPlMin DIV nonTmDvCn { App(App(Const("div"),$1),$3) } | nonPlMin CARET nonTmDvCn { App(App(Const("concat"),$1),$3) } nonTmDvCn: nonApp { $1 } | nonTmDvCn nonApp { App($1,$2) } nonApp: VAR { Var($1) } | NOT { Const("not") } | FST { Const("fst") } | SND { Const("snd") } | NIL { Const("nil") } | HEAD { Const("head") } | TAIL { Const("tail") } | NAT { Natexp $1 } | BOOL { Boolexp $1 } | STRING { Stringexp $1 } | LPAREN exp RPAREN { $2 } | LBRAC list_contents RBRAC { braceListContentsIntoExp $2 } list_contents: exp { [$1] } | exp SEMI list_contents { $1 :: $3 }