This repository provides different tools to work on the error messages of a menhir-generated parser.
The main tool is lrgrep
. It takes:
--cmly
flag to Menhir) If the list of rule is well-formed, it produces an OCaml module that can match the rules against the state of a parser at runtime.
By carefully crafting the rules, one can provide fine-grained message to explain syntax errors.
The repository is is structured as follow:
lrgrep.runtime
library-pp <path-to-frontend.exe>
flag)For now, the main focus is on the [ocaml]() sub-directory, and [ocaml/parse_errors.mlyl]() specifically.
My current workflow is as follow:
-pp frontend
to ocamlc
All the work is done using OCaml 4.14. Make sure you are using the right switch:
$ ocamlc -version
4.14.1
Clone the repository and install dependencies:
$ git clone https://github.com/let-def/lrgrep.git
$ cd lrgrep
$ opam install menhir fix cmon
At this point, make
should succeed (contact me if not) and produce the three binaries: lrgrep.exe
, frontend.bc
and interpreter.exe
.
It is usually better to test with the bytecode frontend as it leads to shorter iteration cycles.
Try the new frontend with some simple examples:
$ ocamlc -c -pp _build/default/ocaml/frontend.bc test_ok.ml
This first example compiled successfully.
$ ocamlc -c -pp _build/default/ocaml/frontend.bc test_ko_01.ml
ocamlc -pp _build/default/ocaml/frontend.bc test_ko_01.ml
File "test_ko_01.ml", line 4, characters 0-3:
4 | let z = 7
^^^
Error: Spurious semi-colon at 2:9
File "test_ko_01.ml", line 1:
Error: Error while running external preprocessor
Command line: _build/default/ocaml/frontend.bc 'test_ko_01.ml' > /tmp/ocamlppbbc3f9
In this one however, there is a syntax error. Luckily, this case is covered by a rule: while the error happens on line 4, it is likely caused by the semi-colon at the end of line 2.
By using the OCAMLPARAM
environment variable, we can instruct all execution of ocaml compilers in the current shell to use our frontend.
$ ./demo/setup_shell.sh
export 'OCAMLPARAM=pp=$PWD/lrgrep/_build/default/ocaml/frontend.bc,_'
# setup_shell commands produces a suitable OCAMLPARAM value
$ eval `./demo/setup_shell.sh`
$ ocamlc test_ko_01.ml
...
Error: Spurious semi-colon at 2:9
...
# In the updated environment, the new frontend is picked up automatically
Now you are ready to iterate on [ocaml/parse_errors.mlyl]() to produce new rules.
Note: unset OCAMLPARAM
to switch back to the normal frontend
Once you made sure your setup is working (make
is (re-)building the frontend and ocamlc
is using it), you can proceed to DEVISING-RULES.md to get started with the error DSL and the associated workflow.
I am trying to document the code. Each of the src, lib, ocaml, and support directories contain a README.md that briefly explains the purpose of this directory.
External dependencies that are worth knowing: