caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Matthieu Wipliez <mwipliez@yahoo.fr>
To: caml-list@yquem.inria.fr
Subject: Re : [Caml-list] Parsing simple type expressions
Date: Tue, 6 Jan 2009 22:49:41 +0000 (GMT)	[thread overview]
Message-ID: <524796.35746.qm@web27006.mail.ukl.yahoo.com> (raw)
In-Reply-To: <4963C8AD.8010206@ens-lyon.org>

[-- Attachment #1: Type: text/plain, Size: 3650 bytes --]

Dear caml-list,

here you can find another way of doing what Paolo wants to do.

Basically the point was to reuse as much (well-tested) code as I could, so I tried to use Camlp4 to parse a type definition, and work from there.

You can find in Common the definition of the AST that Paolo provided us with, along with a string_of function and a parse_type function overidden at runtime. In Pa_exp_ext a syntax extension extends the OCaml standard syntax with a rule that parses a type and End Of Input, and in Pa_exp is the driver that loads:
  - Camlp4OCamlRevisedParser the revised syntax parser,
  - Camlp4OCamlParser the "normal" syntax parser,
  - and "pa_exp_ext" our parser.

Actually, Pa_exp acts as the standard "camlp4" executable, loading parsers and stuff.

Please note that this example is incomplete because Pa_exp_ext.Make.convert_type does not take into account the syntax of applied types, which are tranformed using the function "ident_of_ctyp" from Camlp4Ast.mlast which I did not have time to code.

However it is my belief that these files provide a (very interesting) complete example of how camlp4 can be used to parse parts of OCaml syntax without having to write the syntax rules over and over, while using the mysterious quotations :-)

Having spent a couple of hours on this, I hope this helps anyone that is having a look at camlp4 to do what they would like to do,

Cheers and la multi ani "happy new year",
Matei



----- Message d'origine ----
> De : Martin Jambon <martin.jambon@ens-lyon.org>
> À : David Allsopp <dra-news@metastack.com>
> Cc : OCaml mailing list <caml-list@yquem.inria.fr>; Paolo Donadeo <p.donadeo@gmail.com>
> Envoyé le : Mardi, 6 Janvier 2009, 23h10mn 05s
> Objet : Re: [Caml-list] Parsing simple type expressions
> 
> David Allsopp wrote:
> > ocamlyacc - you can get most of it for free out of parsing/parser.mly in the 
> OCaml sources... the section on type expressions starts at line 1144 for OCaml 
> 3.11.0.
> 
> Our json-wheel library is a complete example:
> 
> http://martin.jambon.free.fr/json-wheel.html
> 
> 
> Martin
> 
> >> -----Original Message-----
> >> From: caml-list-bounces@yquem.inria.fr [mailto:caml-list-
> >> bounces@yquem.inria.fr] On Behalf Of Paolo Donadeo
> >> Sent: 06 January 2009 14:04
> >> To: OCaml mailing list
> >> Subject: [Caml-list] Parsing simple type expressions
> >>
> >> For a serializer I'm writing I need to parse simple OCaml type
> >> expressions composed by OCaml basic types, tuples, options and lists.
> >> Given a string like "(int * string option) list" and this type:
> >>
> >> type types =
> >>   | Int
> >>   | String
> >>   | Float
> >>   | Char
> >>   | Bool
> >>   | Option of types
> >>   | List of types
> >>   | Tuple of types list
> >>
> >> the function I need should return something like List (Tuple ([Int;
> >> Option(String)]))
> >>
> >> Before starting with low level sscanf functions I looked at the Genlex
> >> module, but it wasn't so inspiring. Then I tried with Camlp4 but the
> >> documentation doesn't really shine :-)
> >>
> >> So is there a simple way to write this function using some standard
> >> module?
> >>
> >> TIA,
> >>
> >>
> >> --
> >> Paolo
> >> ~
> >> ~
> >> :wq
> 
> -- 
> http://mjambon.com/
> 
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs



      

