The tricky bit is the generic Expr<'T>
. You can make a function that returns expr
parser, and let subsequent use of parsers determine a specific type of Expr<'T>
:
let expr() =
// initially exprRef holds a reference to a dummy parser
let expr, exprRef = createParserForwardedToRef()
// create other union-case parsers as inner or outer functions
let unary() = ...
let binary = ...
let ternary() = ...
let term() = ...
// replace dummy parser reference in exprRef
do exprRef := choice [unary(); binary(); ternary(); term()]
expr
You could also pass primitive parsers such as term
as arguments to expr
function. In this case, type of expr
depends on different kinds of parsers passed on e.g. pstring
, pfloat
.
FParsec tutorial has a section on F# value restriction which might also be helpful.