我有一些这样的代码:
type boolean = T | F
type bexp = Const of boolean
| Var of variable
| Bop of bop * bexp * bexp
| Not of bexp
and bop = And | Or | Xor
and variable = { name: string; mutable value: boolean }
如果我想创建一个我必须做的变量:
let full = Var({name ="full"; value = F});;
我宁愿不必重复两次“完整”,并希望想出一些内省的方法来将名称作为字符串。我认为camlp4可以为此工作,但不知道从哪里开始。
所以最终我希望能够做到这样的事情:
let full = Var({name = :letname:; value = F});;
其中:letname:将当前的let绑定填充为字符串代替(在本例中为“full”)。 (语法:letname:只是一个建议,其他语法的想法不会与OCaml的语法冲突?)
这样一个更简洁的语法可能更可取:
var full = F
然后将扩展为:
let full = Var({name = "full"; value = F});;
这可能与camlp4有关吗?如果是这样,我该如何处理呢?
(经过进一步考虑,:letname:语法或类似的东西会更通用,在更多领域有用)
答案 0 :(得分:3)
尝试以下方法。在单独的文件中,例如test.ml
(* A simple syntax extension for getting the name of an identifier. *)
open Camlp4
(* Create an ID for the macro*)
module Id : Sig.Id = struct
let name = "let'"
let version = "1.0"
end
module Make (Syntax : Sig.Camlp4Syntax) = struct
open Sig
include Syntax
(* Extend the syntax with a let' x=e1 in e2 construction*)
EXTEND Gram
expr: [
[ "let'"; x = patt ; "=" ; e1=expr; "in"; e2=expr ->
let name=begin match x with
| Ast.PaId (_,Ast.IdLid(_,name)) -> name
| _ -> failwith "Require an identifier in a let' statement."
end in
<:expr<
let $x$ = $e1$ in ($str:name$,$e2$)
>>
]
];
END
end
module M = Register.OCamlSyntaxExtension(Id)(Make)
接下来,使用
进行编译 ocamlc -c -I +camlp4 dynlink.cma camlp4lib.cma -pp camlp4of.opt test.ml
在顶层
ocaml dynlink.cma -I +camlp4 camlp4of.cma
然后
# #load "test03.cmo";;
# let' x=1 in x;;
- : string * int = ("x", 1)
为了使用扩展编译,请创建一个不同的文件,例如test2.ml
let' x=1 in x
然后,用
编译ocamlc -pp "camlp4of test.cmo" test2.ml
答案 1 :(得分:0)
是的,这是可能的。首先阅读一些camlp4教程,了解它是如何工作的,并提出更具体的问题。