KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > kawa > functions > DisplayFormat


1 // Copyright (c) 2001, 2002, 2006 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.kawa.functions;
5 import gnu.mapping.*;
6 import gnu.lists.*;
7 import gnu.math.RatNum;
8 import gnu.math.IntNum;
9 import java.io.PrintWriter JavaDoc;
10 import gnu.text.Char;
11 import gnu.kawa.xml.XmlNamespace;
12 import gnu.text.Printable;
13 /* #ifdef use:java.util.regex */
14 import java.util.regex.*;
15 /* #endif */
16
17 /** Handle formatted output for Lisp-like languages. */
18
19 public class DisplayFormat extends AbstractFormat
20 {
21   /** Fluid parameter to specify default output base for printing rationals. */
22   public static final ThreadLocation outBase
23     = new ThreadLocation("out-base");
24   static { outBase.setGlobal(IntNum.ten()); }
25   /** True if we should print a radix indicator when printing rationals.
26    * The default is no; otherwise we follow Common Lisp conventions. */

27   public static final ThreadLocation outRadix
28     = new ThreadLocation("out-radix");
29
30   /** Create a new instance.
31    * @param readable if output should be formatted so it could be read
32    * back in again, for example strings shoudl be quoted.
33    * @param language the programming language style to use, where
34    * 'S' is Scheme, 'C' is Common Lisp, and 'E' is Emacs Lisp.
35    */

36   public DisplayFormat(boolean readable, char language)
37   {
38     this.readable = readable;
39     this.language = language;
40   }
41
42   public static DisplayFormat getEmacsLispFormat(boolean readable)
43   {
44     return new DisplayFormat(readable, 'E');
45   }
46
47   public static DisplayFormat getCommonLispFormat(boolean readable)
48   {
49     return new DisplayFormat(readable, 'C');
50   }
51
52   public static DisplayFormat getSchemeFormat(boolean readable)
53   {
54     return new DisplayFormat(readable, 'S');
55   }
56
57   boolean readable;
58
59   /** 'S' is Scheme-style; 'C' is CommonLisp-style; 'E' is Emacs-style.
60    * Note Emacs has its own sub-class gnu.jemacs.lang.Print. */

61   char language;
62
63   public boolean getReadableOutput () { return readable; }
64
65   public void writeBoolean(boolean v, Consumer out)
66   {
67     write (language == 'S' ? (v ? "#t" : "#f") : (v ? "t" : "nil"), out);
68   }
69
70   public void write (int v, Consumer out)
71   {
72     if (! getReadableOutput ())
73       Char.print(v, out);
74     else
75       {
76     if (language == 'E'
77         && v > ' ')
78       {
79         out.write('?');
80             Char.print(v, out);
81       }
82     // else if (language == 'E') ...
83
else
84       write(Char.toScmReadableString(v), out);
85       }
86   }
87
88   public void writeList(LList value, OutPort out)
89   {
90     Object JavaDoc list = value;
91     out.startLogicalBlock("(", false, ")");
92     while (list instanceof Pair)
93       {
94     if (list != value)
95       out.writeSpaceFill();
96     Pair pair = (Pair) list;
97     writeObject(pair.car, (Consumer) out);
98     list = pair.cdr;
99       }
100     if (list != LList.Empty)
101       {
102     out.writeSpaceFill();
103     out.write(". ");
104     writeObject(LList.checkNonList(list), (Consumer) out);
105       }
106     out.endLogicalBlock(")");
107   }
108
109   public void writeObject(Object JavaDoc obj, Consumer out)
110   {
111     boolean space = false;
112     if (out instanceof OutPort
113         && ! (obj instanceof gnu.kawa.xml.UntypedAtomic)
114         && ! (obj instanceof Values)
115         && (getReadableOutput()
116             || ! (obj instanceof FString
117                   || obj instanceof Char
118                   || obj instanceof Character JavaDoc)))
119       {
120         ((OutPort) out).writeWordStart();
121         space = true;
122       }
123     writeObjectRaw(obj, out);
124     if (space)
125       ((OutPort) out).writeWordEnd();
126   }
127
128   public void writeObjectRaw(Object JavaDoc obj, Consumer out)
129   {
130     if (obj instanceof Boolean JavaDoc)
131       writeBoolean(((Boolean JavaDoc)obj).booleanValue(), out);
132     else if (obj instanceof Char)
133       write(((Char) obj).intValue(), out);
134     else if (obj instanceof Character JavaDoc)
135       write(((Character JavaDoc) obj).charValue(), out);
136     else if (obj instanceof Symbol)
137       {
138         Symbol sym = (Symbol) obj;
139         if (sym.getNamespace() == XmlNamespace.HTML)
140           {
141             write("html:", out);
142             write(sym.getLocalPart(), out);
143           }
144         else
145           writeObject(obj.toString(), out);
146       }
147     /* #ifdef use:java.net.URI */
148     /* #ifdef use:java.lang.CharSequence */
149     else if (obj instanceof java.net.URI JavaDoc && getReadableOutput()
150              && out instanceof PrintWriter JavaDoc)
151       {
152         write("#,(URI ", out);
153         Strings.printQuoted(obj.toString(), (PrintWriter JavaDoc) out, 1);
154         out.write(')');
155       }
156     /* #endif */
157     /* #endif */
158     else if (obj instanceof CharSeq)
159       {
160     CharSeq str = (CharSeq) obj;
161     if (getReadableOutput () && out instanceof PrintWriter JavaDoc)
162       Strings.printQuoted(str, (PrintWriter JavaDoc) out, 1);
163     else if (obj instanceof FString) // FIXME Do we need this case?
164
{
165         FString fstr = (FString) obj;
166         out.write(fstr.data, 0, fstr.size());
167       }
168     else
169       str.consume(0, str.size(), out);
170       }
171     else if (obj instanceof LList && out instanceof OutPort)
172       writeList((LList) obj, (OutPort) out);
173     else if (obj instanceof SimpleVector)
174       {
175     SimpleVector vec = (SimpleVector) obj;
176     String JavaDoc tag = vec.getTag();
177     String JavaDoc start, end;
178     if (language == 'E')
179       {
180         start = "[";
181         end = "]";
182       }
183     else
184       {
185         start = tag == null ? "#(" : ("#" + tag + "(");
186         end = ")";
187       }
188     if (out instanceof OutPort)
189       ((OutPort) out).startLogicalBlock(start, false, end);
190     else
191       write (start, out);
192     int endpos = vec.size() << 1;
193     for (int ipos = 0; ipos < endpos; ipos += 2)
194       {
195         if (ipos > 0 && out instanceof OutPort)
196           ((OutPort) out).writeSpaceFill();
197         if (! vec.consumeNext(ipos, out))
198           break;
199       }
200     if (out instanceof OutPort)
201       ((OutPort) out).endLogicalBlock(end);
202     else
203       write (end, out);
204       }
205     else if (obj instanceof Array)
206       {
207     write((Array) obj, 0, 0, out);
208       }
209     else if (obj instanceof Consumable)
210       ((Consumable) obj).consume(out);
211     else if (obj instanceof Printable)
212       ((Printable) obj).print(out);
213     else if (obj instanceof RatNum)
214       {
215         int b = 10;
216         boolean showRadix = false;
217         Object JavaDoc base = outBase.get(null);
218         Object JavaDoc printRadix = outRadix.get(null);
219         if (printRadix != null
220             && (printRadix == Boolean.TRUE
221                 || "yes".equals(printRadix.toString())))
222           showRadix = true;
223         if (base instanceof Number JavaDoc)
224           b = ((IntNum) base).intValue();
225         else if (base != null)
226           b = Integer.parseInt(base.toString());
227         String JavaDoc asString = ((RatNum) obj).toString(b);
228         if (showRadix)
229           {
230             if (b == 16)
231               write("#x", out);
232             else if (b == 8)
233               write("#o", out);
234             else if (b == 2)
235               write("#b", out);
236             else if (b != 10 || ! (obj instanceof IntNum))
237               write("#"+base+"r", out);
238           }
239         write(asString, out);
240         if (showRadix && b == 10 && obj instanceof IntNum)
241           write(".", out);
242       }
243     else
244       {
245         String JavaDoc asString;
246         if (obj == null)
247           asString = null;
248         else
249           {
250             Class JavaDoc cl = obj.getClass();
251             if (cl.isArray())
252               {
253                 int len = java.lang.reflect.Array.getLength(obj);
254                 if (out instanceof OutPort)
255                   ((OutPort) out).startLogicalBlock("[", false, "]");
256                 else
257                   write("[", out);
258                 for (int i = 0; i < len; i++)
259                   {
260                     if (i > 0)
261                       {
262                         write(" ", out);
263                         if (out instanceof OutPort)
264                           ((OutPort) out).writeBreakFill();
265                       }
266                     writeObject(java.lang.reflect.Array.get(obj, i), out);
267                   }
268                 if (out instanceof OutPort)
269                   ((OutPort) out).endLogicalBlock("]");
270                 else
271                   write("]", out);
272                 return;
273               }
274             asString = obj.toString();
275           }
276     if (asString == null)
277       write("#!null", out);
278     else if (readable && obj instanceof String JavaDoc)
279           writeReadableSymbol(asString, out);
280         else
281           write(asString, out);
282       }
283   }
284
285   /** Recursive helper method for writing out Array (sub-) objects.
286    * @param array the Array to write out (part of).
287    * @param index the row-major index to start
288    * @param level the recurssion level, from 0 to array.rank()-1.
289    * @param out the destination
290    */

291   int write(Array array, int index, int level, Consumer out)
292   {
293     int rank = array.rank();
294     int count = 0;
295     String JavaDoc start = level > 0 ? "("
296       : rank == 1 ? "#("
297       : "#" + rank + "a(";
298     if (out instanceof OutPort)
299       ((OutPort) out).startLogicalBlock(start, false, ")");
300     else
301       write (start, out);
302     if (rank > 0)
303       {
304     int size = array.getSize(level);
305     level++;
306     for (int i = 0; i < size; i++)
307       {
308         if (i > 0)
309               {
310                 write(" ", out);
311                 if (out instanceof OutPort)
312                   ((OutPort) out).writeBreakFill();
313               }
314         int step;
315         if (level == rank)
316           {
317         writeObject(array.getRowMajor(index), out);
318         step = 1;
319           }
320         else
321           step = write(array, index, level, out);
322         index += step;
323         count += step;
324       }
325       }
326     if (out instanceof OutPort)
327       ((OutPort) out).endLogicalBlock(")");
328     else
329       write(")", out);
330     return count;
331   }
332
333   /* #ifdef use:java.util.regex */
334   static Pattern r5rsIdentifierMinusInteriorColons =
335     Pattern.compile("(([a-zA-Z]|[!$%&*/:<=>?^_~])"
336                     + "([a-zA-Z]|[!$%&*/<=>?^_~]|[0-9]|([-+.@]))*[:]?)"
337                     + "|([-+]|[.][.][.])");
338   /* #endif */
339
340   void writeReadableSymbol (String JavaDoc sym, Consumer out)
341   {
342     /* #ifdef use:java.util.regex */
343     /* Use |...| if symbol doesn't follow R5RS conventions
344        for identifiers or has a colon in the interior. */

345     if (! r5rsIdentifierMinusInteriorColons.matcher(sym).matches())
346       {
347         int len = sym.length();
348         if (len == 0)
349           {
350             write("||", out);
351           }
352         else
353           {
354             boolean inVerticalBars = false;
355             for (int i = 0; i < len; i++)
356               {
357                 char ch = sym.charAt(i);
358                 if (ch == '|')
359                   {
360                     write(inVerticalBars ? "|\\" : "\\", out);
361                     inVerticalBars = false;
362                   }
363                 else if (! inVerticalBars)
364                   {
365                     out.write('|');
366                     inVerticalBars = true;
367                   }
368                 out.write(ch);
369               }
370             if (inVerticalBars)
371               out.write('|');
372           }
373         return;
374       }
375     /* #endif */
376     write(sym, out);
377   }
378 }
379
Popular Tags