SoftTimur
SoftTimur

Reputation: 5510

Automatize indentation in a pretty printer

I have implemented a pretty printer which works quite well on a complex syntax tree. As the syntax is complicated, sometimes given a statement or an expression, it helps to print the constructors to understand their structure. To this end, I added a parameter constructor_print. When this variable is false, a statement or an expression is normally printed; otherwise, all the related constructors are printed in a good order. Here is a very small part of code (there are actually lots of functions pp_...):

let tercs s0 s1 =
  if !constructor_print then
    format_of_string s0
  else
    format_of_string s1  

let pp_e (chan: out_channel) (e: expression) =
  match e with
  | ADD_E_E (e0, e1) -> 
    Printf.fprintf chan  (tercs "ADD_E_E (\n%a,\n%a)" "%a + %a") pp_e e0 pp_e e1
  | UMINUS_E e ->
    Printf.fprintf chan  (tercs "UMINUS_E %a" "- %a") pp_e e
  | PARENTHESIZED_E e ->
    Printf.fprintf chan  (tercs "PARENTHESIZED_E %a" "(%a)") pp_e e
  ...

let pp_s (chan: out_channel) (s: statement) =
  ...

...

For instance, 3 + (-2) is parsed to an expression e. When !constructor_print is false. pp_e stdout e returns 3 + (-2); otherwise pp_e stdout e returns

ADD_E_E (
Int 3,
PARENTHESIZED_E UMINUS_E INT 2)

However, the problem is, I would like to print indentation when necessary to make it more readable. For instance, I would hope the previous output could be:

ADD_E_E (
  INT 3,
  PARENTHESIZED_E UMINUS_E INT 2)

The rule is quite simple: when there is a pair (or triple or more) constructor (e.g. ADD_E_E), it prints a new lines for its arguments, each line has another 2 spaces of indentation; when there is a unary constroctor (e.g. UMINUS_E), it doesn't print new line.

Almost all the lines have this structure Printf.fprintf chan (tercs ... ...) ..., as they are a lot, I really need to automatize the indentation in a clever way.

One way I think of is to have a ref variable i which represents the number of the spaces of the current indentation. We incorporate i := !i+2 and i := !i-2 before and after Printf.fprintf chan (tercs ... ...). Also we need to modify the format returned by tercs: once there is \n, we add i spaces after \n.

But I have also heard of box, hint, etc. provided by Format module. Does anyone know them well, and is there a more direct solution for my request?

Upvotes: 2

Views: 246

Answers (1)

Kakadu
Kakadu

Reputation: 2839

You can pass an integer parameter to your functions which will incapsulate how many spaces you should write at the beginning of each line. If you will do some recursive call this value should be increased.

Upvotes: 1

Related Questions