如何从Ocaml编译器中获取更多信息

时间:2017-12-31 18:52:08

标签: compiler-errors syntax-error ocaml

我在ocamlc遇到了最困难的时间,而且这是非常无法提供信息的错误消息。现在,当我编译我的一个文件时,它给了我

Error: Syntax Error

在文件的最后一行,这是空的。所以,我假设我缺少一些开括号或其他东西,我不确定。无论如何,在生产环境中使用Ocaml的人如何处理这个?是否有任何可用的工具可以提供关于词法分析器期望的字符的任何提示,或者只是更好的错误消息?

具体来说,我正在寻找像this这样的工具,它看起来很棒。但看起来它不再处于开发阶段,但这看起来像是一个将Ocaml编译为Javascript的工具,这不是我想要的最终结果。

关于人们通常如何解决Ocaml语法错误的任何建议都会很棒。

1 个答案:

答案 0 :(得分:3)

鉴于one.ml:

let a = 42 in
let f x = x + a
let g x = x + x

编译时会出现此错误:

$ ocamlc one.ml 
File "one.ml", line 3, characters 0-3:
Error: Syntax error

ocamlc放弃了在第三行的let上理解这一点,因为在那一点上,第2行唯一可能的延续是in和另一个表达式(或{{的延续) 1}},如x + x)。这里的根本问题是ocamlc没有在第1行的末尾抛出错误,因为ocamlc试图允许正确的OCaml 和一堆你可以粘贴到交互式中的表达式会话。它甚至在文件中允许+ x in ...,这是荒谬的:;;只需要交互式,因为没有一些特殊的终止规则(比如Python的空白行结束定义 - 但只是交互式)OCaml我们不知道表达式不会由运算符和另一个表达式继续。 ocamlc试图宽恕混乱,以至于混淆被延长,而不是纠正。

那么适当的OCaml是什么?无论出于何种原因,它没有得到很好的记录。但是当你明白某些形式可以放在最左边时,你可以很快感受到它。在一个文件中,某种形式只能作为第一种形式的子表达式存在,或者如果你试图读取写得好的OCaml,同时记住OCaml中的空白是无意义的,就像在C中一样:OCaml不使用在定义之间用空行来理解那些定义是分开的,那么它们是如何将它们分开的呢?

或者,您可以从一些规则开始。 "除了作为子表达式外,不要使用;;。" "不要尝试执行副作用,除非let ... in","表示需要右侧的操作符的分号,而不是终结符",等

所以不是one.ml,而是任何一个都可以工作:

let () =

let a = 42
let f x = x + a
let g x = x + x

或(显然这是不好的风格):

let f x =
  let a = 42 in
  x + a
let g x = x + x

two.ml有另一个常见错误:

let f x = let a = 42 in x + a let g x = x + x

您将收到“语法错误”#39;在第5行,字符0 = 0。哪个是ocamlc到达文件的末尾,仍然没有看到必须遵循的let () = print_endline "hi"; let f x = x + x (或in的延续)。因为第2行的x + x表示第4行的;必须是第1行let的子表达式。

而不是两个.ml,其中任何一个都没关系:

let

或(又是糟糕的风格,但想象一下分号):

let () =
  print_endline "hi"

let f x = x + x

虽然你也可以得到一个'裸露的' let () = print_endline "hi" let f x = x + x 的语法错误,即使是对OCaml很新的人也会在他们发现线条和角色范围被抱怨时识别出这样的错误,因此这些错误在one.ml和2的级别上并不令人沮丧。毫升