我已經實現了漂亮的打印機,它在複雜的語法樹上運行得非常好。由於語法複雜,有時會給出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
爲false時。 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個空格的縮進;當存在一個一元的constroctor(例如UMINUS_E
)時,它不會打印新行。
幾乎所有的線都有這種結構Printf.fprintf chan (tercs ... ...) ...
,因爲它們很多,我真的需要以一種聰明的方式自動縮進縮進。
我想到的一種方法是有一個ref變量i
,它表示當前縮進空格的數量。我們在Printf.fprintf chan (tercs ... ...)
之前和之後合併了i := !i+2
和i := !i-2
。我們也需要修改tercs
返回的格式:一旦有\n
,我們在\n
後面加上i
的空格。
但我也聽說過box
,hint
等由Format
模塊提供。有人認識他們嗎?對我的要求有沒有更直接的解決方案?
這對學習如何使用Format模塊也很有幫助。 http://caml.inria.fr/resources/doc/guides/format.en.html –