[-- Attachment #2: common.ml --]
[-- Type: application/octet-stream, Size: 525 bytes --]

type types =
  | Int
  | String
  | Float
  | Char
  | Bool
  | Option of types
  | List of types
  | Tuple of types list

let rec string_of_type = function
  | Int -> "int"
  | String -> "string"
  | Float -> "float"
  | Char -> "char"
  | Bool -> "bool"
  | Option types -> string_of_type types ^ " option"
  | List types -> string_of_type types ^ " list"
  | Tuple types ->
    let tup = String.concat " * " (List.map string_of_type types) in
    "(" ^ tup ^ ")"

let parse_type : (string -> unit) ref = ref (fun _ -> ())

[-- Attachment #3: pa_exp.ml --]
[-- Type: application/octet-stream, Size: 665 bytes --]

open Camlp4
open PreCast
open Printf
  
let _ =
  let dl = DynLoader.mk () in
  DynLoader.load dl "Camlp4OCamlRevisedParser.cmo";
  DynLoader.load dl "Camlp4OCamlParser.cmo";
  DynLoader.load dl "pa_exp_ext.cmo";
  
  List.iter print_endline !Register.loaded_modules;
  Register.iter_and_take_callbacks
    (fun (name, module_callback) ->
      module_callback ());
  (*parse_type "int * string option list";
  parse_type "(int * string option) list";*)
  try
    !Common.parse_type "int option"
  with Loc.Exc_located (loc, e) ->
      print_endline (Loc.to_string loc);
	  print_endline (Printexc.to_string e)
  | e -> 
	  print_endline (Printexc.to_string e)
  

[-- Attachment #4: pa_exp_ext.ml --]
[-- Type: application/octet-stream, Size: 1227 bytes --]

open Camlp4
open PreCast
open Printf
 
module Id = struct
  let name = "pa_exp"
  let version = "1.0"
end

module Make (Syntax : Sig.Camlp4Syntax) = struct
  open Sig
  include Syntax

  let rtyuio = Gram.Entry.mk "rtyuio"

  let rec convert_type = function
  | <:ctyp< $lid:i$ >> when i = "int" -> Common.Int
  | <:ctyp< $lid:i$ >> when i = "string" -> Common.String
  | <:ctyp< $lid:i$ >> when i = "float" -> Common.Float
  | <:ctyp< $lid:i$ >> when i = "char" -> Common.Char
  | <:ctyp< $lid:i$ >> when i = "bool" -> Common.Bool
  | <:ctyp< $t1$ $t2$ >> ->
    let t = convert_type t2 in
    (match t1 with
	| <:ctyp< $lid:i$ >> when i = "option" -> Common.Option t
	| <:ctyp< $lid:i$ >> when i = "list" -> Common.List t
	| _ -> failwith "only option and list allowed for type application")
  | _ -> failwith "this case is not representable using this AST"

  (* Grammar definition *)
  EXTEND Gram
  
    rtyuio: [
  		[ t = ctyp; EOI -> convert_type t ]
  	];

  END
  
  let my_parse_type str =
    print_endline (Common.string_of_type (Gram.parse rtyuio (Loc.mk str) (Stream.of_string str)))

  let _ =
    Common.parse_type := my_parse_type
end
  
let _=
  let module M = Register.OCamlSyntaxExtension (Id) (Make) in ()

[-- Attachment #5: build.sh --]
[-- Type: application/octet-stream, Size: 205 bytes --]

#!/bin/sh
ocamlc -g -c common.ml
ocamlc -g -c -I +camlp4 pa_exp.ml
ocamlc -g -c -I +camlp4 -pp camlp4of pa_exp_ext.ml
ocamlc -g -o pa_exp.exe -I +camlp4 dynlink.cma camlp4fulllib.cma common.cmo pa_exp.cmo 

  reply	other threads:[~2009-01-06 22:50 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-01-06 14:03 Paolo Donadeo
2009-01-06 15:12 ` [Caml-list] " David Allsopp
2009-01-06 21:10   ` Martin Jambon
2009-01-06 22:49     ` Matthieu Wipliez [this message]
2009-01-07 22:50       ` Paolo Donadeo
2009-01-06 18:19 ` Jake Donham
2009-01-06 21:00   ` Paolo Donadeo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=524796.35746.qm@web27006.mail.ukl.yahoo.com \
    --to=mwipliez@yahoo.fr \
    --cc=caml-list@yquem.inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).