Создание простого расширения грамматики camlp4 - PullRequest
2 голосов
/ 08 января 2012

Учитывая этот тип:

type 'a variable = { name: string; mutable value: 'a } 

Я пытаюсь создать расширение синтаксиса, которое будет принимать этот синтаксис:

var foo = true

... и преобразовать его в:

let foo = { name = "foo"; value = true }

Вот моя попытка:

open Camlp4.PreCast
open Syntax

type 'a variable = { name: string; mutable value: 'a } 

EXTEND Gram
  expr: LEVEL "top"
     [ [ "var"; v = a_LIDENT; "=";  e = expr -> 
         <:expr< let $lid:v$ = { name= $`str:v$ ; value = $e$ } in  $e$ >>
     ] ]
  ;
END

(я почти уверен, что в конце замены нужно $ e $, чтобы сказать «остальное», но этотакже выглядит подозрительно, учитывая, что мы хотим, чтобы поле значения записи имело значение выражения справа - изначально у меня не было конца $ e $ там, и я получил ту же ошибку)

Iпопробуйте скомпилировать с помощью:

ocamlc -I +camlp4 camlp4lib.cma -pp camlp4orf -c pa_var.ml

Что приводит к:

File "pa_var.ml", line 10, characters 50-51:
While expanding quotation "expr" in a position of "expr":
  Parse error: "}" expected after [label_expr_list] (in [expr])

File "pa_var.ml", line 1, characters 0-1:
Error: Preprocessor error

Я не знаю, почему кажется, что он хочет иметь "}" после поля имени записи.(Иначе я на правильном пути?)

1 Ответ

3 голосов
/ 08 января 2012

Ошибка в том, что вы используете camlp4orf, который использует стандартный синтаксис для кода, но пересмотренный синтаксис для цитат вместе с именем поля value, которое является ключевым словом в пересмотренном синтаксисе OCaml. Самое простое решение - использовать camlp4oof для повсеместного использования стандартного синтаксиса, но вы также можете переименовать это поле.

PS: я действительно не думаю, что для этого нужно писать расширение Camlp4. Я бы посоветовал жить с избыточностью и вместо этого использовать let foo = var "foo" true. Это упростит обслуживание, взаимодействие с другими кодовыми базами и т. Д.

PPS: еще пара комментариев:

  • вы не хотите реализовывать это таким образом; если вы хотите перехватить фразы объявления верхнего уровня let x = foo;;, вы должны жить в struct_item, а не expr, а в expr вы можете захотеть перехватить локальные объявления в форме var <lid> = <expr> in <expr>.

  • Если вы настаиваете на использовании Camlp4, вам следует избегать модификации грамматики с помощью EXTEND, как вы делаете сейчас. Вместо этого выберите let foo = VAR true в качестве конкретного синтаксиса и используйте механизм Camlp4Filters, чтобы преобразовать его в то, что вы хотите. Это будет намного надежнее и проще в реализации.

...