packages feed

liquid-fixpoint-0.1.0.0: external/ocamlgraph/src/gml.mll

(**************************************************************************)
(*                                                                        *)
(*  Ocamlgraph: a generic graph library for OCaml                         *)
(*  Copyright (C) 2004-2007                                               *)
(*  Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles        *)
(*                                                                        *)
(*  This software is free software; you can redistribute it and/or        *)
(*  modify it under the terms of the GNU Library General Public           *)
(*  License version 2, with the special exception on linking              *)
(*  described in file LICENSE.                                            *)
(*                                                                        *)
(*  This software is distributed in the hope that it will be useful,      *)
(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                  *)
(*                                                                        *)
(**************************************************************************)

(* $Id: gml.mll,v 1.3 2005-07-06 13:20:31 conchon Exp $ *)

{ 

  open Lexing

  type value = 
    | Int of int 
    | Float of float
    | String of string
    | List of value_list

  and value_list = (string * value) list

}

let space = [' ' '\t' '\r' '\n']+
let ident = ['a'-'z' 'A'-'Z'] ['a'-'z' 'A'-'Z' '0'-'9']*
let digit = ['0'-'9']
let sign = '-' | '+' 
let integer = sign? digit+
let mantissa = 'E' sign? digit+
let real = sign? digit* '.' digit* mantissa?
let in_string = [^ '"']*

rule file = parse
  | space 
      { file lexbuf }
  | (ident as key) space 
      { let v = value lexbuf in
	(key, v) :: file lexbuf }
  | eof 
      { [] }
  | _ as c
      { failwith ("Gml: invalid character " ^ String.make 1 c) }

and value_list = parse
  | space 
      { value_list lexbuf }
  | (ident as key) space 
      { let v = value lexbuf in
	(key, v) :: value_list lexbuf }
  | ']' 
      { [] }
  | _ as c
      { failwith ("Gml: invalid character " ^ String.make 1 c) }

and value = parse
  | integer as i
      { Int (int_of_string i) }
  | real as r
      { Float (float_of_string r) }
  | '"' (in_string as s) '"'
      { String s }
  | '['
      { let l = value_list lexbuf in List l }
  | _ as c
      { failwith ("Gml: invalid character " ^ String.make 1 c) }

{

  let parse f =
    let c = open_in f in
    let lb = from_channel c in
    let v = file lb in
    close_in c;
    v

  module Parse
    (B : Builder.S)
    (L : sig val node : value_list -> B.G.V.label
	     val edge : value_list -> B.G.E.label end) = 
  struct

    let create_graph l =
      let nodes = Hashtbl.create 97 in
      let g = B.empty () in
      (* 1st pass: create the nodes *)
      let g =
	List.fold_left 
	  (fun g v -> match v with
	     | "node", List l ->
		 let n = B.G.V.create (L.node l) in
		 begin 
		   try 
		     let id = List.assoc "id" l in Hashtbl.add nodes id n
		   with Not_found -> 
		     ()
		 end;
		 B.add_vertex g n
	     | _ -> 
		 g)
	  g l
      in
      (* 2nd pass: add the edges *)
      List.fold_left
	(fun g v -> match v with
	   | "edge", List l ->
	       begin try
		 let source = List.assoc "source" l in
		 let target = List.assoc "target" l in
		 let nsource = Hashtbl.find nodes source in
		 let ntarget = Hashtbl.find nodes target in
		 let e = B.G.E.create nsource (L.edge l) ntarget in
		 B.add_edge_e g e
	       with Not_found ->
		 g
	       end
	   | _ ->
	       g)
	g l
	
    let parse f =
      match parse f with
	| ["graph", List l] -> create_graph l
	| _ -> invalid_arg "Gml.Parse.parse: not a graph file"
      
  end

  module Print
    (G : sig
       module V : sig
	 type t
	 val hash : t -> int
	 val equal : t -> t -> bool
	 type label
	 val label : t -> label
       end
       module E : sig
	 type t
	 type label
	 val src : t -> V.t
	 val dst : t -> V.t
	 val label : t -> label
       end
       type t
       val iter_vertex : (V.t -> unit) -> t -> unit
       val iter_edges_e : (E.t -> unit) -> t -> unit
     end)
    (L : sig
       val node : G.V.label -> value_list
       val edge : G.E.label -> value_list
     end) =
  struct

    open Format

    module H = Hashtbl.Make(G.V)

    let print fmt g =
      let nodes = H.create 97 in
      let cpt = ref 0 in
      let id n = 
	try H.find nodes n
	with Not_found -> incr cpt; let id = !cpt in H.add nodes n id; id
      in
      fprintf fmt "@[graph [@\n";
      let rec value fmt = function
	| Int n -> fprintf fmt "%d" n
	| Float f -> fprintf fmt "%f" f
	| String s -> fprintf fmt "\"%s\"" s
	| List l -> fprintf fmt "[@\n  @[%a@]@\n]" value_list l
      and value_list fmt = function
	| [] -> ()
	| [s,v] -> fprintf fmt "%s %a" s value v
	| (s,v) :: l -> fprintf fmt "%s %a@\n" s value v; value_list fmt l
      in
      G.iter_vertex
	(fun v -> 
	   fprintf fmt "  @[node [@\n  id %d@\n  @[%a@]@\n]@]@\n" 
	     (id v) value_list (L.node (G.V.label v)))
	g;
      G.iter_edges_e
	(fun e ->
	   fprintf fmt 
	     "  @[edge [@\n  source %d@\n  target %d@\n  @[%a@]@\n]@]@\n"
	     (id (G.E.src e)) (id (G.E.dst e)) 
	     value_list (L.edge (G.E.label e)))
	g;
      fprintf fmt "]@\n"

  end

}