Coccinelle release 1.0.0-rc13
[bpt/coccinelle.git] / bundles / menhirLib / menhir-20120123 / src / rawPrinter.ml
diff --git a/bundles/menhirLib/menhir-20120123/src/rawPrinter.ml b/bundles/menhirLib/menhir-20120123/src/rawPrinter.ml
new file mode 100644 (file)
index 0000000..53f6f15
--- /dev/null
@@ -0,0 +1,231 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  Menhir                                                                *)
+(*                                                                        *)
+(*  François Pottier, INRIA Rocquencourt                                  *)
+(*  Yann Régis-Gianas, PPS, Université Paris Diderot                      *)
+(*                                                                        *)
+(*  Copyright 2005-2008 Institut National de Recherche en Informatique    *)
+(*  et en Automatique. All rights reserved. This file is distributed      *)
+(*  under the terms of the Q Public License version 1.0, with the change  *)
+(*  described in file LICENSE.                                            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* A debugging pretty-printer for [IL]. Newlines are used liberally, so as to
+   facilitate diffs. *)
+
+open IL
+open Printf
+
+module Make (X : sig
+
+  (* This is the channel that is being written to. *)
+
+  val f: out_channel
+
+end) = struct
+
+(* ------------------------------------------------------------------------- *)
+(* XML-style trees. *)
+
+type tree =
+  | Node of string * tree list
+
+let node label ts =
+  Node (label, ts)
+
+(* ------------------------------------------------------------------------- *)
+(* Dealing with newlines and indentation. *)
+
+let maxindent =
+  120
+
+let whitespace =
+  String.make maxindent ' '
+
+let indentation =
+  ref 0
+
+let line =
+  ref 1
+
+(* [rawnl] is, in principle, the only place where writing a newline
+   character to the output channel is permitted. This ensures that the
+   line counter remains correct. But see also [stretch] and [typ0]. *)
+
+let rawnl f =
+  incr line;
+  output_char f '\n'
+
+let nl f =
+  rawnl f;
+  output f whitespace 0 !indentation
+
+let indent ofs producer f x =
+  let old_indentation = !indentation in
+  let new_indentation = old_indentation + ofs in
+  if new_indentation <= maxindent then
+    indentation := new_indentation;
+  nl f;
+  producer f x;
+  indentation := old_indentation
+
+(* ------------------------------------------------------------------------- *)
+(* Tree printers. *)
+
+let rec print_tree f = function
+  | Node (label, []) ->
+      output_char f '<';
+      output_string f label;
+      output_char f '/';
+      output_char f '>';
+      nl f
+  | Node (label, ts) ->
+      output_char f '<';
+      output_string f label;
+      output_char f '>';
+      indent 2 print_trees f ts;
+      output_char f '<';
+      output_char f '/';
+      output_string f label;
+      output_char f '>';
+      nl f
+
+and print_trees f = function
+  | [] ->
+      ()
+  | t :: ts ->
+      print_tree f t;
+      print_trees f ts
+
+(* ------------------------------------------------------------------------- *)
+(* Expression-to-tree converter. *)
+
+let rec expr e =
+  match e with
+  | EComment (c, e) ->
+      node "comment" [ string c; expr e ]
+  | EPatComment (s, p, e) ->
+      node "patcomment" [ string s; pat p; expr e ]
+  | ELet (pes, e2) ->
+      node "let" ( patexprs pes @ [ expr e2 ])
+  | ERecordWrite (e1, field, e2) ->
+      node "recordwrite" [ expr e1; string field; expr e2 ]
+  | EMatch (e, brs) ->
+      node "match" ( expr e :: branches brs )
+  | ETry (e, brs) ->
+      node "try" ( expr e :: branches brs )
+  | EIfThen (e1, e2) ->
+      node "ifthen" [ expr e1; expr e2 ]
+  | EIfThenElse (e0, e1, e2) ->
+      node "ifthenelse" [ expr e0; expr e1; expr e2 ]
+  | EFun (ps, e) ->
+      node "fun" ( pats ps @ [ expr e ])
+  | EApp (e, args) ->
+      node "app" ( expr e :: exprs args )
+  | ERaise e ->
+      node "raise" [ expr e ]
+  | EMagic e ->
+      node "magic" [ expr e ]
+  | ERepr e ->
+      node "repr" [ expr e ]
+  | EData (d, args) ->
+      node "data" ( string d :: exprs args )
+  | EVar v ->
+      node "var" [ string v ]
+  | ETextual action ->
+      node "text" [ stretch action ]
+  | EUnit ->
+      node "unit" []
+  | EIntConst k ->
+      node "int" [ int k ]
+  | EStringConst s ->
+      node "string" [ string s ]
+  | ETuple es ->
+      node "tuple" ( exprs es )
+  | EAnnot (e, s) ->
+      node "annot" [ expr e; scheme s ]
+  | ERecordAccess (e, field) ->
+      node "recordaccess" [ expr e; string field ]
+  | ERecord fs ->
+      node "record" (fields fs)
+  | EArray fs ->
+      node "array" (exprs fs)
+  | EArrayAccess (e1, e2) ->
+      node "arrayaccess" [ expr e1; expr e2 ]
+
+and exprs es =
+  List.map expr es
+
+and stretch stretch =
+  string stretch.Stretch.stretch_content
+
+and branches brs =
+  List.map branch brs
+
+and branch br =
+  node "branch" [ pat br.branchpat; expr br.branchbody ]
+
+and fields fs =
+  List.map field fs
+
+and field (label, e) =
+  node "field" [ string label; expr e ]
+
+and pats ps =
+  List.map pat ps
+
+and pat = function
+  | PUnit ->
+      node "punit" []
+  | PWildcard ->
+      node "pwildcard" []
+  | PVar x ->
+      node "pvar" [ string x ]
+  | PTuple ps ->
+      node "ptuple" (pats ps)
+  | PAnnot (p, t) ->
+      node "pannot" [ pat p; typ t ]
+  | PData (d, args) ->
+      node "pdata" (string d :: pats args)
+  | PRecord fps ->
+      node "precord" (fpats fps)
+  | POr ps ->
+      node "por" (pats ps)
+
+and fpats fps =
+  List.map fpat fps
+
+and fpat (_, p) =
+  pat p
+
+and patexprs pes =
+  List.map patexpr pes
+
+and patexpr (p, e) =
+  node "patexpr" [ pat p; expr e ]
+
+and string s =
+  node s []
+
+and int k =
+  node (string_of_int k) []
+
+and bool b =
+  node (if b then "true" else "false") []
+
+and scheme s =
+  string "omitted" (* TEMPORARY to be completed, someday *)
+
+and typ t =
+  string "omitted" (* TEMPORARY to be completed, someday *)
+
+(* ------------------------------------------------------------------------- *)
+(* Convert to a tree, then print the tree. *)
+
+let expr e = 
+  print_tree X.f (expr e)
+
+end
+