2

我已经实现了一个漂亮的打印机,它在复杂的语法树上工作得很好。由于语法很复杂,有时给出 astatement或 an expression,打印构造函数以理解它们的结构会有所帮助。为此,我添加了一个参数constructor_print。当此变量为 false 时,通常打印astatement或 an ;expression否则,所有相关的构造函数都以良好的顺序打印。这是代码的一小部分(实际上有很多功能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) =
  ...

...

例如,3 + (-2)被解析为一个表达式e。什么时候!constructor_print是假的。pp_e stdout e返回3 + (-2);否则pp_e stdout e返回

ADD_E_E (
Int 3,
PARENTHESIZED_E UMINUS_E INT 2)

但是,问题是,我想在必要时打印缩进以使其更具可读性。例如,我希望之前的输出可以是:

ADD_E_E (
  INT 3,
  PARENTHESIZED_E UMINUS_E INT 2)

规则很简单:当有一对(或三重或更多)构造函数(例如ADD_E_E)时,它为其参数打印一个新行,每行有另外 2 个缩进空格;当有一个一元构造器(例如UMINUS_E)时,它不会打印新行。

几乎所有的行都有这种结构Printf.fprintf chan (tercs ... ...) ...,因为它们很多,我真的需要以一种巧妙的方式自动化缩进。

我想到的一种方法是有一个 ref 变量i,它表示当前缩进的空格数。我们合并之前i := !i+2i := !i-2之后Printf.fprintf chan (tercs ... ...)。我们还需要修改返回的格式tercs:一旦有\n,我们在i后面加空格\n

但是我也听说过module提供的box,,hint等。Format有没有人很了解他们,我的要求有更直接的解决方案吗?

4

1 回答 1

1

您可以将一个整数参数传递给您的函数,该参数将封装您应该在每行的开头写入多少个空格。如果你会做一些递归调用,这个值应该增加。

于 2013-10-27T06:58:59.843 回答