using System;
using System.Collections;
+using System.Collections.Generic;
using System.IO;
using M17N;
using M17N.Core;
{
public class MPlist : IEnumerable
{
- public MSymbol Key;
- public object Val;
- private MPlist next;
+ public MSymbol key;
+ public object val;
+ public MPlist next;
+
+ public MSymbol Key { get { return key; } }
+ public object Val { get { return val; } }
+ public MPlist Next { get { return next; } }
+
+ private static List<MSymbol> wf_keys;
+
+ static MPlist ()
+ {
+ wf_keys = new List<MSymbol> ();
+ wf_keys.Add (MSymbol.symbol);
+ wf_keys.Add (MSymbol.mtext);
+ wf_keys.Add (MSymbol.plist);
+ wf_keys.Add (MSymbol.integer);
+ }
public MPlist ()
{
- Key = MSymbol.nil;
- Val = null;
+ key = MSymbol.nil;
+ val = null;
}
- public MPlist (MStreamReader reader)
+ public MPlist (FileStream stream)
{
- MSymbol key;
- object val;
+ MStreamReader reader = new MStreamReader (stream);
bool result = reader.ReadElement (out key, out val);
- Key = key;
- Val = val;
if (result)
next = new MPlist (reader);
}
- private MPlist (MSymbol key, object val)
+ public MPlist (FileStream stream, int count)
{
- Key = key;
- Val = val;
+ MStreamReader reader = new MStreamReader (stream);
+ bool result = reader.ReadElement (out key, out val);
+
+ if (result && --count > 0)
+ next = new MPlist (reader, count);
+ else
+ next = new MPlist ();
+ }
+
+ public MPlist (FileStream stream, MSymbol stop)
+ {
+ MStreamReader reader = new MStreamReader (stream);
+ bool result;
+
+ key = MSymbol.nil;
+ val = null;
+ while (true)
+ {
+ MSymbol this_key;
+ object this_val;
+
+ result = reader.ReadElement (out this_key, out this_val);
+ if (! result)
+ return;
+ if (this_key == MSymbol.plist)
+ {
+ MPlist plist = (MPlist) this_val;
+
+ if (plist.IsSymbol && plist.Symbol == stop)
+ return;
+ }
+ key = this_key;
+ val = this_val;
+ next = new MPlist (reader, stop);
+ }
+ }
+
+ public MPlist (FileStream stream, MSymbol target, MSymbol stop)
+ {
+ MStreamReader reader = new MStreamReader (stream);
+ bool result;
+
+ key = MSymbol.nil;
+ val = null;
+ while (true)
+ {
+ MSymbol this_key;
+ object this_val;
+
+ result = reader.ReadElement (out this_key, out this_val);
+ if (! result)
+ return;
+ if (this_key == MSymbol.plist)
+ {
+ MPlist plist = (MPlist) this_val;
+
+ if (plist.IsSymbol)
+ {
+ if (plist.Symbol == stop)
+ return;
+ if (plist.Symbol == target)
+ {
+ key = target;
+ val = this_val;
+ next = new MPlist ();
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ internal MPlist (MStreamReader reader)
+ {
+ bool result = reader.ReadElement (out key, out val);
+
+ if (result)
+ next = new MPlist (reader);
+ }
+
+ private MPlist (MStreamReader reader, int count)
+ {
+ bool result = reader.ReadElement (out key, out val);
+
+ if (result && --count > 0)
+ next = new MPlist (reader, count);
+ else
+ next = new MPlist ();
+ }
+
+ private MPlist (MStreamReader reader, MSymbol stop)
+ {
+ bool result;
+ MPlist next_plist = null;
+
+ key = MSymbol.nil;
+ val = null;
+ while (true)
+ {
+ MSymbol this_key;
+ object this_val;
+
+ result = reader.ReadElement (out this_key, out this_val);
+ if (! result)
+ return;
+ if (this_key == MSymbol.plist)
+ {
+ MPlist plist = (MPlist) this_val;
+
+ if (plist.IsSymbol && plist.Symbol == stop)
+ return;
+ }
+ if (next_plist == null)
+ {
+ key = this_key;
+ val = this_val;
+ next = next_plist = new MPlist ();
+ }
+ else
+ {
+ next_plist.key = this_key;
+ next_plist.val = this_val;
+ next_plist.next = new MPlist ();
+ next_plist = next_plist.next;
+ }
+ }
+ }
+
+ private MPlist (MStreamReader reader, MSymbol target, MSymbol stop)
+ {
+ bool result;
+
+ key = MSymbol.nil;
+ val = null;
+ while (true)
+ {
+ MSymbol this_key;
+ object this_val;
+
+ result = reader.ReadElement (out this_key, out this_val);
+ if (! result)
+ return;
+ if (this_key == MSymbol.plist)
+ {
+ MPlist plist = (MPlist) this_val;
+
+ if (plist.IsSymbol)
+ {
+ if (plist.Symbol == stop)
+ return;
+ if (plist.Symbol == target)
+ {
+ key = target;
+ val = this_val;
+ next = new MPlist ();
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ protected MPlist (MSymbol key, object val)
+ {
+ this.key = key;
+ this.val = val;
}
public bool IsEmpty { get { return next == null; } }
- public MPlist Next { get { return next; } }
- internal bool IsSymbol { get { return Key == MSymbol.symbol; } }
- internal bool IsMText { get { return Key == MSymbol.mtext; } }
- internal bool IsPlist { get { return Key == MSymbol.plist; } }
- internal bool IsInteger { get { return Key == MSymbol.integer; } }
+ public bool IsSymbol { get { return Key == MSymbol.symbol; } }
+ public bool IsMText { get { return Key == MSymbol.mtext; } }
+ public bool IsPlist { get { return Key == MSymbol.plist; } }
+ public bool IsInteger { get { return Key == MSymbol.integer; } }
- internal MSymbol Symbol { get { return (MSymbol) Val; } }
- internal MText Text { get { return (MText) Val; } }
- internal MPlist Plist { get { return (MPlist) Val; } }
- internal int Integer { get { return (int) Val; } }
+ public MSymbol Symbol { get { return (MSymbol) val; } }
+ public MText Text { get { return (MText) val; } }
+ public MPlist Plist { get { return (MPlist) val; } }
+ public int Integer { get { return (int) val; } }
public int Count
{
}
}
+ public MPlist this[int i]
+ {
+ get {
+ MPlist p;
+ for (p = this; ! p.IsEmpty && i > 0; i--, p = p.next);
+ return (i == 0 ? p : null);
+ }
+ }
+
public MPlist Clone ()
{
MPlist plist = new MPlist (), pl = plist;
for (MPlist p = this; p.next != null; p = p.next)
- pl = pl.Add (p.Key, p.Val);
+ pl = pl.Add (p.key, p.val);
return plist;
}
{
if (p != this)
str += " ";
- if (p.Key != MSymbol.symbol
- && p.Key != MSymbol.integer
- && p.Key != MSymbol.plist
- && p.Key != MSymbol.mtext)
- str += p.Key + ":";
- str += p.Val;
+ if (! wf_keys.Contains (p.key))
+ str += p.key + ":";
+ if (p.key == MSymbol.mtext)
+ str += "\"" + p.val + "\"";
+ else
+ str += p.val;
}
return str + ")";
}
MPlist p;
for (p = this; ! p.IsEmpty; p = p.next)
- if (p.Key == key)
+ if (p.key == key)
break;
return p;
}
public object Get (MSymbol key)
{
- return find (key).Val;
+ return find (key).val;
+ }
+
+ internal MPlist Assq (MSymbol key)
+ {
+ foreach (MPlist p in this)
+ if (p.IsPlist && p.Plist.IsSymbol && p.Plist.Symbol == key)
+ return p;
+ return null;
}
private delegate MPlist MPlistDelegate (MSymbol key, object val);
if (IsEmpty)
Push (key, val);
else
- Val = val;
+ {
+ this.key = key;
+ this.val = val;
+ }
return this;
}
public MPlist Push (MSymbol key, object val)
{
- MPlist p = new MPlist (Key, Val);
+ MPlist p = new MPlist (this.key, this.val);
p.next = this.next;
- Key = key;
- Val = val;
+ this.key = key;
+ this.val = val;
next = p;
return this;
}
public object Pop (out MSymbol key)
{
- key = Key;
+ key = this.key;
if (IsEmpty)
return null;
- object val = Val;
+ object this_val = val;
- Key = next.Key;
- Val = next.Val;
+ this.key = next.key;
+ this.val = next.val;
next = next.next;
- return val;
+ return this_val;
}
public object Pop ()
{
- MSymbol key;
- return Pop (out key);
+ MSymbol temp;
+ return Pop (out temp);
}
public MPlist Add (MSymbol key, object val)
return p.Push (key, val);
}
+ public MPlist Cons (MSymbol key, object val)
+ {
+ MPlist plist = new MPlist ();
+ plist.key = key;
+ plist.val = val;
+ plist.next = this;
+ return plist;
+ }
+
+ public MPlist Clear ()
+ {
+ key = MSymbol.nil;
+ val = null;
+ next = null;
+ return this;
+ }
+
// Implement IEnumerable interface.
// foreach (MPlist p in plist) { ... }
{
private static char[] escaped_char = new char[128];
private static int[] hexadecimal = new int[128];
+ private char comment_start;
+ private bool line_oriented;
public MStreamReader (Stream stream) : base (stream)
{
+ comment_start = ';';
+ line_oriented = false;
+ }
+
+ public MStreamReader (Stream stream, char comment_start,
+ bool line_oriented) : base (stream)
+ {
+ this.comment_start = comment_start;
+ this.line_oriented = line_oriented;
}
static MStreamReader ()
{
for (int i = 0; i < 128; i++)
escaped_char[i] = (char) i;
+ escaped_char['0'] = (char) 0;
escaped_char['e'] = (char) 27;
+ escaped_char['a'] = '\a';
escaped_char['b'] = '\b';
escaped_char['f'] = '\f';
escaped_char['n'] = '\n';
escaped_char['r'] = '\r';
escaped_char['t'] = '\t';
- escaped_char['\\'] = '\\';
+ escaped_char['v'] = '\v';
for (int i = 0; i < 128; i++)
hexadecimal[i] = -1;
for (int i = '0'; i <= '9'; i++)
hexadecimal[i] = hexadecimal[i + 'a' - 'A'] = i -'A' + 10;
}
- internal int PeekChar ()
+ private int ReadHexadecimal (int max)
{
- bool comment = false;
- int c;
+ int i = 0, c;
- while ((c = Peek ()) != -1)
+ while ((c = Peek ()) >= 0 && c < 128 && (c = hexadecimal[c]) >= 0)
{
- if (comment)
- {
- if ((c = Read ()) == '\n')
- comment = false;
- }
- else
- {
- if (c == ';')
- comment = true;
- else if (c != ' ' && c != '\t' && c != '\n')
- return c;
- Read ();
- }
+ if (max >= 0 && (i * 16) + c >= max)
+ break;
+ Read ();
+ i = (i * 16) + c;
}
- return c;
+ return i;
}
- internal int ReadHexadecimal ()
+ public bool ForwardLine ()
{
- int i = 0, c;
+ int c;
+ while ((c = Read ()) >=0 && c != '\n');
+ return (c == '\n');
+ }
- while ((c = Peek ()) >= 0 && c < 128 && (c = hexadecimal[c]) >= 0)
+ public bool SkipSpace (out int c)
+ {
+ while ((c = Peek ()) == ' ' && c == '\t' && c == '\f')
+ Read ();
+ return (c >= 0);
+ }
+
+ public bool PeekChar (out int c)
+ {
+ while ((c = Peek ()) != -1)
{
- Read ();
- i = (i * 16) + c;
+ if (c == comment_start)
+ ForwardLine ();
+ else if (c != ' ' && c != '\t' && c != '\n')
+ return true;
+ else if (c == '\n' && line_oriented)
+ return false;
+ else
+ Read ();
}
- return i;
+ return false;
}
- internal int ReadInteger ()
+ public bool ReadInteger (out int i)
{
- int i = 0, c;
+ int c = Peek ();
+ i = 0;
+ if (c < 0)
+ return false;
+ if (c == '0')
+ {
+ Read ();
+ c = Peek ();
+ if (c == 'x')
+ {
+ Read ();
+ i = ReadHexadecimal (-1);
+ return true;
+ }
+ }
while ((c = Peek ()) >= '0' && c <= '9')
i = (i * 10) + (Read () - '0');
- return i;
+ return true;
}
- internal int ReadChar ()
+ public bool ReadChar (out int c)
{
- int c = Read ();
-
+ c = Read ();
+ if (c < 0 || (line_oriented && c == '\n'))
+ return false;
if (c == '\\')
{
c = Read ();
- if (c == -1)
- return -1;
- if (c == 'x' || c == 'u')
- return ReadHexadecimal ();
- if (c < 128)
+ if (c == '\n')
+ return ReadChar (out c);
+ if (c < 0)
+ c = '\\';
+ else if (c == 'x' || c == 'u' || c == 'U')
+ c = ReadHexadecimal (0x10FFFF);
+ else if (c < 128)
c = escaped_char[c];
}
- return c;
+ return true;
}
- internal MText ReadMtext ()
+ private bool read_string (out string str, int prefix, bool for_symbol)
{
- MText mt = new MText ();
+ char[] buf = new char[256];
int c;
-
- while ((c = Peek ()) != -1 && c != '"')
+ int i = 0;
+
+ str = null;
+ if (prefix >= 0)
+ buf[i++] = (char) prefix;
+ while ((c = Peek ()) >= 0
+ && c != '\"'
+ && (! for_symbol
+ || (c != '(' && c != ')' && c != ' ' && c != '\t' && c != '\n')))
{
- if (c == '\\')
+ if (! ReadChar (out c))
+ break;
+ if (c < 0x10000)
{
- c = ReadChar ();
- if (Peek () == '\n')
- {
- ReadChar ();
- continue;
- }
- if (c == -1)
- {
- mt.Cat ('\\');
- break;
- }
- mt.Cat (c);
+ buf[i++] = (char) c;
}
else
- mt.Cat (Read ());
+ {
+ buf[i++] = (char) (0xD800 + ((c - 0x10000) >> 10));
+ buf[i++] = (char) (0xDC00 + ((c - 0x10000) & 0x3FF));
+ }
+ if (i >= 255)
+ {
+ if (str == null)
+ str = new string (buf, 0, i);
+ else
+ str += new string (buf, 0, i);
+ i = 0;
+ }
}
- if (c == '"')
+ if (c == '\"' && ! for_symbol)
Read ();
- return mt;
+ if (i > 0)
+ {
+ if (str == null)
+ str = new string (buf, 0, i);
+ else
+ str += new string (buf, 0, i);
+ }
+ return (str != null);
}
- internal string ReadSymbolName ()
+ public bool ReadString (out string str)
+ {
+ return read_string (out str, -1, false);
+ }
+
+ public bool ReadMText (out MText mt)
{
int c = Peek ();
- if (c == -1 || c == '(' || c == ' ' || c == '\n' || c == '"')
- return "";
- Read ();
+ if (c == '"')
+ {
+ string str;
+
+ Read ();
+ if (read_string (out str, -1, false))
+ mt = new MText (str);
+ else
+ mt = new MText ();
+ return true;
+ }
+ mt = new MText ();
if (c == '\\')
{
- c = Read ();
- if (c == -1)
- c = '\\';
+ while ((c = Peek ()) == '\\')
+ {
+ Read ();
+ c = Peek ();
+ if (c != 'x')
+ break;
+ Read ();
+ mt.Cat (ReadHexadecimal (0x10FFFF));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public bool ReadSymbol (out MSymbol sym, int prefix)
+ {
+ string str;
+
+ if (read_string (out str, prefix, true))
+ {
+ sym = MSymbol.Of (str);
+ return true;
}
- return (char) c + ReadSymbolName ();
+ sym = MSymbol.nil;
+ return false;
}
internal bool ReadElement (out MSymbol key, out object val)
{
- int c = PeekChar ();
+ int c;
+
+ if (! PeekChar (out c))
+ {
+ val = null;
+ key = MSymbol.nil;
+ return false;
+ }
if (c == '(')
{
}
else if (c == '"')
{
- Read ();
- val = ReadMtext ();
+ MText mt;
+ ReadMText (out mt);
+ val = mt;
key = MSymbol.mtext;
}
else if (c >= '0' && c <= '9')
{
- int i = ReadInteger ();
-
+ int i;
+ ReadInteger (out i);
val = i;
key = MSymbol.integer;
}
c = Peek ();
if (c >= '0' && c <= '9')
{
- int i = ReadInteger ();
+ int i;
+ ReadInteger (out i);
val = - i;
key = MSymbol.integer;
}
else
{
- string str = ReadSymbolName ();
+ MSymbol sym;
- val = new MSymbol ("-" + str);
+ ReadSymbol (out sym, '-');
+ val = sym;
key = MSymbol.symbol;
}
}
else if (c == '?')
{
Read ();
- val = ReadChar ();
- key = MSymbol.integer;
+ if (ReadChar (out c))
+ {
+ val = c;
+ key = MSymbol.integer;
+ }
+ else
+ {
+ val = null;
+ key = MSymbol.nil;
+ }
}
else if (c == '#')
{
if ((c = Peek ()) == 'x' || c == 'u')
{
Read ();
- val = ReadHexadecimal ();
+ val = ReadHexadecimal (-1);
key = MSymbol.integer;
}
else
{
- string str = ReadSymbolName ();
+ MSymbol sym;
- val = new MSymbol ("#" + (char) c + str);
+ ReadSymbol (out sym, '#');
+ val = sym;
key = MSymbol.symbol;
}
}
- else if (c == -1 || c == ')')
+ else if (c == ')')
{
- if (c == ')')
- Read ();
+ Read ();
val = null;
key = MSymbol.nil;
return false;
}
else
{
- val = new MSymbol (ReadSymbolName ());
+ MSymbol sym;
+
+ ReadSymbol (out sym, -1);
+ val = sym;
key = MSymbol.symbol;
}
return true;