Creating a simple camlp4 grammar extension

549 views Asked by At

Given this type:

type 'a variable = { name: string; mutable value: 'a } 

I'm trying to create a syntax extension that would accept this syntax:

var foo = true

...and convert it to:

let foo = { name = "foo"; value = true }

Here's my attempt:

open Camlp4.PreCast
open Syntax

type 'a variable = { name: string; mutable value: 'a } 

EXTEND Gram
  expr: LEVEL "top"
     [ [ "var"; v = a_LIDENT; "=";  e = expr -> 
         <:expr< let $lid:v$ = { name= $`str:v$ ; value = $e$ } in  $e$ >>
     ] ]
  ;
END

(I'm pretty sure it needs that $e$ at the end of the substitution as a way of saying "the rest", but it also looks kind of suspect given that we want the value field of the record to have the value of the expression on the right - initially I did not have the ending $e$ there and got the same error)

I try compiling with:

ocamlc -I +camlp4 camlp4lib.cma -pp camlp4orf -c pa_var.ml

Which results in:

File "pa_var.ml", line 10, characters 50-51:
While expanding quotation "expr" in a position of "expr":
  Parse error: "}" expected after [label_expr_list] (in [expr])

File "pa_var.ml", line 1, characters 0-1:
Error: Preprocessor error

I do not know know why it seems to want to have a "}" after the name field of the record. (Otherwise, am I on the right track here?)

1

There are 1 answers

5
gasche On BEST ANSWER

The error is that you use camlp4orf, which uses standard syntax for the code, but revised syntax for the quotations, along with a field name value, which is a keyword in OCaml revised syntax. The simplest fix is to uses camlp4oof to use standard syntax everywhere, but you could also rename that field.

PS: I really don't think it is necessary to write a Camlp4 extension to do this. I would suggest living with the redundancy and using let foo = var "foo" true instead. That would simplify maintenance, interaction with other codebases, etc.

PPS: A couple more comments :

  • you don't want to implement it that way; if you want to catch toplevel declaration phrases let x = foo;;, you must live in struct_item, not expr, and in expr you may want to catch local declarations of the form var <lid> = <expr> in <expr>.

  • If you insist on using Camlp4, you should avoid grammar modification using EXTEND, as you are doing right now. Instead choose let foo = VAR true as your concrete syntax, and use the Camlp4Filters mechanism to transform this into what you want. This will be much more robust and simple to implement.