2 using System.Collections;
3 using System.Collections.Generic;
10 public class MPlist : IEnumerable
16 public MSymbol Key { get { return key; } }
17 public object Val { get { return val; } }
18 public MPlist Next { get { return next; } }
20 private static List<MSymbol> wf_keys;
24 wf_keys = new List<MSymbol> ();
25 wf_keys.Add (MSymbol.symbol);
26 wf_keys.Add (MSymbol.mtext);
27 wf_keys.Add (MSymbol.plist);
28 wf_keys.Add (MSymbol.integer);
37 public MPlist (FileStream stream)
39 MStreamReader reader = new MStreamReader (stream);
40 bool result = reader.ReadElement (out key, out val);
43 next = new MPlist (reader);
46 public MPlist (FileStream stream, int count)
48 MStreamReader reader = new MStreamReader (stream);
49 bool result = reader.ReadElement (out key, out val);
51 if (result && --count > 0)
52 next = new MPlist (reader, count);
57 public MPlist (FileStream stream, MSymbol target, MSymbol stop)
59 MStreamReader reader = new MStreamReader (stream);
69 result = reader.ReadElement (out this_key, out this_val);
72 if (this_key == MSymbol.plist)
74 MPlist plist = (MPlist) this_val;
78 if (plist.Symbol == stop)
80 if (plist.Symbol == target)
92 internal MPlist (MStreamReader reader)
94 bool result = reader.ReadElement (out key, out val);
97 next = new MPlist (reader);
100 private MPlist (MStreamReader reader, int count)
102 bool result = reader.ReadElement (out key, out val);
104 if (result && --count > 0)
105 next = new MPlist (reader, count);
107 next = new MPlist ();
110 private MPlist (MStreamReader reader, MSymbol target, MSymbol stop)
121 result = reader.ReadElement (out this_key, out this_val);
124 if (this_key == MSymbol.plist)
126 MPlist plist = (MPlist) this_val;
130 if (plist.Symbol == stop)
132 if (plist.Symbol == target)
136 next = new MPlist ();
144 protected MPlist (MSymbol key, object val)
150 public bool IsEmpty { get { return next == null; } }
152 internal bool IsSymbol { get { return Key == MSymbol.symbol; } }
153 internal bool IsMText { get { return Key == MSymbol.mtext; } }
154 internal bool IsPlist { get { return Key == MSymbol.plist; } }
155 internal bool IsInteger { get { return Key == MSymbol.integer; } }
157 internal MSymbol Symbol { get { return (MSymbol) val; } }
158 internal MText Text { get { return (MText) val; } }
159 internal MPlist Plist { get { return (MPlist) val; } }
160 internal int Integer { get { return (int) val; } }
168 for (MPlist p = this; p.next != null; i++, p = p.next);
173 public MPlist Clone ()
175 MPlist plist = new MPlist (), pl = plist;
177 for (MPlist p = this; p.next != null; p = p.next)
178 pl = pl.Add (p.key, p.val);
182 public override string ToString ()
186 for (MPlist p = this; ! p.IsEmpty; p = p.next)
190 if (! wf_keys.Contains (p.key))
192 if (p.key == MSymbol.mtext)
193 str += "\"" + p.val + "\"";
200 private MPlist find (MSymbol key)
204 for (p = this; ! p.IsEmpty; p = p.next)
210 public MPlist Find (MSymbol key)
212 MPlist p = find (key);
214 return (p.IsEmpty ? null : p);
217 public object Get (MSymbol key)
219 return find (key).val;
222 internal MPlist Assq (MSymbol key)
224 foreach (MPlist p in this)
225 if (p.IsPlist && p.Plist.IsSymbol && p.Plist.Symbol == key)
230 private delegate MPlist MPlistDelegate (MSymbol key, object val);
232 private MPlist mplist_op (MPlistDelegate op, object val)
234 Type type = val.GetType ();
236 if (Object.ReferenceEquals (type, typeof (MSymbol)))
237 return op (MSymbol.symbol, val);
238 if (Object.ReferenceEquals (type, typeof (MText)))
239 return op (MSymbol.mtext, val);
240 if (Object.ReferenceEquals (type, typeof (MPlist)))
241 return op (MSymbol.plist, val);
242 if (Object.ReferenceEquals (type, typeof (int)))
243 return op (MSymbol.integer, val);
244 return op (MSymbol.t, val);
247 public MPlist Set (MSymbol key, object val)
256 public MPlist Set (object val)
258 return mplist_op (Set, val);
261 public MPlist Put (MSymbol key, object val)
263 return find (key).Set (key, val);
266 public MPlist Put (object val)
268 return mplist_op (Put, val);
271 public MPlist Push (MSymbol key, object val)
273 MPlist p = new MPlist (this.key, this.val);
282 public MPlist Push (object val)
284 return mplist_op (Push, val);
287 public object Pop (out MSymbol key)
293 object this_val = val;
304 return Pop (out temp);
307 public MPlist Add (MSymbol key, object val)
311 for (p = this; ! p.IsEmpty; p = p.next);
312 return p.Push (key, val);
315 public MPlist Clear ()
323 // Implement IEnumerable interface.
324 // foreach (MPlist p in plist) { ... }
326 public virtual IEnumerator GetEnumerator ()
328 return new Enumerator (this);
331 private class Enumerator : IEnumerator
333 private MPlist plist;
334 private MPlist current;
336 internal Enumerator (MPlist plist)
341 public object Current
344 if (current == null || current.IsEmpty)
345 throw new InvalidOperationException ();
355 public bool MoveNext ()
360 current = current.next;
361 return (! current.IsEmpty);
366 public class MStreamReader : StreamReader
368 private static char[] escaped_char = new char[128];
369 private static int[] hexadecimal = new int[128];
370 private char comment_start;
371 private bool line_oriented;
373 public MStreamReader (Stream stream) : base (stream)
376 line_oriented = false;
379 public MStreamReader (Stream stream, char comment_start,
380 bool line_oriented) : base (stream)
382 this.comment_start = comment_start;
383 this.line_oriented = line_oriented;
386 static MStreamReader ()
388 for (int i = 0; i < 128; i++)
389 escaped_char[i] = (char) i;
390 escaped_char['0'] = (char) 0;
391 escaped_char['e'] = (char) 27;
392 escaped_char['a'] = '\a';
393 escaped_char['b'] = '\b';
394 escaped_char['f'] = '\f';
395 escaped_char['n'] = '\n';
396 escaped_char['r'] = '\r';
397 escaped_char['t'] = '\t';
398 escaped_char['v'] = '\v';
399 for (int i = 0; i < 128; i++)
401 for (int i = '0'; i <= '9'; i++)
402 hexadecimal[i] = i - '0';
403 for (int i = 'A'; i <= 'F'; i++)
404 hexadecimal[i] = hexadecimal[i + 'a' - 'A'] = i -'A' + 10;
407 private int ReadHexadecimal (int max)
411 while ((c = Peek ()) >= 0 && c < 128 && (c = hexadecimal[c]) >= 0)
413 if (max >= 0 && (i * 16) + c >= max)
421 public bool ForwardLine ()
424 while ((c = Read ()) >=0 && c != '\n');
428 public bool SkipSpace (out int c)
430 while ((c = Peek ()) == ' ' && c == '\t' && c == '\f')
435 public bool PeekChar (out int c)
437 while ((c = Peek ()) != -1)
439 if (c == comment_start)
441 else if (c != ' ' && c != '\t' && c != '\n')
443 else if (c == '\n' && line_oriented)
451 public bool ReadInteger (out int i)
465 i = ReadHexadecimal (-1);
469 while ((c = Peek ()) >= '0' && c <= '9')
470 i = (i * 10) + (Read () - '0');
474 public bool ReadChar (out int c)
477 if (c < 0 || (line_oriented && c == '\n'))
483 return ReadChar (out c);
486 else if (c == 'x' || c == 'u' || c == 'U')
487 c = ReadHexadecimal (0x10FFFF);
494 private bool read_string (out string str, int prefix, bool for_symbol)
496 char[] buf = new char[256];
502 buf[i++] = (char) prefix;
503 while ((c = Peek ()) >= 0
506 || (c != '(' && c != ')' && c != ' ' && c != '\t' && c != '\n')))
508 if (! ReadChar (out c))
516 buf[i++] = (char) (0xD800 + ((c - 0x10000) >> 10));
517 buf[i++] = (char) (0xDC00 + ((c - 0x10000) & 0x3FF));
522 str = new string (buf, 0, i);
524 str += new string (buf, 0, i);
528 if (c == '\"' && ! for_symbol)
533 str = new string (buf, 0, i);
535 str += new string (buf, 0, i);
537 return (str != null);
540 public bool ReadString (out string str)
542 return read_string (out str, -1, false);
545 public bool ReadMText (out MText mt)
554 if (read_string (out str, -1, false))
555 mt = new MText (str);
563 while ((c = Peek ()) == '\\')
570 mt.Cat (ReadHexadecimal (0x10FFFF));
577 public bool ReadSymbol (out MSymbol sym, int prefix)
581 if (read_string (out str, prefix, true))
583 sym = MSymbol.Of (str);
590 internal bool ReadElement (out MSymbol key, out object val)
594 if (! PeekChar (out c))
604 val = new MPlist (this);
607 else if (c == '"' || c == '\\')
614 else if (c >= '0' && c <= '9')
619 key = MSymbol.integer;
625 if (c >= '0' && c <= '9')
630 key = MSymbol.integer;
636 ReadSymbol (out sym, '-');
638 key = MSymbol.symbol;
644 if (ReadChar (out c))
647 key = MSymbol.integer;
658 if ((c = Peek ()) == 'x' || c == 'u')
661 val = ReadHexadecimal (-1);
662 key = MSymbol.integer;
668 ReadSymbol (out sym, '#');
670 key = MSymbol.symbol;
684 ReadSymbol (out sym, -1);
686 key = MSymbol.symbol;