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; } }
48 for (MPlist p = this; p.next != null; i++, p = p.next);
53 public MPlist Clone ()
55 MPlist plist = new MPlist (), pl = plist;
57 for (MPlist p = this; p.next != null; p = p.next)
58 pl = pl.Add (p.Key, p.Val);
62 public override string ToString ()
66 for (MPlist p = this; ! p.IsEmpty; p = p.next)
70 if (p.Key != MSymbol.symbol
71 && p.Key != MSymbol.integer
72 && p.Key != MSymbol.plist
73 && p.Key != MSymbol.mtext)
80 private MPlist find (MSymbol key)
84 for (p = this; ! p.IsEmpty; p = p.next)
90 public MPlist Find (MSymbol key)
92 MPlist p = find (key);
94 return (p.IsEmpty ? null : p);
97 public object Get (MSymbol key)
99 return find (key).Val;
102 private delegate MPlist MPlistDelegate (MSymbol key, object val);
104 private MPlist mplist_op (MPlistDelegate op, object val)
106 Type type = val.GetType ();
108 if (Object.ReferenceEquals (type, typeof (MSymbol)))
109 return op (MSymbol.symbol, val);
110 if (Object.ReferenceEquals (type, typeof (MText)))
111 return op (MSymbol.mtext, val);
112 if (Object.ReferenceEquals (type, typeof (MPlist)))
113 return op (MSymbol.plist, val);
114 if (Object.ReferenceEquals (type, typeof (int)))
115 return op (MSymbol.integer, val);
116 return op (MSymbol.t, val);
119 public MPlist Set (MSymbol key, object val)
128 public MPlist Set (object val)
130 return mplist_op (Set, val);
133 public MPlist Put (MSymbol key, object val)
135 return find (key).Set (key, val);
138 public MPlist Put (object val)
140 return mplist_op (Put, val);
143 public MPlist Push (MSymbol key, object val)
145 MPlist p = new MPlist (Key, Val);
154 public MPlist Push (object val)
156 return mplist_op (Push, val);
159 public object Pop (out MSymbol key)
176 return Pop (out key);
179 public MPlist Add (MSymbol key, object val)
183 for (p = this; ! p.IsEmpty; p = p.next);
184 return p.Push (key, val);
187 // Implement IEnumerable interface.
188 // foreach (MPlist p in plist) { ... }
190 public virtual IEnumerator GetEnumerator ()
192 return new Enumerator (this);
195 private class Enumerator : IEnumerator
197 private MPlist plist;
198 private MPlist current;
200 internal Enumerator (MPlist plist)
205 public object Current
208 if (current == null || current.IsEmpty)
209 throw new InvalidOperationException ();
219 public bool MoveNext ()
224 current = current.next;
225 return (! current.IsEmpty);
230 public class MStreamReader : StreamReader
232 private static char[] escaped_char = new char[128];
233 private static int[] hexadecimal = new int[128];
235 public MStreamReader (Stream stream) : base (stream)
239 static MStreamReader ()
241 for (int i = 0; i < 128; i++)
242 escaped_char[i] = (char) i;
243 escaped_char['e'] = (char) 27;
244 escaped_char['b'] = '\b';
245 escaped_char['f'] = '\f';
246 escaped_char['n'] = '\n';
247 escaped_char['r'] = '\r';
248 escaped_char['t'] = '\t';
249 escaped_char['\\'] = '\\';
250 for (int i = 0; i < 128; i++)
252 for (int i = '0'; i <= '9'; i++)
253 hexadecimal[i] = i - '0';
254 for (int i = 'A'; i <= 'F'; i++)
255 hexadecimal[i] = hexadecimal[i + 'a' - 'A'] = i -'A' + 10;
258 internal int PeekChar ()
260 bool comment = false;
263 while ((c = Peek ()) != -1)
267 if ((c = Read ()) == '\n')
274 else if (c != ' ' && c != '\t' && c != '\n')
282 internal int ReadHexadecimal ()
286 while ((c = Peek ()) >= 0 && c < 128 && (c = hexadecimal[c]) >= 0)
294 internal int ReadInteger ()
298 while ((c = Peek ()) >= '0' && c <= '9')
299 i = (i * 10) + (Read () - '0');
303 internal int ReadChar ()
312 if (c == 'x' || c == 'u')
313 return ReadHexadecimal ();
320 internal MText ReadMtext ()
322 MText mt = new MText ();
325 while ((c = Peek ()) != -1 && c != '"')
350 internal string ReadSymbolName ()
354 if (c == -1 || c == '(' || c == ' ' || c == '\n' || c == '"')
363 return (char) c + ReadSymbolName ();
366 internal bool ReadElement (out MSymbol key, out object val)
373 val = new MPlist (this);
382 else if (c >= '0' && c <= '9')
384 int i = ReadInteger ();
387 key = MSymbol.integer;
393 if (c >= '0' && c <= '9')
395 int i = ReadInteger ();
397 key = MSymbol.integer;
401 string str = ReadSymbolName ();
403 val = new MSymbol ("-" + str);
404 key = MSymbol.symbol;
411 key = MSymbol.integer;
416 if ((c = Peek ()) == 'x' || c == 'u')
419 val = ReadHexadecimal ();
420 key = MSymbol.integer;
424 string str = ReadSymbolName ();
426 val = new MSymbol ("#" + (char) c + str);
427 key = MSymbol.symbol;
430 else if (c == -1 || c == ')')
440 val = new MSymbol (ReadSymbolName ());
441 key = MSymbol.symbol;