简体   繁体   中英

How to use Menhir error messages generation via OCamlbuild?

I am using the --compile-errors functionality of menhir and I'm quite happy with it. I'm also using ocamlbuild to manage the compilation of my project. Since the project is quite basic, the build infrastructure has remained trivial so far.

I have a single _tags file and a simple Makefile at the root of the project. I don't have a myocamlbuild.ml file yet. The _tags file contains just one line:

<src/*>: package(ppx_deriving.std)

The relevant part of the Makefile is

all: src/ParsingErrors.ml
    ocamlbuild $(OPTIONS) src/Main.native

src/ParsingErrors.ml: src/Handcrafted.messages src/Parser.mly
    menhir --compile-errors src/Handcrafted.messages src/Parser.mly > src/ParsingErrors.ml

OPTIONS = -j 4 -use-menhir -use-ocamlfind -yaccflag --table -pkgs menhirLib,str,unix

OCamlbuild and Menhir are usually well integrated, but --compile-errors seems to be a fairly new functionality. My setup is not ideal because I dislike having an automatically generated file, src/ParsingErrors.ml , in my source directory instead of the build directory. What would be the best way to explain to OCamlbuild that I want Menhir to build this error messages file? Changing the naming convention of my files (into src/Parser.messages and src/Parser.ml , for example) does not bother me if it simplifies things.

NB: although I have myocamlbuild.ml files in other projects, I copied them from online sources. I find them hard to decipher and I don't really understand how to write these things.

The best place to look for an answer to this question is in Menhir's distribution, since Menhir uses "menhir --compile-errors" and ocamlbuild in its own compilation process.

The file to look for is src/myocamlbuild.ml in the source tarball .

Here is a relevant excerpt:

(* This rule generates an .ml file [target] from an .mly file [grammar] and a
   .messages file [messages]. *)

(* If the name of a witness file is passed, it is made an additional
   dependency. This triggers a separate rule (see below) which performs a
   completeness check, that is, which checks that the .messages file lists
   every possible syntax error. *)

let compile_errors grammar messages (witness : string list) target =
  rule
    "menhir/compile_errors"
    ~prod:target
    ~deps:([ grammar; messages ] @ witness)
    (fun env _ ->
      let grammar = env grammar in
      let tags = tags_of_pathname grammar ++ "ocaml" ++ "menhir" in
      Cmd(S[
        !Options.ocamlyacc; (* menhir *)
        T tags;
        P grammar;
        A "--compile-errors"; P (env messages);
        Sh ">"; Px (env target);
      ]))

(* A generic version of the above rule, with uniform naming. *)

let generic_compile_errors (check_completeness : bool) =
  compile_errors
    (* sources: *)
    "%.mly" "%Messages.messages"
    (* if present, this dependency forces a completeness check: *)
    (if check_completeness then [ "%Messages.witness" ] else [])
    (* target: *)
    "%Messages.ml"

I would be happy to discuss with the ocamlbuild maintainers whether some parts of Menhir's myocamlbuild.ml could be moved into ocamlbuild's standard set of rules. (Hi Gabriel!)

The feature is indeed not supported in current ocamlbuild versions. To add it in your myocamlbuild.ml plugin, you would have to define a new build rule. If you are scared by what is inside myocamlbuild.ml , you may be interested in the new ocamlbuild manual , in particular its section on plugins .

I just opened an issue report #121 on the ocamlbuild repository to track this missing feature. Are you interested in learning enough about ocamlbuild to write a proper rule for this and contribute it to the next ocamlbuild version? If yes, feel free to the github issue and start asking questions about how to implement it, I would be glad to help. If not, I'll try to implement it myself when I have some time.

In the meantime, note that it's much easier to define a one-shot rule for specific files than a generic rule. If you are ready to hardcode the sourcefiles you use, you could have something that would look very similar to the Makefile rule. I don't have the time today to write and check this rule, but I'll try to come back tomorrow if someone else hasn't done it in between.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM