2

作为我在大学学习的编译器原理课程的一部分,我们正在编写一个在 OCaml 中实现的编译器,它将 Scheme 代码编译成类似 CISC 的程序集(只是 C 宏)。编译器的基本操作是这样的:

  1. 读取*.scm文件并将其转换为 OCaml string
  2. 解析字符串并执行各种分析。
  3. 在语义分析器的 AST 输出上运行代码生成器,将文本输出到*.c文件中。
  4. 使用 GCC 编译该文件并在终端中运行它。

好吧,一切都很好,除了这个:我正在尝试读取一个输入文件,它大约有 4000 行长,基本上是一个混合了 Scheme if&的巨大表达式and。我正在通过utop. 当我尝试读取输入文件时,我立即收到堆栈溢出错误消息。我最初的猜测是该文件对于 OCaml 来说太大了,无法处理,但我找不到任何支持该理论的文档。

有什么建议么?

4

2 回答 2

1

最大字符串长度由 给出Sys.max_string_length。对于 32 位系统,它很短:16777211。对于 64 位系统,它是 144115188075855863。

除非您使用的是 32 位系统,并且您的 4000 行文件超过 16MB,否则我认为您没有达到字符串长度限制。

当字符串太长时,堆栈溢出不是您期望看到的。

你更有可能有无限递归,或者可能只是一个非常深的嵌套计算。

于 2016-01-24T08:20:57.450 回答
0

好吧,事实证明,限制是 OCaml 配置使用的最大内存量。

我在终端中运行了以下命令以增加配额:

export OCAMLRUNPARAM="l=5555555555"

这就像一个魅力——我设法几乎瞬间读取和编译输入文件。

出于参考目的,这是读取文件的代码:

let file_to_string input_file =
  let in_channel = open_in input_file in
  let rec run () =
    try
      let ch = input_char in_channel in ch :: (run ())
    with End_of_file ->
      ( close_in in_channel;
       [] )
  in list_to_string (run ());;

哪里list_to_string是:

let list_to_string s =
  let rec loop s n =
    match s with
    | [] -> String.make n '?'
    | car :: cdr ->
       let result = loop cdr (n + 1) in
       String.set result n car;
       result
  in
  loop s 0;;

有趣的是——我file_to_string用尾递归写的。这防止了堆栈溢出,但由于某种原因进入了无限循环。那好吧...

于 2016-02-14T13:10:50.117 回答