Previous Contents Next

Chapter 6   Extending the syntax of OCaml

6.1   Introduction

Syntax extensions in OCaml can be done by extending the grammars entries of the OCaml syntax. All grammars entries are defined in the module named Pcaml. They all return values of types defined in the module MLast: nodes of these types can be created using the predefined quotation expansion q_MLast.cmo.

The entries in Pcaml are:

Most of these entries are generally defined (``extended'') with several ``levels'' (see chapter 2). Some of them are labelled, in order to be able to extend them or to insert other levels.

The levels and their possible labels are not predefined. It depend on how the syntax define them. To see which labels are defined and which rule they contain, enter the toplevel:

            $ ocaml -I `camlp4 -where`
Then type for the normal syntax:

       #load "camlp4o.cma";;
       Grammar.Entry.print Pcaml.expr;; (* for the expressions *)
       Grammar.Entry.print Pcaml.patt;; (* for the patterns *)
                                        (* ... and so on *)
For the revised syntax, load "camlp4r.cma" instead. If you defined another syntax of the whole language or want to see the other syntaxes provided, load it before, and call Grammar.Entry.print of the desired grammar entry. Look at the manual page (man camlp4 in the shell) to see all available syntaxes and extensions.

Once you have the list of the grammar entry you want to extend and the possible level label, you can do your extension.

6.2   Example: ``repeat until'' like in Pascal

If you read all this tutorial, you are able to understand this complete example. If you did not, just create the files and type the indicated commands.

Write first a file named foo.ml containing:
       open Pcaml;;
       EXTEND
         expr: LEVEL "top"
           [[ "repeat"; e1 = expr; "until"; e2 = expr ->
                 <:expr< do { $e1$; while not $e2$ do { $e1$; } } >> ]];
       END;;
The compilation of this file can be done by typing under the shell (the dollar is the shell prompt):
       $ ocamlc -pp "camlp4o pa_extend.cmo q_MLast.cmo" -I `camlp4 -where` \
           -c foo.ml
Here is the file bar.ml containing a repeat..until statement:
       let main () =
         let i = ref 0 in
         repeat print_int !i; incr i until !i = 10;
         print_newline ()
       let _ = main ()
You can compile it by typing:
       $ ocamlc -pp "camlp4o ./foo.cmo" bar.ml
And run it:
       $ ./a.out
       0123456789
Or just pretty print the program with the expanded syntax:
       $ camlp4o ./foo.cmo pr_o.cmo bar.ml
       let main () =
         let i = ref 0 in
         begin print_int !i; incr i end;
         while not (!i = 10) do print_int !i; incr i done;
         print_newline ()
       ;;
       main ();;

6.3   Example: a constant

If you want to have the equivalent of a #define of C, you can write for example, if you want FOO to be replaced by 54 in expressions and patterns:

       open Pcaml;;
       EXTEND
         expr: LEVEL "simple"
           [[ UIDENT "FOO" -> <:expr< 54 >> ]];
         patt: LEVEL "simple"
           [[ UIDENT "FOO" -> <:patt< 54 >> ]];
       END;;
The compilation of this file can be done by typing:

       $ ocamlc -pp "camlp4o pa_extend.cmo q_MLast.cmo" -I `camlp4 -where` \
           -c foo.ml
Here is the file bar.ml containing FOO constants:

       FOO;;
       function FOO -> 22;;
You can compile it by typing:

       $ ocamlc -pp "camlp4o ./foo.cmo" bar.ml
You can just pretty print the program with the expanded syntax:

       $ camlp4o ./foo.cmo pr_o.cmo bar.ml
       54;;
       function 54 -> 22;;

Previous Contents Next