Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using external type declarations with OCamlyacc

I have a type expr in an expr.ml file. In parser.mly (OCamlyacc file), I define the expr rule and give the type :

    %start expr
    %type <expr> expr

However, I get :

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

I tried adding

    %{
      open Expr
    %}

at the beginning of the .mly file but it still doesn't work. How may I define this expr type in an external file and use it as the return value of my rule? Thanks.

like image 937
rochem Avatar asked Jun 15 '11 15:06

rochem


3 Answers

You need to qualify expr type with the module name. I.e., if it is defined in expression.ml (using type expr = ...) you should use

%type <Expresssion.expr> main

Note the capital E when using the module name.

like image 152
nimrodm Avatar answered Dec 18 '22 23:12

nimrodm


I"m not sure if I'm understanding correctly.

But you are struggling with a circular dependency? Let's say T contains your type and calls the parser, P. P cannot produce type T.t since T depends on P, not the other way around. Normally, I've created a third file that contains the type information, T'.

For example,

T.ml

 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
like image 40
nlucaroni Avatar answered Dec 19 '22 01:12

nlucaroni


Ocamlyacc doesn't let you specify text to be generated in the interface (.mli) file. So wherever you specify a type that goes into the interface (the type of a token or rule), you need to use a fully-qualified type.

Here it looks like you can use a fully-qualified type, but sometimes that's not possible because the type involves a functor application. There are several workarounds:

  • Arrange to build all functors in a separate compilation unit. This is easy, but doesn't work e.g. if the functors involve the token type.
  • Do post-processing on the ocamlyacc-generated .mli file to add a header. You can do pretty much anything this way, but it's ugly and annoying.
  • Use Menhir, an improved replacement of Ocamlyacc. It's an additional dependency, but it does solve Ocamlyacc's main shortcomings.
like image 29
Gilles 'SO- stop being evil' Avatar answered Dec 19 '22 00:12

Gilles 'SO- stop being evil'