Skip to content

dariusf/ppx_deriving_unparse

Repository files navigation

ppx_deriving_unparse

Are you tired of writing pretty-printers?!

Annotate your AST type like this:

type expr =
  | Num of int [@form _1]
  | Plus of expr * expr [@form _1 "+" _2] [@prec left, 3]
  | Times of expr * expr [@form _1 "*" _2] [@prec left, 4]
[@@deriving unparse { between = " " }]

and a printer which parenthesizes expressions properly is generated!

let () =
  let e = Times (Plus (Num 1, Num 2), Num 3) in
  assert ((unparse_expr e) = "(1 + 2) * 3");
  let e = Plus (Times (Num 1, Num 2), Num 3) in
  assert ((unparse_expr e) = "1 * 2 + 3")

Basics

[@form <e1> <e2> ...] goes on constructors, to specify their pretty-printed form. The payload is a sequence of expressions. String literals are printed as is. Variables starting with _ refer to positional arguments.

[@prec <fixity>, <precedence>] also goes on constructors. fixity is one of left, right, nonassoc, prefix, or postfix. precedence is a natural number. The arguments of a constructor without a precedence annotation will not be parenthesized (as it is presumably not an operator).

A number of options may be passed to the deriver.

  • the string between is inserted between every expression in [@form ...] (default: "")
  • fn controls what the generated function is named (default: "unparse")
  • the latex flag generates several functions for working with definitions in LaTeX. [@form.latex ...] may be used to provide an alternate form (default: disabled)

Background

This is an implementation of the classic paper Unparsing expressions with prefix and postfix operators (1998).

It's unproven beyond the small examples in the tests. I might pick it up again the next time I have to write a pretty-printer...

About

Are you tired of writing pretty-printers?!

Resources

License

Stars

Watchers

Forks

Releases

No releases published