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 public MPlist (MStreamReader reader, int count)
37 bool result = reader.ReadElement (out key, out val);
41 if (result && --count > 0)
42 next = new MPlist (reader, count);
47 public MPlist (MStreamReader reader, MSymbol target, MSymbol stop)
57 result = reader.ReadElement (out key, out val);
60 if (key == MSymbol.plist)
62 MPlist plist = (MPlist) val;
66 if (plist.Symbol == stop)
68 if (plist.Symbol == target)
80 private MPlist (MSymbol key, object val)
86 public bool IsEmpty { get { return next == null; } }
87 public MPlist Next { get { return next; } }
89 internal bool IsSymbol { get { return Key == MSymbol.symbol; } }
90 internal bool IsMText { get { return Key == MSymbol.mtext; } }
91 internal bool IsPlist { get { return Key == MSymbol.plist; } }
92 internal bool IsInteger { get { return Key == MSymbol.integer; } }
94 internal MSymbol Symbol { get { return (MSymbol) Val; } }
95 internal MText Text { get { return (MText) Val; } }
96 internal MPlist Plist { get { return (MPlist) Val; } }
97 internal int Integer { get { return (int) Val; } }
105 for (MPlist p = this; p.next != null; i++, p = p.next);
110 public MPlist Clone ()
112 MPlist plist = new MPlist (), pl = plist;
114 for (MPlist p = this; p.next != null; p = p.next)
115 pl = pl.Add (p.Key, p.Val);
119 public override string ToString ()
123 for (MPlist p = this; ! p.IsEmpty; p = p.next)
127 if (p.Key != MSymbol.symbol
128 && p.Key != MSymbol.integer
129 && p.Key != MSymbol.plist
130 && p.Key != MSymbol.mtext)
132 if (p.Key == MSymbol.mtext)
133 str += "\"" + p.Val + "\"";
140 private MPlist find (MSymbol key)
144 for (p = this; ! p.IsEmpty; p = p.next)
150 public MPlist Find (MSymbol key)
152 MPlist p = find (key);
154 return (p.IsEmpty ? null : p);
157 public object Get (MSymbol key)
159 return find (key).Val;
162 internal MPlist Assq (MSymbol key)
164 foreach (MPlist p in this)
165 if (p.IsPlist && p.Plist.IsSymbol && p.Plist.Symbol == key)
170 private delegate MPlist MPlistDelegate (MSymbol key, object val);
172 private MPlist mplist_op (MPlistDelegate op, object val)
174 Type type = val.GetType ();
176 if (Object.ReferenceEquals (type, typeof (MSymbol)))
177 return op (MSymbol.symbol, val);
178 if (Object.ReferenceEquals (type, typeof (MText)))
179 return op (MSymbol.mtext, val);
180 if (Object.ReferenceEquals (type, typeof (MPlist)))
181 return op (MSymbol.plist, val);
182 if (Object.ReferenceEquals (type, typeof (int)))
183 return op (MSymbol.integer, val);
184 return op (MSymbol.t, val);
187 public MPlist Set (MSymbol key, object val)
196 public MPlist Set (object val)
198 return mplist_op (Set, val);
201 public MPlist Put (MSymbol key, object val)
203 return find (key).Set (key, val);
206 public MPlist Put (object val)
208 return mplist_op (Put, val);
211 public MPlist Push (MSymbol key, object val)
213 MPlist p = new MPlist (Key, Val);
222 public MPlist Push (object val)
224 return mplist_op (Push, val);
227 public object Pop (out MSymbol key)
244 return Pop (out key);
247 public MPlist Add (MSymbol key, object val)
251 for (p = this; ! p.IsEmpty; p = p.next);
252 return p.Push (key, val);
255 public MPlist Clear ()
263 // Implement IEnumerable interface.
264 // foreach (MPlist p in plist) { ... }
266 public virtual IEnumerator GetEnumerator ()
268 return new Enumerator (this);
271 private class Enumerator : IEnumerator
273 private MPlist plist;
274 private MPlist current;
276 internal Enumerator (MPlist plist)
281 public object Current
284 if (current == null || current.IsEmpty)
285 throw new InvalidOperationException ();
295 public bool MoveNext ()
300 current = current.next;
301 return (! current.IsEmpty);
306 public class MStreamReader : StreamReader
308 private static char[] escaped_char = new char[128];
309 private static int[] hexadecimal = new int[128];
311 public MStreamReader (Stream stream) : base (stream)
315 static MStreamReader ()
317 for (int i = 0; i < 128; i++)
318 escaped_char[i] = (char) i;
319 escaped_char['e'] = (char) 27;
320 escaped_char['b'] = '\b';
321 escaped_char['f'] = '\f';
322 escaped_char['n'] = '\n';
323 escaped_char['r'] = '\r';
324 escaped_char['t'] = '\t';
325 escaped_char['\\'] = '\\';
326 for (int i = 0; i < 128; i++)
328 for (int i = '0'; i <= '9'; i++)
329 hexadecimal[i] = i - '0';
330 for (int i = 'A'; i <= 'F'; i++)
331 hexadecimal[i] = hexadecimal[i + 'a' - 'A'] = i -'A' + 10;
334 internal int PeekChar ()
336 bool comment = false;
339 while ((c = Peek ()) != -1)
343 if ((c = Read ()) == '\n')
350 else if (c != ' ' && c != '\t' && c != '\n')
358 internal int ReadHexadecimal ()
362 while ((c = Peek ()) >= 0 && c < 128 && (c = hexadecimal[c]) >= 0)
370 internal int ReadInteger ()
374 while ((c = Peek ()) >= '0' && c <= '9')
375 i = (i * 10) + (Read () - '0');
379 internal int ReadChar ()
388 if (c == 'x' || c == 'u')
389 return ReadHexadecimal ();
396 internal MText ReadMtext ()
398 MText mt = new MText ();
401 while ((c = Peek ()) != -1 && c != '"')
426 internal string ReadSymbolName ()
430 if (c == -1 || c == '(' || c == ')' || c == ' ' || c == '\n' || c == '"')
439 return (char) c + ReadSymbolName ();
442 internal bool ReadElement (out MSymbol key, out object val)
449 val = new MPlist (this);
458 else if (c >= '0' && c <= '9')
460 int i = ReadInteger ();
463 key = MSymbol.integer;
469 if (c >= '0' && c <= '9')
471 int i = ReadInteger ();
473 key = MSymbol.integer;
477 string str = ReadSymbolName ();
479 val = MSymbol.Of ("-" + str);
480 key = MSymbol.symbol;
487 key = MSymbol.integer;
492 if ((c = Peek ()) == 'x' || c == 'u')
495 val = ReadHexadecimal ();
496 key = MSymbol.integer;
500 string str = ReadSymbolName ();
502 val = MSymbol.Of ("#" + (char) c + str);
503 key = MSymbol.symbol;
506 else if (c == -1 || c == ')')
516 val = MSymbol.Of (ReadSymbolName ());
517 key = MSymbol.symbol;