Внешние определения регулярных выражений ocamllex

Я реализовал обычную комбинацию lexer/parser/pretty-printer для чтения / печати типа в моем коде. Я нахожу избыточность среди лексера и симпатичного принтера, когда речь идет о регулярных выражениях в виде простых строк, обычно используемых для символов, знаков препинания или разделителей.

Например у меня сейчас

rule token = parse
  | "|-" { TURNSTILE }

в моем lexer.mll файл и такая функция:

let pp fmt (l,r) = 
  Format.fprintf fmt "@[%a |-@ %a@]" Form.pp l Form.pp r

для красивой печати. Если я решу изменить строку для TURNSTILE, мне придется отредактировать два места в коде, которые я нахожу менее чем идеальными.

По-видимому, лексер OCaml поддерживает определенную способность определять регулярные выражения, а затем обращаться к ним внутри mll файл Так lexer.mll может быть написано как

let symb_turnstile = "|-"

rule token = parse
  | symb_turnstile { TURNSTILE }

Но это не даст мне внешний доступ symb_turnstile Скажем из моих симпатичных печатных функций. На самом деле, после запуска ocamllex нет случаев symb_turnstile в lexer.ml, Я даже не могу сослаться на эти идентификаторы в эпилоге OCaml lexer.mll,

Есть ли способ достичь этого?

2 ответа

Решение

В конце концов, я пошел на следующий стиль, который я украл из источников ocamllex сам (так что я предполагаю, что это стандартная практика). Карта из строк в токены (здесь список ассоциаций) определяется в преамбуле lexer.mll

let symbols =
  [ 
    ...
    (Symb.turnstile, TURNSTILE); 
    ...
  ]

где Symb это модуль, определяющий turnstile как строка Затем лексическая часть lexer.mll преднамеренно чрезмерно общий:

rule token = parse
  ...
  | punctuation
    {
      try 
        List.assoc (Lexing.lexeme lexbuf) symbols
      with Not_found -> lex_error lexbuf  
    }
  ...

где punctuation является регулярным выражением, соответствующим последовательности символов.

Симпатичный принтер теперь может быть написан так.

let pp fmt (l,r) = 
  Format.fprintf fmt "@[%a %s@ %a@]" Form.pp Symb.turnstile l Form.pp r

Хотя оба токена выглядят как строки в нотации, на самом деле они очень разные. Я не думаю, что есть удобный тип, под которым они могут быть совместно использованы для ocamllex и Printf.printf. Возможно, это причина того, что ocamllex не поддерживает такие внешние определения. Вы можете получить эффект, который хотите, с помощью макро-функции (текстовое включение).

Другие вопросы по тегам