Gleb Kolobkov
Gleb Kolobkov

Reputation: 19

How to build OCaml source which using Genlex

I'm new to OCaml, but its documentation makes me cry. I want to write a parser on ocaml and integrate it into c++ project.

I've made c++ - OCaml binding right like it is described here http://www.mega-nerd.com/erikd/Blog/CodeHacking/Ocaml/calling_ocaml.html

so I can get an executable that calling OCaml code with such commands:

But then I've add "open Genlex;;" to ocaml-called-from-c.ml and try to write simple parser for example, as it described here:

http://caml.inria.fr/pub/docs/manual-ocaml/libref/Genlex.html

As it saying: "One should notice that the use of the parser keyword and associated notation for streams are only available through camlp4 extensions. This means that one has to preprocess its sources e. g. by using the "-pp" command-line switch of the compilers."

but

ocamlopt -pp camlp4 -o build/ocaml-called-from-c.cmx -c ocaml-called-from-c.ml

gets

Parse error: entry [implem] is empty Error while running external preprocessor Command line: camlp4 'ocaml-called-from-c.ml' > /tmp/ocamlpp162c63

without -pp it falling on:

parser | [< n1 = parse_atom; n2 = parse_remainder n1 >] -> n2

with

File "ocaml-called-from-c.ml", line 99, characters 13-14: Error: Syntax error

Upvotes: 0

Views: 401

Answers (1)

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66818

In my opinion, Genlex is intended for quick hacks. If your language is at all interesting you might want to look into Menhir, as Basile Starynkevitch suggests.

What the Genlex documentation is telling you is that the make_lexer function uses streams. Although streams themselves are part of the core language (in the Stream module), the cool stream syntax is an extension of OCaml. The syntax used to be part of the language, but was moved out into an extension a while ago.

The area of syntax extensions to OCaml is in a rather fluid state at the moment. The fullest description I can find for the Stream extension is in Chapter 2 of the old camlp4 manual. There is also a good tutorial description at OCaml.org's Stream Expression page.

I was able make the example from the documentation work as follows. I'm using OCaml 4.01.0 on OS X 10.9.2.

My source file gl.ml looks like this. (I added a main function.)

open Genlex

let lexer = make_lexer ["+";"-";"*";"/";"let";"="; "("; ")"]

let rec parse_expr = parser
    | [< n1 = parse_atom; n2 = parse_remainder n1 >] -> n2
and parse_atom = parser
    | [< 'Int n >] -> n
    | [< 'Kwd "("; n = parse_expr; 'Kwd ")" >] -> n
and parse_remainder n1 = parser
    | [< 'Kwd "+"; n2 = parse_expr >] -> n1+n2
    | [< >] -> n1

let main () =
    let s = Stream.of_channel stdin in
    let n = parse_expr (lexer s) in
    Printf.printf "%d\n" n

let () = main ()

I compile as follows.

$ ocamlopt -o gl -pp camlp4o gl.ml

I run as follows:

$ echo '3 + (5 + 8)' | gl
16

So, Genlex can be made to work.

For your case, I think your command line would look like this:

$ ocamlopt -o gl.o -c -pp camlp4o gl.ml

This works for me. It creates both gl.o and gl.cmx.

This probably doesn't solve all your problems, but I hope it helps.

Upvotes: 1

Related Questions