c++ - 如何使用 Genlex 构建 OCaml 源代码

标签 c++ linux bash gcc ocaml

我是 OCaml 的新手,但它的文档让我哭了。 我想在 ocaml 上编写一个解析器并将其集成到 c++ 项目中。

我已经使 c++ - OCaml 绑定(bind)正确,就像这里描述的那样 http://www.mega-nerd.com/erikd/Blog/CodeHacking/Ocaml/calling_ocaml.html

所以我可以得到一个可执行文件,它使用这样的命令调用 OCaml 代码:

  • cat 构建.sh
  • #/bin/庆典
  • mkdir -p 构建
  • ocamlopt -c -o build/ocaml-called-from-c.cmx ocaml-called-from-c.ml
  • ocamlopt -output-obj -o build/camlcode.o build/ocaml-called-from-c.cmx
  • gcc -g -Wall -Wextra -c c-main-calls-ocaml.c -o build/c-main-calls-ocaml.o
  • gcc build/camlcode.o build/c-main-calls-ocaml.o -lm -L ~/.opam/4.01.0/lib/ocaml -lasmrun -o c-main-calls-ocaml -ldl

但后来我添加了“open Genlex;;”到 ocaml-called-from-c.ml 并尝试编写简单的解析器,例如,如下所述:

http://caml.inria.fr/pub/docs/manual-ocaml/libref/Genlex.html

正如它所说: “人们应该注意到,只有通过 camlp4 扩展才能使用解析器关键字和相关的流符号。这意味着必须对其源进行预处理,例如使用编译器的“-pp”命令行开关。”

但是

ocamlopt -pp camlp4 -o build/ocaml-called-from-c.cmx -c ocaml-called-from-c.ml

得到

解析错误:条目 [implem] 为空 运行外部预处理器时出错 命令行:camlp4 'ocaml-called-from-c.ml' >/tmp/ocamlpp162c63

没有 -pp 它落在:

解析器 | [< n1 = 解析原子; n2 = parse_remainder n1 >] -> n2

文件“ocaml-called-from-c.ml”,第 99 行,字符 13-14: 错误:语法错误

最佳答案

在我看来,Genlex 是为快速破解而设计的。如果您的语言非常有趣,您可能想要研究 Menhir,正如 Basile Starynkevitch 所建议的那样。

Genlex 文档告诉您的是,make_lexer 函数使用流。尽管流本身是核心语言的一部分(在 Stream module 中),但很酷的流语法是 OCaml 的扩展。语法曾经是语言的一部分,但不久前被移出到扩展中。

OCaml 的语法扩展领域目前处于相当不稳定的状态。我能找到的关于 Stream 扩展的最完整描述在 Chapter 2 of the old camlp4 manual 中。 .在 OCaml.org's Stream Expression page 也有很好的教程说明。 .

我能够使文档中的示例按如下方式工作。我在 OS X 10.9.2 上使用 OCaml 4.01.0。

我的源文件 gl.ml 看起来像这样。 (我添加了一个 main 函数。)

open Genlex

let lexer = make_lexer ["+";"-";"*";"/";"let";"="; "("; ")"]

let rec parse_expr = parser
    | [< n1 = parse_atom; n2 = parse_remainder n1 >] -> n2
and parse_atom = parser
    | [< 'Int n >] -> n
    | [< 'Kwd "("; n = parse_expr; 'Kwd ")" >] -> n
and parse_remainder n1 = parser
    | [< 'Kwd "+"; n2 = parse_expr >] -> n1+n2
    | [< >] -> n1

let main () =
    let s = Stream.of_channel stdin in
    let n = parse_expr (lexer s) in
    Printf.printf "%d\n" n

let () = main ()

我编译如下。

$ ocamlopt -o gl -pp camlp4o gl.ml

我运行如下:

$ echo '3 + (5 + 8)' | gl
16

因此,Genlex 可以发挥作用。

对于您的情况,我认为您的命令行如下所示:

$ ocamlopt -o gl.o -c -pp camlp4o gl.ml

这对我有用。它创建 gl.ogl.cmx

这可能并不能解决您所有的问题,但希望对您有所帮助。

关于c++ - 如何使用 Genlex 构建 OCaml 源代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24720757/

相关文章:

linux - 如何同时设置 niceness 和 process affinity?

LINUX:如何软链接(soft link)所有子目录中的特定文件

c++ - 是否可以将重载方法传递给 std::thread

linux - 创建包含引导加载程序和内核的可引导软盘时出错

c++ - Windows、Linux 和内存管理

linux - 如何在共享的 Linux 内核上运行 Docker 守护进程?

bash - rsync:带空格、引号和日文字母的文件名

c++ - c中的指针,双指针和三重指针

c++ - 为什么我可以在列表中删除对象后访问其成员变量?

c++ - C++ 中的模板