Writer.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // $Id$
  2. using System;
  3. using System.IO;
  4. using System.Collections;
  5. using System.Globalization;
  6. namespace Lisp
  7. {
  8. public sealed class Writer {
  9. private TextWriter stream;
  10. private int IndentDepth;
  11. private Stack lists = new Stack();
  12. public Writer(TextWriter stream) {
  13. this.stream = stream;
  14. }
  15. /// <summary>
  16. /// Writes a comment to the stream.
  17. /// </summary>
  18. /// <param name="comment">Contents of the comment</param>
  19. public void WriteComment(string comment) {
  20. stream.WriteLine("; " + comment);
  21. }
  22. /// <summary>
  23. /// Starts a new lisp tree.
  24. /// </summary>
  25. /// <param name="name">The name of the lisp tree.</param>
  26. /// <seealso cref="EndList"/>
  27. public void StartList(string name) {
  28. indent();
  29. stream.WriteLine("(" + name);
  30. IndentDepth += 2;
  31. lists.Push(name);
  32. }
  33. /// <summary>
  34. /// Ends a lisptree opened with <see cref="StartList"/>.
  35. /// </summary>
  36. /// <param name="name">The name of the lisp tree.</param>
  37. /// <seealso cref="StartList"/>
  38. public void EndList(string name) {
  39. if(lists.Count == 0)
  40. throw new LispException("Trying to close list while none is open");
  41. string back = (string) lists.Pop();
  42. if(name != back)
  43. throw new LispException(String.Format("Trying to close {0} which is not open", name));
  44. IndentDepth -= 2;
  45. indent();
  46. stream.WriteLine(")");
  47. }
  48. /// <summary>
  49. /// Write an object <paramref name="value"/> to
  50. /// the stream under the name
  51. /// <paramref name="name"/>.
  52. /// </summary>
  53. /// <param name="name">The name to write value to in lisp.</param>
  54. /// <param name="value">The object to write</param>
  55. /// <remarks>
  56. /// This function can write
  57. /// strings, lists that implements <see cref="IEnumerable"/>,
  58. /// and for anything else it will call <see cref="WriteValue"/>.
  59. /// </remarks>
  60. public void Write(string name, object value) {
  61. indent();
  62. stream.Write("(" + name);
  63. if(value is string) {
  64. stream.Write(" \"");
  65. foreach(char c in value.ToString()) {
  66. if(c == '\"')
  67. stream.Write("\\\"");
  68. else if(c == '\\')
  69. stream.Write("\\\\");
  70. else
  71. stream.Write(c);
  72. }
  73. stream.Write("\"");
  74. } else if(value is IEnumerable) {
  75. foreach(object o in (IEnumerable) value) {
  76. stream.Write(" ");
  77. WriteValue(o);
  78. }
  79. } else {
  80. stream.Write(" ");
  81. WriteValue(value);
  82. }
  83. stream.WriteLine(")");
  84. }
  85. /// <summary>
  86. /// Writes a string and marks it as translatable
  87. /// (for use with gettext?).
  88. /// </summary>
  89. /// <param name="Name">The name of the element to write.</param>
  90. /// <param name="value">The value of it.</param>
  91. public void WriteTranslatable(string Name, string value) {
  92. indent();
  93. stream.WriteLine("(" + Name + " (_ \"" + value + "\"))");
  94. }
  95. /// <summary>
  96. /// Processes and writes a value <paramref name="val"/>.
  97. /// </summary>
  98. /// <remarks>
  99. /// If <paramref name="val"/> is a
  100. /// <list type="table">
  101. /// <listheader>
  102. /// <term>Type</term>
  103. /// <description>What will be written</description>
  104. /// </listheader>
  105. /// <item>
  106. /// <term><see cref="Boolean"/></term>
  107. /// <description>#t or #f will be written.</description>
  108. /// </item>
  109. /// <item>
  110. /// <term><see cref="Single"/> or <see cref="Double"/></term>
  111. /// <description>
  112. /// The floating point number will be formated with
  113. /// <see cref="CultureInfo.InvariantCulture"/>
  114. /// </description>
  115. /// </item>
  116. /// <item>
  117. /// <term>Other</term>
  118. /// <description>Call ToString() of <paramref name="val"/></description>
  119. /// </item>
  120. /// </list>
  121. /// </remarks>
  122. /// <param name="val">The value to write</param>
  123. private void WriteValue(object val) {
  124. if(val is bool) {
  125. stream.Write( ((bool) val) == true ? "#t" : "#f");
  126. } else if(val is int || val is uint) {
  127. stream.Write(val.ToString());
  128. } else if(val is float || val is double) {
  129. string num = String.Format(CultureInfo.InvariantCulture, "{0:G}", val);
  130. stream.Write(num);
  131. } else {
  132. stream.Write("\"" + val.ToString() + "\"");
  133. }
  134. }
  135. /// <summary>
  136. /// Indents and write the string passed in <paramref name="line"/>
  137. /// without any processing of it.
  138. /// </summary>
  139. /// <param name="line">The line to write.</param>
  140. public void WriteVerbatimLine(string line) {
  141. indent();
  142. stream.WriteLine(line);
  143. }
  144. /// <summary>
  145. /// Add spaces to indent to <see cref="IndentDepth"/>.
  146. /// </summary>
  147. private void indent() {
  148. stream.Write(new String(' ', IndentDepth));
  149. }
  150. }
  151. }