PETXMLTree.Mod 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. MODULE PETXMLTree; (** AUTHOR "TF/staubesv"; PURPOSE "XML Structure Viewer for PET"; *)
  2. IMPORT
  3. Modules, Streams, Diagnostics, CompilerInterface, Strings, Texts, PETTrees, WMTrees,
  4. XML, XMLObjects, XMLScanner, XMLParser, UTF8Strings;
  5. TYPE
  6. Tree* = OBJECT(PETTrees.Tree)
  7. VAR
  8. diagnostics : Diagnostics.Diagnostics;
  9. log : Streams.Writer;
  10. hasErrors : BOOLEAN;
  11. PROCEDURE &Init*;
  12. BEGIN
  13. Init^;
  14. diagnostics := NIL;
  15. log := NIL;
  16. hasErrors := FALSE;
  17. END Init;
  18. PROCEDURE AddSubNode(node : PETTrees.TreeNode; xml : XML.Element );
  19. VAR
  20. en : XMLObjects.Enumerator; newNode : PETTrees.TreeNode;
  21. p : ANY; s, t, c : Strings.String;
  22. BEGIN
  23. NEW(newNode);
  24. tree.AddChildNode(node, newNode);
  25. SetNodeInfo(newNode, xml.GetPos());
  26. s := xml.GetName();
  27. t := xml.GetAttributeValue("name");
  28. IF (t # NIL) THEN
  29. NEW(c,Strings.Length(s^) + Strings.Length(t^) + 1 + 4);
  30. c[0] := 0X;
  31. IF (s # NIL) THEN
  32. Strings.Append(c^,s^);
  33. Strings.Append(c^,': ');
  34. END;
  35. Strings.Append(c^,'"');
  36. Strings.Append(c^,t^);
  37. Strings.Append(c^,'"');
  38. ELSE
  39. c := s;
  40. END;
  41. IF (c # NIL) THEN tree.SetNodeCaption(newNode, c) END;
  42. en := xml.GetContents();
  43. WHILE en.HasMoreElements() DO
  44. p := en.GetNext();
  45. IF p IS XML.Element THEN
  46. AddSubNode(newNode, p(XML.Element));
  47. END
  48. END;
  49. END AddSubNode;
  50. PROCEDURE SetDocument(xml : XML.Element);
  51. VAR en : XMLObjects.Enumerator; p : ANY; string : Strings.String; node : PETTrees.TreeNode;
  52. BEGIN
  53. NEW(node);
  54. tree.Acquire;
  55. tree.SetRoot(node);
  56. tree.SetNodeState(node, {WMTrees.NodeAlwaysExpanded});
  57. IF xml # NIL THEN
  58. string := xml.GetName();
  59. IF (string = NIL) THEN
  60. tree.SetNodeCaption(node, Strings.NewString("Document"));
  61. ELSE
  62. tree.SetNodeCaption(node, string);
  63. END;
  64. SetNodeInfo(node, xml.GetPos());
  65. en := xml.GetContents();
  66. WHILE en.HasMoreElements() DO
  67. p := en.GetNext();
  68. IF p IS XML.Element THEN
  69. AddSubNode(node, p(XML.Element));
  70. END
  71. END
  72. ELSE
  73. tree.SetNodeCaption(node, Strings.NewString("No Document"));
  74. END;
  75. tree.Release
  76. END SetDocument;
  77. PROCEDURE Error(pos, line, row: LONGINT; CONST msg: ARRAY OF CHAR);
  78. VAR diagnostics : Diagnostics.Diagnostics; log : Streams.Writer;
  79. BEGIN
  80. diagnostics := SELF.diagnostics;
  81. log := SELF.log;
  82. hasErrors := TRUE;
  83. END Error;
  84. PROCEDURE AddNodes*(parent : PETTrees.TreeNode; diagnostics : Diagnostics.Diagnostics; log : Streams.Writer);
  85. VAR r : Streams.StringReader;
  86. scanner : XMLScanner.Scanner;
  87. parser : XMLParser.Parser;
  88. doc : XML.Document;
  89. tr : Texts.TextReader; ch : Texts.Char32; i, p : LONGINT; resstr : ARRAY 7 OF CHAR;
  90. s : Strings.String;
  91. text : Texts.Text; out : Streams.Writer; ob : Strings.Buffer; hasErrors : BOOLEAN;
  92. BEGIN
  93. AddNodes^(parent, diagnostics, log);
  94. hasErrors := FALSE;
  95. text := editor.text;
  96. text.AcquireRead;
  97. NEW(ob, (text.GetLength() * 3 DIV 2)); (* heuristic to avoid growing in most cases *)
  98. out := ob.GetWriter();
  99. NEW(tr, text);
  100. FOR i := 0 TO text.GetLength() - 1 DO
  101. tr.ReadCh(ch); p := 0;
  102. IF (ch > 0) & UTF8Strings.EncodeChar(ch, resstr, p) THEN out.String(resstr) END
  103. END;
  104. out.Update;
  105. text.ReleaseRead;
  106. NEW(r, ob.GetLength() + 1);
  107. s := ob.GetString();
  108. r.SetRaw(s^, 0, ob.GetLength());
  109. NEW(scanner, r); scanner.reportError := Error;
  110. NEW(parser, scanner); parser.reportError := Error;
  111. doc := parser.Parse();
  112. IF hasErrors THEN SetTitle("XML Structure (ERRORS)");
  113. ELSE
  114. SetTitle("XML Structure");
  115. END;
  116. IF doc # NIL THEN
  117. SetDocument(doc.GetRoot())
  118. END;
  119. END AddNodes;
  120. PROCEDURE SetNodeInfo(node : PETTrees.TreeNode; position : LONGINT);
  121. BEGIN
  122. IF (position >= 0) THEN
  123. NEW(node.pos, editor.text);
  124. node.pos.SetPosition(position);
  125. ELSE
  126. node.pos := NIL;
  127. END;
  128. END SetNodeInfo;
  129. END Tree;
  130. TYPE
  131. ErrorReporter = OBJECT
  132. VAR
  133. diagnostics : Diagnostics.Diagnostics;
  134. hasErrors : BOOLEAN;
  135. PROCEDURE ReportError(pos, line, row : LONGINT; CONST msg : ARRAY OF CHAR);
  136. BEGIN
  137. diagnostics.Error("PET", pos, msg);
  138. hasErrors := TRUE;
  139. END ReportError;
  140. PROCEDURE &Init(diagnostics : Diagnostics.Diagnostics);
  141. BEGIN
  142. ASSERT(diagnostics # NIL);
  143. SELF.diagnostics := diagnostics;
  144. hasErrors := FALSE;
  145. END Init;
  146. END ErrorReporter;
  147. PROCEDURE ParseText(
  148. text : Texts.Text; CONST source: ARRAY OF CHAR; pos: LONGINT; CONST pc,opt: ARRAY OF CHAR;
  149. log: Streams.Writer; diagnostics : Diagnostics.Diagnostics; VAR error: BOOLEAN);
  150. VAR
  151. r : Streams.StringReader;
  152. scanner : XMLScanner.Scanner;
  153. parser : XMLParser.Parser;
  154. doc : XML.Document;
  155. tr : Texts.TextReader; ch : Texts.Char32; i, p : LONGINT; resstr : ARRAY 7 OF CHAR;
  156. s : Strings.String;
  157. out : Streams.Writer; ob : Strings.Buffer;
  158. errors : ErrorReporter;
  159. BEGIN
  160. ASSERT((text # NIL) & (diagnostics # NIL));
  161. text.AcquireRead;
  162. NEW(ob, (text.GetLength() * 3 DIV 2)); (* heuristic to avoid growing in most cases *)
  163. out := ob.GetWriter();
  164. NEW(tr, text);
  165. FOR i := 0 TO text.GetLength() - 1 DO
  166. tr.ReadCh(ch); p := 0;
  167. IF (ch > 0) & UTF8Strings.EncodeChar(ch, resstr, p) THEN out.String(resstr) END
  168. END;
  169. out.Update;
  170. text.ReleaseRead;
  171. NEW(r, ob.GetLength() + 1);
  172. s := ob.GetString();
  173. r.SetRaw(s^, 0, ob.GetLength());
  174. NEW(errors, diagnostics);
  175. NEW(scanner, r); scanner.reportError := errors.ReportError;
  176. NEW(parser, scanner); parser.reportError := errors.ReportError;
  177. error := errors.hasErrors;
  178. doc := parser.Parse();
  179. IF (log # NIL) THEN
  180. IF error THEN log.String("XML Parser reports errors"); ELSE log.String("XML Parser: OK"); END;
  181. log.Update;
  182. END;
  183. END ParseText;
  184. PROCEDURE GenXMLTree*() : PETTrees.Tree;
  185. VAR tree : Tree;
  186. BEGIN
  187. NEW(tree); RETURN tree;
  188. END GenXMLTree;
  189. PROCEDURE Cleanup;
  190. BEGIN
  191. CompilerInterface.Unregister("XML");
  192. END Cleanup;
  193. BEGIN
  194. Modules.InstallTermHandler(Cleanup);
  195. CompilerInterface.Register("XML", "XML Parser", "XML", ParseText);
  196. END PETXMLTree.