创建一个简单的camlp4语法扩展

时间:2012-01-08 01:23:32

标签: ocaml camlp4

鉴于此类型:

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 $并得到相同的错误)

我尝试编译:

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 个答案:

答案 0 :(得分:3)

错误在于您使用camlp4orf,它使用代码的标准语法,但修改了引用的语法,以及字段名value,这是OCaml修订语法中的关键字。最简单的解决方法是使用camlp4oof在任何地方使用标准语法,但您也可以重命名该字段。

PS:我真的认为没有必要写一个Camlp4扩展来做到这一点。我建议使用冗余并使用let foo = var "foo" true代替。这将简化维护,与其他代码库的交互等。

PPS:还有几条评论:

  • 你不想那样实现它;如果你想要捕获顶级声明短语let x = foo;;,你必须住在struct_item,而不是expr,而expr你可能想要捕捉var <lid> = <expr> in <expr>形式的本地声明1}}。

  • 如果您坚持使用Camlp4,则应该使用EXTEND来避免语法修改,就像您现在正在做的那样。而是选择let foo = VAR true作为您的具体语法,并使用Camlp4Filters机制将其转换为您想要的内容。这将更加强大且易于实施。