How to run ocamlyacc generated code in utop

I’m a newbie in OCAML. For this example on using ocamlyacc: OCaml - Lexer and parser generators (ocamllex, ocamlyacc). I can compile and run the calc program. How do I run calc.ml in utop? When I do this in utop

open Parser;;
open Lexer;;
#use "calc.ml";;

I get this error

File "calc.ml", line 5, characters 19-30:
5 |       let result = Parser.main Lexer.token lexbuf in
                       ^^^^^^^^^^^
Error: Unbound value Parser.main

Here are the files from the above website. parser.mly:

%token <int> INT
%token PLUS MINUS TIMES DIV
%token LPAREN RPAREN
%token EOL
%left PLUS MINUS        /* lowest precedence */
%left TIMES DIV         /* medium precedence */
%nonassoc UMINUS        /* highest precedence */
%start main             /* the entry point */
%type <int> main
%%
main:
    expr EOL                { $1 }
;
expr:
    INT                     { $1 }
  | LPAREN expr RPAREN      { $2 }
  | expr PLUS expr          { $1 + $3 }
  | expr MINUS expr         { $1 - $3 }
  | expr TIMES expr         { $1 * $3 }
  | expr DIV expr           { $1 / $3 }
  | MINUS expr %prec UMINUS { - $2 }
;

lexer.mll:

{
open Parser        (* The type token is defined in parser.mli *)
exception Eof
}
rule token = parse
    [' ' '\t']     { token lexbuf }     (* skip blanks *)
  | ['\n' ]        { EOL }
  | ['0'-'9']+ as lxm { INT(int_of_string lxm) }
  | '+'            { PLUS }
  | '-'            { MINUS }
  | '*'            { TIMES }
  | '/'            { DIV }
  | '('            { LPAREN }
  | ')'            { RPAREN }
  | eof            { raise Eof }

calc.ml:

let _ =
  try
    let lexbuf = Lexing.from_channel stdin in
    while true do
      let result = Parser.main Lexer.token lexbuf in
      print_int result; print_newline(); flush stdout
    done
  with Lexer.Eof ->
    exit 0

You need to load your lexer and parser in your toplevel session, opening is not enough.
You can use the #load command for that (#load "parser.cmo";; then #load "lexer.cmo";;).

In utop when I do

#load "parser.cmo";;
#load "lexer.cmo";;
#use "calc.ml";;

I get

File "calc.ml", line 1:
Error: The files parser.cmo
       and /home/ocamlnewbie/.opam/default/lib/ocaml/compiler-libs/parser.cmi
       make inconsistent assumptions over interface Parser

I compile everything using the same instructions from the website:

ocamllex lexer.mll
ocamlyacc parser.mly
ocamlc -c parser.mli
ocamlc -c lexer.ml
ocamlc -c parser.ml
ocamlc -c calc.ml
ocamlc -o calc lexer.cmo parser.cmo calc.cmo

How do I correct the error?

Two solutions, either one should work:

  • Use ocaml instead of utop
  • rename parser.mly and lexer.mll to give them less generic names

The issue is that utop, unlike the default toplevel, gives you access to the compiler’s internal libraries by default, and the names Parser and Lexer conflict with internal compiler modules.

1 Like

Ahh … I see. Thanks! It works now … onward …