2

我想编写一个 OCaml 模块,该模块具有一个compile函数,该函数将接受一个包含 OCaml 程序的字符串,并将编译结果输出为正确或错误,在错误情况下,输出有关第一个错误的行和字符的信息。我不在乎错误是什么(至少现在是这样)。

一个基本的模块类型是:

module type Compile =
    sig
        type result = Correct | Error of (int*int)
        val compile : string -> result
    end

至少有两种根本不同的方式来实现它:

  1. 快速破解方式——将字符串与程序一起写入文件,使用 Unix 进程ocamlc在命令行上调用并解析 stderr;
  2. 正确的方法——使用 OCaml 工具来分析代码。

关于(1),我无法掌握 stderr 的内容。我开始使用 Unix.open_process_in,它将标准输出重定向到一个 in_channel ,然后我可以读取它。由于ocamlcgo to stderr (而不是 stdout) 输出的编译错误,我尝试使用

let ic = Unix.open_process_in "ocamlc test.ml 2>&1" 

以便 stderr 的内容在命令行被重定向到 stdout。我希望ic 这样可以包含编译错误。不幸的是,情况并非如此,ic仅包含End_of_file.

然后我转到Unix.create_process命令,因为它允许我为 out、in、err 选择新通道。但是我在选择这些频道时遇到了麻烦。输出通道应该是什么,以便我可以在我的程序中读取它?

关于(2),您认为(合理)简单的方法是什么?

非常感谢您的帮助!

4

2 回答 2

3

关于 2),OCaml 安装通常有一个compiler-lib目录,其中包含构成编译器的许多模块,包括解析器。这没有记录,但可用于进行编译和类型检查。对于解析,还有 Camlp4,它可以用来做除了预处理之外的事情(我想你可以将 Camlp4 加载到你的程序中并将它用作库,可能在对其进行一些修补之后),但它只包含语法而不是类型检查器。

于 2011-02-19T23:04:03.053 回答
2

关于1)我认为你做错了什么。在我的机器上:

> ocaml unix.cma
        Objective Caml version 3.12.0

# let ic = Unix.open_process_in "ocamlc test.ml 2>&1";;
val ic : in_channel = <abstr>
# input_line ic;;
- : string = "File \"test.ml\", line 1, characters 0-1:"
# input_line ic;;
- : string = "Error: I/O error: test.ml: No such file or directory"
# input_line ic;;
Exception: End_of_file.

Unix.create_process一种方法是传递Unix.stdin,以便您new_stdout可以通过程序的标准输入读取进程的输出(这假设您不想将程序的标准输入用于其他目的)。但我使用的更简单的方法是Unix.open_process_full.

关于 2)您可以尝试使用toplevellib.cma(但请注意,这是完全无证和不受支持的)。看看toplevel/toploop.mli分布,特别是Toploop.execute_phrase.

于 2011-02-19T21:57:43.287 回答