2013-10-26 2 views
2

Я реализовал красивый принтер, который хорошо работает на сложном синтаксическом дереве. Поскольку синтаксис сложный, иногда заданный statement или expression, он помогает распечатать конструкторы, чтобы понять их структуру. С этой целью я добавил параметр constructor_print. Когда эта переменная ложна, обычно печатается 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 e3 + (-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+2 и i := !i-2 до и после Printf.fprintf chan (tercs ... ...). Также нам нужно изменить формат, возвращаемый tercs: после этого есть \n, мы добавим i пробелов после \n.

Но я также слышал о box, hint и т. Д., Предоставляемый модулем Format. Кто-нибудь знает их хорошо, и есть ли более прямое решение по моей просьбе?

+1

Было также полезно узнать, как использовать модуль Format. http://caml.inria.fr/resources/doc/guides/format.en.html –

ответ

1

Вы можете передать целочисленный параметр своим функциям, который будет инкапсулировать, сколько пробелов вы должны записать в начале каждой строки. Если вы сделаете рекурсивный вызов, это значение должно быть увеличено.

+0

'String.make offset ''' будет генерировать строку для печати после разрыва строки, если текущий отступ «offset». – lukstafi

Смежные вопросы