2013-10-26 20 views
2

我已經實現了漂亮的打印機,它在複雜的語法樹上運行得非常好。由於語法複雜,有時會給出statementexpression,這有助於打印構造函數以瞭解其結構。爲此,我添加了一個參數constructor_print。當此變量爲false時,通常會打印statementexpression;否則,所有相關的構造函數都會按順序打印出來。下面是代碼的非常小的部分(實際上有大量的功能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+2i := !i-2。我們也需要修改tercs返回的格式:一旦有\n,我們在\n後面加上i的空格。

但我也聽說過boxhint等由Format模塊提供。有人認識他們嗎?對我的要求有沒有更直接的解決方案?

+1

這對學習如何使用Format模塊也很有幫助。 http://caml.inria.fr/resources/doc/guides/format.en.html –

回答

1

您可以將一個整數參數傳遞給您的函數,該函數將封裝每行開始時應該寫入多少個空格。如果你會做一些遞歸調用,這個值應該增加。

+0

如果當前縮進是'offset',則String.make offset''將生成換行符後打印的字符串。 – lukstafi