2 using System.Collections;
9 public class MPlist : IEnumerable
21 public MPlist (MStreamReader reader)
25 bool result = reader.ReadElement (out key, out val);
30 next = new MPlist (reader);
33 private MPlist (MSymbol key, object val)
39 public bool IsEmpty { get { return next == null; } }
40 public MPlist Next { get { return next; } }
42 internal bool IsSymbol { get { return Key == MSymbol.symbol; } }
43 internal bool IsMText { get { return Key == MSymbol.mtext; } }
44 internal bool IsPlist { get { return Key == MSymbol.plist; } }
45 internal bool IsInteger { get { return Key == MSymbol.integer; } }
47 internal MSymbol Symbol { get { return (MSymbol) Val; } }
48 internal MText Text { get { return (MText) Val; } }
49 internal MPlist Plist { get { return (MPlist) Val; } }
50 internal int Integer { get { return (int) Val; } }
58 for (MPlist p = this; p.next != null; i++, p = p.next);
63 public MPlist Clone ()
65 MPlist plist = new MPlist (), pl = plist;
67 for (MPlist p = this; p.next != null; p = p.next)
68 pl = pl.Add (p.Key, p.Val);
72 public override string ToString ()
76 for (MPlist p = this; ! p.IsEmpty; p = p.next)
80 if (p.Key != MSymbol.symbol
81 && p.Key != MSymbol.integer
82 && p.Key != MSymbol.plist
83 && p.Key != MSymbol.mtext)
90 private MPlist find (MSymbol key)
94 for (p = this; ! p.IsEmpty; p = p.next)
100 public MPlist Find (MSymbol key)
102 MPlist p = find (key);
104 return (p.IsEmpty ? null : p);
107 public object Get (MSymbol key)
109 return find (key).Val;
112 private delegate MPlist MPlistDelegate (MSymbol key, object val);
114 private MPlist mplist_op (MPlistDelegate op, object val)
116 Type type = val.GetType ();
118 if (Object.ReferenceEquals (type, typeof (MSymbol)))
119 return op (MSymbol.symbol, val);
120 if (Object.ReferenceEquals (type, typeof (MText)))
121 return op (MSymbol.mtext, val);
122 if (Object.ReferenceEquals (type, typeof (MPlist)))
123 return op (MSymbol.plist, val);
124 if (Object.ReferenceEquals (type, typeof (int)))
125 return op (MSymbol.integer, val);
126 return op (MSymbol.t, val);
129 public MPlist Set (MSymbol key, object val)
138 public MPlist Set (object val)
140 return mplist_op (Set, val);
143 public MPlist Put (MSymbol key, object val)
145 return find (key).Set (key, val);
148 public MPlist Put (object val)
150 return mplist_op (Put, val);
153 public MPlist Push (MSymbol key, object val)
155 MPlist p = new MPlist (Key, Val);
164 public MPlist Push (object val)
166 return mplist_op (Push, val);
169 public object Pop (out MSymbol key)
186 return Pop (out key);
189 public MPlist Add (MSymbol key, object val)
193 for (p = this; ! p.IsEmpty; p = p.next);
194 return p.Push (key, val);
197 public MPlist Clear ()
205 // Implement IEnumerable interface.
206 // foreach (MPlist p in plist) { ... }
208 public virtual IEnumerator GetEnumerator ()
210 return new Enumerator (this);
213 private class Enumerator : IEnumerator
215 private MPlist plist;
216 private MPlist current;
218 internal Enumerator (MPlist plist)
223 public object Current
226 if (current == null || current.IsEmpty)
227 throw new InvalidOperationException ();
237 public bool MoveNext ()
242 current = current.next;
243 return (! current.IsEmpty);
248 public class MStreamReader : StreamReader
250 private static char[] escaped_char = new char[128];
251 private static int[] hexadecimal = new int[128];
253 public MStreamReader (Stream stream) : base (stream)
257 static MStreamReader ()
259 for (int i = 0; i < 128; i++)
260 escaped_char[i] = (char) i;
261 escaped_char['e'] = (char) 27;
262 escaped_char['b'] = '\b';
263 escaped_char['f'] = '\f';
264 escaped_char['n'] = '\n';
265 escaped_char['r'] = '\r';
266 escaped_char['t'] = '\t';
267 escaped_char['\\'] = '\\';
268 for (int i = 0; i < 128; i++)
270 for (int i = '0'; i <= '9'; i++)
271 hexadecimal[i] = i - '0';
272 for (int i = 'A'; i <= 'F'; i++)
273 hexadecimal[i] = hexadecimal[i + 'a' - 'A'] = i -'A' + 10;
276 internal int PeekChar ()
278 bool comment = false;
281 while ((c = Peek ()) != -1)
285 if ((c = Read ()) == '\n')
292 else if (c != ' ' && c != '\t' && c != '\n')
300 internal int ReadHexadecimal ()
304 while ((c = Peek ()) >= 0 && c < 128 && (c = hexadecimal[c]) >= 0)
312 internal int ReadInteger ()
316 while ((c = Peek ()) >= '0' && c <= '9')
317 i = (i * 10) + (Read () - '0');
321 internal int ReadChar ()
330 if (c == 'x' || c == 'u')
331 return ReadHexadecimal ();
338 internal MText ReadMtext ()
340 MText mt = new MText ();
343 while ((c = Peek ()) != -1 && c != '"')
368 internal string ReadSymbolName ()
372 if (c == -1 || c == '(' || c == ' ' || c == '\n' || c == '"')
381 return (char) c + ReadSymbolName ();
384 internal bool ReadElement (out MSymbol key, out object val)
391 val = new MPlist (this);
400 else if (c >= '0' && c <= '9')
402 int i = ReadInteger ();
405 key = MSymbol.integer;
411 if (c >= '0' && c <= '9')
413 int i = ReadInteger ();
415 key = MSymbol.integer;
419 string str = ReadSymbolName ();
421 val = new MSymbol ("-" + str);
422 key = MSymbol.symbol;
429 key = MSymbol.integer;
434 if ((c = Peek ()) == 'x' || c == 'u')
437 val = ReadHexadecimal ();
438 key = MSymbol.integer;
442 string str = ReadSymbolName ();
444 val = new MSymbol ("#" + (char) c + str);
445 key = MSymbol.symbol;
448 else if (c == -1 || c == ')')
458 val = new MSymbol (ReadSymbolName ());
459 key = MSymbol.symbol;