1

我有一些这样的代码:

  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: 会将当前的 le​​t 绑定填充为字符串来代替(在本例中为“full”)。(语法 :letname: 只是一个建议,其他不会与 OCaml 语法冲突的语法想法?)

像这样更简洁的语法可能更可取:

var full = F 

然后将扩展为:

let full = Var({name = "full"; value = F});;

这可能与camlp4有关吗?如果可以,我该怎么做?

(进一步考虑, :letname: 语法或类似的东西会更通用,在更多领域有用)

4

2 回答 2

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
于 2012-02-11T18:56:29.903 回答
0

是的,这是可能的。首先阅读一些 camlp4 教程以了解它的工作原理并提出更具体的问题。

于 2012-01-05T08:12:36.567 回答