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; } }
53 for (MPlist p = this; p.next != null; i++, p = p.next);
58 public MPlist Clone ()
60 MPlist plist = new MPlist (), pl = plist;
62 for (MPlist p = this; p.next != null; p = p.next)
63 pl = pl.Add (p.Key, p.Val);
67 public override string ToString ()
71 for (MPlist p = this; ! p.IsEmpty; p = p.next)
75 if (p.Key != MSymbol.symbol
76 && p.Key != MSymbol.integer
77 && p.Key != MSymbol.plist
78 && p.Key != MSymbol.mtext)
85 private MPlist find (MSymbol key)
89 for (p = this; ! p.IsEmpty; p = p.next)
95 public MPlist Find (MSymbol key)
97 MPlist p = find (key);
99 return (p.IsEmpty ? null : p);
102 public object Get (MSymbol key)
104 return find (key).Val;
107 private delegate MPlist MPlistDelegate (MSymbol key, object val);
109 private MPlist mplist_op (MPlistDelegate op, object val)
111 Type type = val.GetType ();
113 if (Object.ReferenceEquals (type, typeof (MSymbol)))
114 return op (MSymbol.symbol, val);
115 if (Object.ReferenceEquals (type, typeof (MText)))
116 return op (MSymbol.mtext, val);
117 if (Object.ReferenceEquals (type, typeof (MPlist)))
118 return op (MSymbol.plist, val);
119 if (Object.ReferenceEquals (type, typeof (int)))
120 return op (MSymbol.integer, val);
121 return op (MSymbol.t, val);
124 public MPlist Set (MSymbol key, object val)
133 public MPlist Set (object val)
135 return mplist_op (Set, val);
138 public MPlist Put (MSymbol key, object val)
140 return find (key).Set (key, val);
143 public MPlist Put (object val)
145 return mplist_op (Put, val);
148 public MPlist Push (MSymbol key, object val)
150 MPlist p = new MPlist (Key, Val);
159 public MPlist Push (object val)
161 return mplist_op (Push, val);
164 public object Pop (out MSymbol key)
181 return Pop (out key);
184 public MPlist Add (MSymbol key, object val)
188 for (p = this; ! p.IsEmpty; p = p.next);
189 return p.Push (key, val);
192 // Implement IEnumerable interface.
193 // foreach (MPlist p in plist) { ... }
195 public virtual IEnumerator GetEnumerator ()
197 return new Enumerator (this);
200 private class Enumerator : IEnumerator
202 private MPlist plist;
203 private MPlist current;
205 internal Enumerator (MPlist plist)
210 public object Current
213 if (current == null || current.IsEmpty)
214 throw new InvalidOperationException ();
224 public bool MoveNext ()
229 current = current.next;
230 return (! current.IsEmpty);
235 public class MStreamReader : StreamReader
237 private static char[] escaped_char = new char[128];
238 private static int[] hexadecimal = new int[128];
240 public MStreamReader (Stream stream) : base (stream)
244 static MStreamReader ()
246 for (int i = 0; i < 128; i++)
247 escaped_char[i] = (char) i;
248 escaped_char['e'] = (char) 27;
249 escaped_char['b'] = '\b';
250 escaped_char['f'] = '\f';
251 escaped_char['n'] = '\n';
252 escaped_char['r'] = '\r';
253 escaped_char['t'] = '\t';
254 escaped_char['\\'] = '\\';
255 for (int i = 0; i < 128; i++)
257 for (int i = '0'; i <= '9'; i++)
258 hexadecimal[i] = i - '0';
259 for (int i = 'A'; i <= 'F'; i++)
260 hexadecimal[i] = hexadecimal[i + 'a' - 'A'] = i -'A' + 10;
263 internal int PeekChar ()
265 bool comment = false;
268 while ((c = Peek ()) != -1)
272 if ((c = Read ()) == '\n')
279 else if (c != ' ' && c != '\t' && c != '\n')
287 internal int ReadHexadecimal ()
291 while ((c = Peek ()) >= 0 && c < 128 && (c = hexadecimal[c]) >= 0)
299 internal int ReadInteger ()
303 while ((c = Peek ()) >= '0' && c <= '9')
304 i = (i * 10) + (Read () - '0');
308 internal int ReadChar ()
317 if (c == 'x' || c == 'u')
318 return ReadHexadecimal ();
325 internal MText ReadMtext ()
327 MText mt = new MText ();
330 while ((c = Peek ()) != -1 && c != '"')
355 internal string ReadSymbolName ()
359 if (c == -1 || c == '(' || c == ' ' || c == '\n' || c == '"')
368 return (char) c + ReadSymbolName ();
371 internal bool ReadElement (out MSymbol key, out object val)
378 val = new MPlist (this);
387 else if (c >= '0' && c <= '9')
389 int i = ReadInteger ();
392 key = MSymbol.integer;
398 if (c >= '0' && c <= '9')
400 int i = ReadInteger ();
402 key = MSymbol.integer;
406 string str = ReadSymbolName ();
408 val = new MSymbol ("-" + str);
409 key = MSymbol.symbol;
416 key = MSymbol.integer;
421 if ((c = Peek ()) == 'x' || c == 'u')
424 val = ReadHexadecimal ();
425 key = MSymbol.integer;
429 string str = ReadSymbolName ();
431 val = new MSymbol ("#" + (char) c + str);
432 key = MSymbol.symbol;
435 else if (c == -1 || c == ')')
445 val = new MSymbol (ReadSymbolName ());
446 key = MSymbol.symbol;