9

我在 expr.ml 文件中有一个 expr 类型。在 parser.mly(OCamlyacc 文件)中,我定义了 expr 规则并给出了类型:

    %start expr
    %type <expr> expr

但是,我得到:

    File "parser.mli", line 34, characters 48-52:
    Error: Unbound type constructor expr

我尝试添加

    %{
      open Expr
    %}

在 .mly 文件的开头,但它仍然不起作用。如何在外部文件中定义此 expr 类型并将其用作我的规则的返回值?谢谢。

4

3 回答 3

10

您需要expr使用模块名称限定类型。即,如果它在expression.ml(使用type expr = ...)中定义,您应该使用

%type <Expresssion.expr> main

E使用模块名称时请注意大写。

于 2011-06-15T17:07:51.040 回答
2

我不确定我是否理解正确。

但是您正在为循环依赖而苦苦挣扎?假设T包含您的类型并调用解析器,P. P不能产生类型,T.t因为T取决于P,而不是相反。通常,我创建了包含类型信息的第三个文件T'.

例如,

毫升

 let parse filename : T'.t =
     filename
         |> open_in
         |> Lexing.from_channel
         |> P.command L.token

P.mly

%type <T'.t> command
%start command
%%

T'.ml

type t = Label of String
       | Integer of String
       | Float of string
       | Star of t
于 2011-06-15T15:28:20.353 回答
1

Ocamlyacc 不允许您在 interface ( .mli) 文件中指定要生成的文本。因此,无论您在何处指定进入接口的类型(令牌或规则的类型),您都需要使用完全限定的类型。

在这里,您似乎可以使用完全限定的类型,但有时这是不可能的,因为该类型涉及函子应用程序。有几种解决方法:

  • 安排在单独的编译单元中构建所有仿函数。这很容易,但如果函子涉及令牌类型,则不起作用。
  • 对 ocamlyacc 生成的.mli文件进行后处理以添加标题。你几乎可以用这种方式做任何事情,但它既丑陋又烦人。
  • 使用Menhir,一种改进的 Ocamlyacc 替代品。这是一个额外的依赖,但它确实解决了 Ocamlyacc 的主要缺点。
于 2011-06-16T13:25:15.690 回答