caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Installing parsers and printers
@ 1994-03-22 14:55 John Harrison
  0 siblings, 0 replies; 2+ messages in thread
From: John Harrison @ 1994-03-22 14:55 UTC (permalink / raw)
  To: caml-list; +Cc: John.Harrison


My interest in CAML is as a metalanguage for an embedded logic (which was of
course ML's original application, hence the name). An important part of this is
the provision of a nice interface to the user who still uses the toplevel loop,
so I have two wishes:

 o I'd like to be able to install a custom printer to display objects of a
   nominated type (in the toplevel loop). I have a logic encoded as a
   recursive type. Of course this is unreadable in its raw form, and it's
   very tedious to have to call a prettyprinter explicitly. Ideally I'd
   like to be able to do something like:

     #install_printer "term" "term_printer";;

   (where `term_printer' is an ML function I have defined), and then have all
   objects of type `term' displayed using that printer. If something this clean
   is not possible I'm willing to dive into C if somebody can advise me on how
   to interface to the system.

 o I'd like to be able to set up some special quotation syntax to parse
   down to a nominated type automatically. I envisage something like:

     #install_parser "<<" ">>" "term_parser";;

   (where `term_parser' is an ML function I have defined). Thereafter if I
   type <<....>>, the system would call the parser on the string "...." and
   that would be the result of evaluation.

   If this is not possible, then I can survive by invoking a parser explicitly
   on a string. However I would really like to suppress recognition of escapes
   like "\n" in this string. Is there a clean way of forcing this, or does
   it necessitate patching the lexer?

It is interesting to note that SML/NJ originally had no such facilities, but
they have been added by Konrad Slind -- see his paper in the Second ML
Workshop: "Object Language Embedding in Standard ML of New Jersey".

I'd be grateful for any help,

John.




^ permalink raw reply	[flat|nested] 2+ messages in thread

* Installing parsers and printers
@ 1994-03-22 16:20 Pierre Weis
  0 siblings, 0 replies; 2+ messages in thread
From: Pierre Weis @ 1994-03-22 16:20 UTC (permalink / raw)
  To: caml-list

This is a long answer to John Harrison.
Abstract:
These kind of facilities are partly supported by Caml Light and completely
available in Caml V3.1. Moreover the development of this kind of
object languages features has been one of the great speciality of our
Caml team (and it is still an active research area today).

> o I'd like to be able to install a custom printer to display objects of a
>   nominated type (in the toplevel loop). I have a logic encoded as a
>   recursive type. Of course this is unreadable in its raw form, and it's
>   very tedious to have to call a prettyprinter explicitly. Ideally I'd
>   like to be able to do something like:
>
>     #install_printer "term" "term_printer";;
>
>   (where `term_printer' is an ML function I have defined), and then have all
>   objects of type `term' displayed using that printer. If something this clean
>   is not possible I'm willing to dive into C if somebody can advise me on how
>   to interface to the system.

This possibility is available in both Caml V3.1 and Caml Light.
In Caml Light the directive has almost the same syntax as yours:

new_printer "term" term_printer;;

In Caml V3.1 you just type in:

#printer term_printer;;

the system is able to find out the type of term_printer by itself...

>     #install_parser "<<" ">>" "term_parser";;

This is available in Caml V3.1 with the grammar feature, it's called 
``set default grammar'' and is used like in this session:

We start by setting the default user grammar to the predefined parser
of Caml for expressions (hence the Caml:Expr annotation, meaning the entry
point named Expr, in the grammar named Caml):

   CAML (decstation) (V3.1.2) by INRIA Thu Feb 4

##set default grammar Caml:Expr;;
Default grammar is now Caml:Expr
Pragma () : unit

Now we can parse Caml expressions either directly using the << >> notation:

#<<let x=1 in x  +  1>>;;
<:Caml:Expr< let x = 1 in x+1 >> : ML

or by calling directly the proper entry point for the grammar:

#<:Caml:Expr< let x = 1 in x + 1>>;;
<:Caml:Expr< let x = 1 in x+1 >> : ML

As you may have notice the toplevel has already a default
pretty-printer for values of type ML (the type of Caml expressions
abstract syntax trees). If we turn off this pretty-printer and reset
the default way of printing, we can see the real abstract syntax tree of 
pieces of Caml concrete syntax:

##default printer for type ML;;
() : unit

Now:

#<< let x = 1 in x + 1>>;;
(MLin
 ((MLlet ((MLvarpat "x"),(MLconst (mlint 1)))),
  (MLapply ((MLvar "+"),(MLpair ((MLvar "x"),(MLconst (mlint 1)))),[])))) :
 ML

We can define another pretty-printer for values of the type ML. For
instance ``print_caml_expr'' which is predefined too and which does'nt
print the french brackets << and >>:

#print_caml_expr;;
<fun> : ML -> unit

#let s = << let rec x = 1 in z - t>>;;
Value s is
      (MLin
       ((MLrec (MLlet ((MLvarpat "x"),(MLconst (mlint 1))))),
        (MLapply ((MLvar "-"),(MLpair ((MLvar "z"),(MLvar "t"))),[])))) :
      ML

##printer print_caml_expr;;
New printer defined for type: ML
() : unit

#s;;
let rec x = 1 in z-t : ML

Just for fun, let use another predefined grammar in Caml, to get
escapes. We reuse the AST bound to s inside another AST:

#<:CAML<let z = 1 in #s>>;;
let z = 1 in let rec x = 1 in z-t : ML

And to end with, let's obtain the Caml syntax of a Caml type, using
two predefined grammars: the gtype grammar of concrete representation of types
and the Caml grammar (we now compose grammars)...

#let ast_of_int_arrow_int = <:Caml < <:gtype< int -> int>> >>;;

Remember that this is really Caml abstract syntax:
##default printer for type ML;;
() : unit

#ast_of_int_arrow_int;;
(MLapply
 ((MLvar "Gconsttype"),
  (MLpair
   ((MLconst (mlsystyp "->")),
    (MLlist
     ((MLapply
       ((MLvar "Gconsttype"),
        (MLpair ((MLconst (mlsystyp "int")),(MLvar ""))),[])),
      [(MLapply
        ((MLvar "Gconsttype"),
         (MLpair ((MLconst (mlsystyp "int")),(MLvar ""))),[]))])))),
  [])) :
 ML

I admit that this is a bit complex to understand, but notice how the
concrete notation is compact, compared to what we ought to enter if
this feature were not available.

>It is interesting to note that SML/NJ originally had no such facilities, but
>they have been added by Konrad Slind -- see his paper in the Second ML
>Workshop: "Object Language Embedding in Standard ML of New Jersey".

It is even more interesting to notice that a Yacc interface has been
added to Caml in 1984 by Philippe Lechenadec, and that this interface
allows user's defined grammars inside quotations " " (this has been
abandonned when the double quote symbol has been used for strings!).
Moreover the grammar feature as presented above was implemented in Caml by
Michel Mauny during the years 1987-1988... 

Now this have been abandoned in Caml Light for two main reasons: first
the implementation had to remain small, and these features are
complex; second this was mainly considered as a toplevel feature, and
not very important compared to the development of a good compiler
featuring an easy separate compilation facility.

Nowadays, Michel Mauny and Daniel de Rauglaudre are working on a new
version of Caml Light featuring concrete language features. This may
be available some day ...

Pierre Weis




^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~1994-03-22 16:25 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1994-03-22 14:55 Installing parsers and printers John Harrison
1994-03-22 16:20 Pierre Weis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).