Reputation: 19
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
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