鉴于此类型:
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
我不知道为什么它似乎想在记录的名称字段后面有一个“}”。 (否则,我是否在正确的轨道上?)
答案 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
机制将其转换为您想要的内容。这将更加强大且易于实施。