FunAlg - syntax

<literal> ::=
  |  ( )
  |  [ - ] { 0 - 9 }+
  |  [ - ] { 0 - 9 }+ / { 0 - 9 }+
  |  ' _ '
  |  " { _ }* "

<ident> ::=
  |  { a - z | A - Z } { a - z | A - Z | 0 - 9 | _ }*

<infix_op> ::=
  |  { = | <> | > | < | >= | <= | + | - | * | / | % | ^ | || | && | $$ | ; }

<type_cons> ::=
  |  <ident> [ <poly_appl> ]
  |  <type_cons> { * <type_cons> }*
  |  <type_cons> => <type_cons>

<poly_appl> ::=
  |  [ ]
  |  [ <type_cons> { , <type_cons> }* ]

<poly_args> ::=
  | [ ]
  | [ <ident> { , <ident> }* ]

<denote> ::=
  |  _
  |  ( )
  |  <ident>
  |  ( <denote> { , <denote> }* )

<expr> ::=
  |  <literal>
  |  <ident> [ <poly_appl> ]
  |  ( <expr> { , <expr> }* )
  |  <expr> <expr>
  |  <expr> <infix_op> <expr>
  |  if <expr> then <expr> else <expr>
  |  let <denote> = <expr> in <expr>
  |  fun <denote> : <type_cons> -> <expr>
  |  match <expr> with { | <ident> <denote> -> <expr> }+

<def> ::=
  |  type <ident> [ <poly_args> ] = { <type_cons> | { | <ident> : <type_cons> }+ }
  |  let <ident> [ <poly_args> ] [ : <type_cons> ] = <expr>
  |  let rec <ident> [ <poly_args> ] : <type_cons> = <expr>

<file> ::=
  |  { <def> ;; }*