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 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;
76 if (plist.IsSymbol && plist.Symbol == stop)
81 next = new MPlist (reader, stop);
85 public MPlist (FileStream stream, MSymbol target, MSymbol stop)
87 MStreamReader reader = new MStreamReader (stream);
97 result = reader.ReadElement (out this_key, out this_val);
100 if (this_key == MSymbol.plist)
102 MPlist plist = (MPlist) this_val;
106 if (plist.Symbol == stop)
108 if (plist.Symbol == target)
112 next = new MPlist ();
120 internal MPlist (MStreamReader reader)
122 bool result = reader.ReadElement (out key, out val);
125 next = new MPlist (reader);
128 private MPlist (MStreamReader reader, int count)
130 bool result = reader.ReadElement (out key, out val);
132 if (result && --count > 0)
133 next = new MPlist (reader, count);
135 next = new MPlist ();
138 private MPlist (MStreamReader reader, MSymbol stop)
141 MPlist next_plist = null;
150 result = reader.ReadElement (out this_key, out this_val);
153 if (this_key == MSymbol.plist)
155 MPlist plist = (MPlist) this_val;
157 if (plist.IsSymbol && plist.Symbol == stop)
160 if (next_plist == null)
164 next = next_plist = new MPlist ();
168 next_plist.key = this_key;
169 next_plist.val = this_val;
170 next_plist.next = new MPlist ();
171 next_plist = next_plist.next;
176 private MPlist (MStreamReader reader, MSymbol target, MSymbol stop)
187 result = reader.ReadElement (out this_key, out this_val);
190 if (this_key == MSymbol.plist)
192 MPlist plist = (MPlist) this_val;
196 if (plist.Symbol == stop)
198 if (plist.Symbol == target)
202 next = new MPlist ();
210 protected MPlist (MSymbol key, object val)
216 public bool IsEmpty { get { return next == null; } }
218 public bool IsSymbol { get { return Key == MSymbol.symbol; } }
219 public bool IsMText { get { return Key == MSymbol.mtext; } }
220 public bool IsPlist { get { return Key == MSymbol.plist; } }
221 public bool IsInteger { get { return Key == MSymbol.integer; } }
223 public MSymbol Symbol { get { return (MSymbol) val; } }
224 public MText Text { get { return (MText) val; } }
225 public MPlist Plist { get { return (MPlist) val; } }
226 public int Integer { get { return (int) val; } }
234 for (MPlist p = this; p.next != null; i++, p = p.next);
239 public MPlist this[int i]
243 for (p = this; ! p.IsEmpty && i > 0; i--, p = p.next);
244 return (i == 0 ? p : null);
248 public MPlist Clone ()
250 MPlist plist = new MPlist (), pl = plist;
252 for (MPlist p = this; p.next != null; p = p.next)
253 pl = pl.Add (p.key, p.val);
257 public override string ToString ()
261 for (MPlist p = this; ! p.IsEmpty; p = p.next)
265 if (! wf_keys.Contains (p.key))
267 if (p.key == MSymbol.mtext)
268 str += "\"" + p.val + "\"";
275 private MPlist find (MSymbol key)
279 for (p = this; ! p.IsEmpty; p = p.next)
285 public MPlist Find (MSymbol key)
287 MPlist p = find (key);
289 return (p.IsEmpty ? null : p);
292 public object Get (MSymbol key)
294 return find (key).val;
297 internal MPlist Assq (MSymbol key)
299 foreach (MPlist p in this)
300 if (p.IsPlist && p.Plist.IsSymbol && p.Plist.Symbol == key)
305 private delegate MPlist MPlistDelegate (MSymbol key, object val);
307 private MPlist mplist_op (MPlistDelegate op, object val)
309 Type type = val.GetType ();
311 if (Object.ReferenceEquals (type, typeof (MSymbol)))
312 return op (MSymbol.symbol, val);
313 if (Object.ReferenceEquals (type, typeof (MText)))
314 return op (MSymbol.mtext, val);
315 if (Object.ReferenceEquals (type, typeof (MPlist)))
316 return op (MSymbol.plist, val);
317 if (Object.ReferenceEquals (type, typeof (int)))
318 return op (MSymbol.integer, val);
319 return op (MSymbol.t, val);
322 public MPlist Set (MSymbol key, object val)
334 public MPlist Set (object val)
336 return mplist_op (Set, val);
339 public MPlist Put (MSymbol key, object val)
341 return find (key).Set (key, val);
344 public MPlist Put (object val)
346 return mplist_op (Put, val);
349 public MPlist Push (MSymbol key, object val)
351 MPlist p = new MPlist (this.key, this.val);
360 public MPlist Push (object val)
362 return mplist_op (Push, val);
365 public object Pop (out MSymbol key)
371 object this_val = val;
382 return Pop (out temp);
385 public MPlist Add (MSymbol key, object val)
389 for (p = this; ! p.IsEmpty; p = p.next);
390 return p.Push (key, val);
393 public MPlist Cons (MSymbol key, object val)
395 MPlist plist = new MPlist ();
402 public MPlist Clear ()
410 // Implement IEnumerable interface.
411 // foreach (MPlist p in plist) { ... }
413 public virtual IEnumerator GetEnumerator ()
415 return new Enumerator (this);
418 private class Enumerator : IEnumerator
420 private MPlist plist;
421 private MPlist current;
423 internal Enumerator (MPlist plist)
428 public object Current
431 if (current == null || current.IsEmpty)
432 throw new InvalidOperationException ();
442 public bool MoveNext ()
447 current = current.next;
448 return (! current.IsEmpty);
453 public class MStreamReader : StreamReader
455 private static char[] escaped_char = new char[128];
456 private static int[] hexadecimal = new int[128];
457 private char comment_start;
458 private bool line_oriented;
460 public MStreamReader (Stream stream) : base (stream)
463 line_oriented = false;
466 public MStreamReader (Stream stream, char comment_start,
467 bool line_oriented) : base (stream)
469 this.comment_start = comment_start;
470 this.line_oriented = line_oriented;
473 static MStreamReader ()
475 for (int i = 0; i < 128; i++)
476 escaped_char[i] = (char) i;
477 escaped_char['0'] = (char) 0;
478 escaped_char['e'] = (char) 27;
479 escaped_char['a'] = '\a';
480 escaped_char['b'] = '\b';
481 escaped_char['f'] = '\f';
482 escaped_char['n'] = '\n';
483 escaped_char['r'] = '\r';
484 escaped_char['t'] = '\t';
485 escaped_char['v'] = '\v';
486 for (int i = 0; i < 128; i++)
488 for (int i = '0'; i <= '9'; i++)
489 hexadecimal[i] = i - '0';
490 for (int i = 'A'; i <= 'F'; i++)
491 hexadecimal[i] = hexadecimal[i + 'a' - 'A'] = i -'A' + 10;
494 private int ReadHexadecimal (int max)
498 while ((c = Peek ()) >= 0 && c < 128 && (c = hexadecimal[c]) >= 0)
500 if (max >= 0 && (i * 16) + c >= max)
508 public bool ForwardLine ()
511 while ((c = Read ()) >=0 && c != '\n');
515 public bool SkipSpace (out int c)
517 while ((c = Peek ()) == ' ' && c == '\t' && c == '\f')
522 public bool PeekChar (out int c)
524 while ((c = Peek ()) != -1)
526 if (c == comment_start)
528 else if (c != ' ' && c != '\t' && c != '\n')
530 else if (c == '\n' && line_oriented)
538 public bool ReadInteger (out int i)
552 i = ReadHexadecimal (-1);
556 while ((c = Peek ()) >= '0' && c <= '9')
557 i = (i * 10) + (Read () - '0');
561 public bool ReadChar (out int c)
564 if (c < 0 || (line_oriented && c == '\n'))
570 return ReadChar (out c);
573 else if (c == 'x' || c == 'u' || c == 'U')
574 c = ReadHexadecimal (0x10FFFF);
581 private bool read_string (out string str, int prefix, bool for_symbol)
583 char[] buf = new char[256];
589 buf[i++] = (char) prefix;
590 while ((c = Peek ()) >= 0
593 || (c != '(' && c != ')' && c != ' ' && c != '\t' && c != '\n')))
595 if (! ReadChar (out c))
603 buf[i++] = (char) (0xD800 + ((c - 0x10000) >> 10));
604 buf[i++] = (char) (0xDC00 + ((c - 0x10000) & 0x3FF));
609 str = new string (buf, 0, i);
611 str += new string (buf, 0, i);
615 if (c == '\"' && ! for_symbol)
620 str = new string (buf, 0, i);
622 str += new string (buf, 0, i);
624 return (str != null);
627 public bool ReadString (out string str)
629 return read_string (out str, -1, false);
632 public bool ReadMText (out MText mt)
641 if (read_string (out str, -1, false))
642 mt = new MText (str);
650 while ((c = Peek ()) == '\\')
657 mt.Cat (ReadHexadecimal (0x10FFFF));
664 public bool ReadSymbol (out MSymbol sym, int prefix)
668 if (read_string (out str, prefix, true))
670 sym = MSymbol.Of (str);
677 internal bool ReadElement (out MSymbol key, out object val)
681 if (! PeekChar (out c))
691 val = new MPlist (this);
701 else if (c >= '0' && c <= '9')
706 key = MSymbol.integer;
712 if (c >= '0' && c <= '9')
717 key = MSymbol.integer;
723 ReadSymbol (out sym, '-');
725 key = MSymbol.symbol;
731 if (ReadChar (out c))
734 key = MSymbol.integer;
745 if ((c = Peek ()) == 'x' || c == 'u')
748 val = ReadHexadecimal (-1);
749 key = MSymbol.integer;
755 ReadSymbol (out sym, '#');
757 key = MSymbol.symbol;
771 ReadSymbol (out sym, -1);
773 key = MSymbol.symbol;