nxml.ml 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. (*
  2. * Neko NXML for OCaml
  3. * Copyright (c)2005 Nicolas Cannasse
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  18. *)
  19. open Nast
  20. type xml =
  21. | Node of string * (string * string) list * xml list
  22. | CData of string
  23. let node name att childs = Node(name,att,childs)
  24. let rec to_xml_rec p2 ast =
  25. let e , p = ast in
  26. let name = ref "" in
  27. let aval = ref None in
  28. let childs = ref [] in
  29. (match e with
  30. | EConst c ->
  31. (match c with
  32. | True
  33. | False
  34. | Null
  35. | This
  36. | Builtin _
  37. | Ident _ ->
  38. name := "v";
  39. aval := Some (s_constant c)
  40. | Int i ->
  41. name := "i";
  42. aval := Some (string_of_int i);
  43. | Float s ->
  44. name := "f";
  45. aval := Some s;
  46. | String s ->
  47. name := "s";
  48. aval := Some s;
  49. | Int32 i ->
  50. name := "i";
  51. aval := Some (Int32.to_string i);
  52. )
  53. | EBlock el ->
  54. name := "b";
  55. childs := List.map (to_xml_rec p) el;
  56. | EParenthesis e ->
  57. name := "p";
  58. childs := [to_xml_rec p e];
  59. | EField (e,f) ->
  60. name := "g";
  61. aval := Some f;
  62. childs := [to_xml_rec p e];
  63. | ECall (e,el) ->
  64. name := "c";
  65. childs := to_xml_rec p e :: List.map (to_xml_rec p) el;
  66. | EArray (a,b) ->
  67. name := "a";
  68. childs := [to_xml_rec p a; to_xml_rec p b];
  69. | EVars vl ->
  70. name := "var";
  71. childs := List.map (fun(v,e) ->
  72. node "v" [("v",v)] (match e with None -> [] | Some e -> [to_xml_rec p e])
  73. ) vl;
  74. | EWhile (econd,e,NormalWhile) ->
  75. name := "while";
  76. childs := [to_xml_rec p econd; to_xml_rec p e];
  77. | EWhile (econd,e,DoWhile) ->
  78. name := "do";
  79. childs := [to_xml_rec p e; to_xml_rec p econd];
  80. | EIf (cond,e,eelse) ->
  81. name := "if";
  82. childs := to_xml_rec p cond :: to_xml_rec p e :: (match eelse with None -> [] | Some e -> [to_xml_rec p e])
  83. | ETry (e1,v,e2) ->
  84. name := "try";
  85. aval := Some v;
  86. childs := [to_xml_rec p e1; to_xml_rec p e2];
  87. | EFunction (args,e) ->
  88. name := "function";
  89. aval := Some (String.concat ":" args);
  90. childs := [to_xml_rec p e];
  91. | EBinop (op,e1,e2) ->
  92. name := "o";
  93. aval := Some op;
  94. childs := [to_xml_rec p e1; to_xml_rec p e2];
  95. | EReturn e ->
  96. name := "return";
  97. childs := (match e with None -> [] | Some e -> [to_xml_rec p e]);
  98. | EBreak e ->
  99. name := "break";
  100. childs := (match e with None -> [] | Some e -> [to_xml_rec p e]);
  101. | EContinue ->
  102. name := "continue";
  103. | ENext (e1,e2) ->
  104. name := "next";
  105. childs := [to_xml_rec p e1; to_xml_rec p e2];
  106. | EObject fl ->
  107. name := "object";
  108. childs := List.map (fun(v,e) -> node "v" [("v",v)] [to_xml_rec p e]) fl;
  109. | ELabel v ->
  110. name := "label";
  111. aval := Some v;
  112. | ESwitch (e,cases,def) ->
  113. name := "switch";
  114. let cases = List.map (fun(e1,e2) -> node "case" [] [to_xml_rec p e1; to_xml_rec p e2]) cases in
  115. childs := to_xml_rec p e :: (match def with None -> cases | Some e -> node "default" [] [to_xml_rec p e] :: cases );
  116. | ENeko s ->
  117. name := "neko";
  118. childs := [CData s];
  119. );
  120. let pos = (if p.psource <> p2.psource then
  121. [("p",p.psource ^ ":" ^ string_of_int p.pline)]
  122. else if p.pline <> p2.pline then
  123. [("p",string_of_int p.pline)]
  124. else
  125. []
  126. ) in
  127. let aval = (match !aval with None -> [] | Some v -> [("v",v)]) in
  128. node !name (List.append pos aval) !childs
  129. let to_xml ast =
  130. to_xml_rec null_pos ast
  131. let rec write_fmt_rec tabs ch x =
  132. match x with
  133. | CData s ->
  134. IO.printf ch "%s<![CDATA[%s]]>" tabs s
  135. | Node (name,att,childs) ->
  136. IO.printf ch "%s<%s%s" tabs name (String.concat "" (List.map (fun(a,v) -> " " ^ a ^ "=\"" ^ escape v ^ "\"") att));
  137. match childs with
  138. | [] -> IO.nwrite_string ch "/>"
  139. | l ->
  140. IO.nwrite_string ch ">\n";
  141. List.iter (fun(x) -> write_fmt_rec (tabs ^ " ") ch x; IO.write ch '\n') l;
  142. IO.printf ch "%s</%s>" tabs name
  143. let write_fmt ch x =
  144. write_fmt_rec "" ch (node "nxml" [] [x])
  145. let rec write_rec ch x =
  146. match x with
  147. | CData s ->
  148. IO.printf ch "<![CDATA[%s]]>" s
  149. | Node (name,att,childs) ->
  150. IO.printf ch "<%s%s" name (String.concat "" (List.map (fun(a,v) -> " " ^ a ^ "=\"" ^ escape v ^ "\"") att));
  151. match childs with
  152. | [] -> IO.nwrite_string ch "/>"
  153. | l ->
  154. IO.nwrite_string ch ">";
  155. List.iter (fun(x) -> write_rec ch x) l;
  156. IO.printf ch "</%s>" name
  157. let write ch x =
  158. write_rec ch (node "nxml" [] [x])