X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=MPlist.cs;h=6b89ac1f3e6da2e752cb8cec034202360e134749;hb=6da38c4d8072a32a940434f3a5dfa7a9e6b24b1f;hp=6bf1f0c35ef92fba360f1f598057288ed4f167ec;hpb=80a46f5fb11e98798ea0490008ec61cd36c9f5a5;p=m17n%2Fm17n-lib-cs.git diff --git a/MPlist.cs b/MPlist.cs index 6bf1f0c..6b89ac1 100644 --- a/MPlist.cs +++ b/MPlist.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Collections.Generic; using System.IO; using M17N; using M17N.Core; @@ -8,41 +9,221 @@ namespace 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 wf_keys; + + static MPlist () + { + wf_keys = new List (); + 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 (FileStream stream) + { + MStreamReader reader = new MStreamReader (stream); + bool result = reader.ReadElement (out key, out val); + + if (result) + next = new MPlist (reader); + } + + public MPlist (FileStream stream, int count) + { + 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; + } + } + } + } } - public MPlist (MStreamReader reader) + internal MPlist (MStreamReader reader) { - MSymbol key; - object val; bool result = reader.ReadElement (out key, out val); - Key = key; - Val = val; if (result) next = new MPlist (reader); } - private MPlist (MSymbol key, object val) + 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) { - Key = key; - Val = 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; } } + + 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 { @@ -55,12 +236,21 @@ namespace M17N.Core } } + 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; } @@ -72,12 +262,12 @@ namespace M17N.Core { 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 + ")"; } @@ -87,7 +277,7 @@ namespace M17N.Core MPlist p; for (p = this; ! p.IsEmpty; p = p.next) - if (p.Key == key) + if (p.key == key) break; return p; } @@ -101,7 +291,15 @@ namespace M17N.Core 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); @@ -126,7 +324,7 @@ namespace M17N.Core if (IsEmpty) Push (key, val); else - Val = val; + this.val = val; return this; } @@ -147,11 +345,11 @@ namespace M17N.Core 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; } @@ -163,22 +361,22 @@ namespace M17N.Core 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) @@ -189,6 +387,23 @@ namespace M17N.Core 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) { ... } @@ -236,22 +451,35 @@ namespace M17N.Core { 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++) @@ -260,117 +488,199 @@ namespace M17N.Core 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 == '(') { @@ -380,14 +690,15 @@ namespace M17N.Core } 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; } @@ -397,23 +708,33 @@ namespace M17N.Core 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 == '#') { @@ -421,28 +742,31 @@ namespace M17N.Core 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;