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 // Implement IEnumerable interface.
198 // foreach (MPlist p in plist) { ... }
200 public virtual IEnumerator GetEnumerator ()
202 return new Enumerator (this);
205 private class Enumerator : IEnumerator
207 private MPlist plist;
208 private MPlist current;
210 internal Enumerator (MPlist plist)
215 public object Current
218 if (current == null || current.IsEmpty)
219 throw new InvalidOperationException ();
229 public bool MoveNext ()
234 current = current.next;
235 return (! current.IsEmpty);
240 public class MStreamReader : StreamReader
242 private static char[] escaped_char = new char[128];
243 private static int[] hexadecimal = new int[128];
245 public MStreamReader (Stream stream) : base (stream)
249 static MStreamReader ()
251 for (int i = 0; i < 128; i++)
252 escaped_char[i] = (char) i;
253 escaped_char['e'] = (char) 27;
254 escaped_char['b'] = '\b';
255 escaped_char['f'] = '\f';
256 escaped_char['n'] = '\n';
257 escaped_char['r'] = '\r';
258 escaped_char['t'] = '\t';
259 escaped_char['\\'] = '\\';
260 for (int i = 0; i < 128; i++)
262 for (int i = '0'; i <= '9'; i++)
263 hexadecimal[i] = i - '0';
264 for (int i = 'A'; i <= 'F'; i++)
265 hexadecimal[i] = hexadecimal[i + 'a' - 'A'] = i -'A' + 10;
268 internal int PeekChar ()
270 bool comment = false;
273 while ((c = Peek ()) != -1)
277 if ((c = Read ()) == '\n')
284 else if (c != ' ' && c != '\t' && c != '\n')
292 internal int ReadHexadecimal ()
296 while ((c = Peek ()) >= 0 && c < 128 && (c = hexadecimal[c]) >= 0)
304 internal int ReadInteger ()
308 while ((c = Peek ()) >= '0' && c <= '9')
309 i = (i * 10) + (Read () - '0');
313 internal int ReadChar ()
322 if (c == 'x' || c == 'u')
323 return ReadHexadecimal ();
330 internal MText ReadMtext ()
332 MText mt = new MText ();
335 while ((c = Peek ()) != -1 && c != '"')
360 internal string ReadSymbolName ()
364 if (c == -1 || c == '(' || c == ' ' || c == '\n' || c == '"')
373 return (char) c + ReadSymbolName ();
376 internal bool ReadElement (out MSymbol key, out object val)
383 val = new MPlist (this);
392 else if (c >= '0' && c <= '9')
394 int i = ReadInteger ();
397 key = MSymbol.integer;
403 if (c >= '0' && c <= '9')
405 int i = ReadInteger ();
407 key = MSymbol.integer;
411 string str = ReadSymbolName ();
413 val = new MSymbol ("-" + str);
414 key = MSymbol.symbol;
421 key = MSymbol.integer;
426 if ((c = Peek ()) == 'x' || c == 'u')
429 val = ReadHexadecimal ();
430 key = MSymbol.integer;
434 string str = ReadSymbolName ();
436 val = new MSymbol ("#" + (char) c + str);
437 key = MSymbol.symbol;
440 else if (c == -1 || c == ')')
450 val = new MSymbol (ReadSymbolName ());
451 key = MSymbol.symbol;