【发布时间】:2013-10-26 21:02:06
【问题描述】:
我已经实现了一个漂亮的打印机,它在复杂的语法树上工作得很好。由于语法很复杂,有时给出statement 或expression,有助于打印构造函数以了解它们的结构。为此,我添加了一个参数constructor_print。当此变量为 false 时,通常会打印 statement 或 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)时,它为其参数打印一个新行,每行有另外两个缩进空格;当有一个一元构造函数时(例如UMINUS_E),它不会打印新行。
几乎所有的行都有这种结构Printf.fprintf chan (tercs ... ...) ...,因为它们很多,我真的需要以一种聪明的方式自动化缩进。
我想到的一种方法是有一个引用变量i,它代表当前缩进的空格数。我们在Printf.fprintf chan (tercs ... ...) 之前和之后合并i := !i+2 和i := !i-2。另外我们需要修改tercs返回的格式:一旦有\n,我们在\n后面加上i空格。
但我也听说过Format模块提供的box、hint等。有没有人很了解他们,我的要求有更直接的解决方案吗?
【问题讨论】:
-
这对学习如何使用格式模块也很有帮助。 caml.inria.fr/resources/doc/guides/format.en.html
标签: ocaml indentation pretty-print