X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=MPlist.cs;h=35cafd8e1f736326fa700e119328b3cc32586368;hb=2d42f6c7d4ea06fec44c84d25097be67a0664318;hp=3c9b140860d8e5bd51759f48ad46e7d66a9f0dc2;hpb=2d755fa02471fd07ce009f9caf5789583a72e7ec;p=m17n%2Fm17n-lib-cs.git diff --git a/MPlist.cs b/MPlist.cs index 3c9b140..35cafd8 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,25 +9,36 @@ 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); - MSymbol key; - object val; bool result = reader.ReadElement (out key, out val); - Key = key; - Val = val; if (result) next = new MPlist (reader); } @@ -34,35 +46,60 @@ namespace M17N.Core public MPlist (FileStream stream, int count) { MStreamReader reader = new MStreamReader (stream); - MSymbol key; - object val; bool result = reader.ReadElement (out key, out val); - Key = key; - Val = 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); - MSymbol key; - object val; bool result; - Key = MSymbol.nil; - Val = null; + key = MSymbol.nil; + val = null; while (true) { - result = reader.ReadElement (out key, out val); + MSymbol this_key; + object this_val; + + result = reader.ReadElement (out this_key, out this_val); if (! result) return; - if (key == MSymbol.plist) + if (this_key == MSymbol.plist) { - MPlist plist = (MPlist) val; + MPlist plist = (MPlist) this_val; if (plist.IsSymbol) { @@ -70,8 +107,8 @@ namespace M17N.Core return; if (plist.Symbol == target) { - Key = target; - Val = val; + key = target; + val = this_val; next = new MPlist (); return; } @@ -80,48 +117,79 @@ namespace M17N.Core } } - private 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 (MStreamReader reader, int count) { - MSymbol key; - object val; bool result = reader.ReadElement (out key, out val); - Key = key; - Val = 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) { - MSymbol key; - object val; bool result; - Key = MSymbol.nil; - Val = null; + key = MSymbol.nil; + val = null; while (true) { - result = reader.ReadElement (out key, out val); + MSymbol this_key; + object this_val; + + result = reader.ReadElement (out this_key, out this_val); if (! result) return; - if (key == MSymbol.plist) + if (this_key == MSymbol.plist) { - MPlist plist = (MPlist) val; + MPlist plist = (MPlist) this_val; if (plist.IsSymbol) { @@ -129,8 +197,8 @@ namespace M17N.Core return; if (plist.Symbol == target) { - Key = target; - Val = val; + key = target; + val = this_val; next = new MPlist (); return; } @@ -139,24 +207,23 @@ namespace M17N.Core } } - private MPlist (MSymbol key, object val) + 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; } } - 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 { @@ -169,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; } @@ -186,15 +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 + ":"; - if (p.Key == MSymbol.mtext) - str += "\"" + p.Val + "\""; + if (! wf_keys.Contains (p.key)) + str += p.key + ":"; + if (p.key == MSymbol.mtext) + str += "\"" + p.val + "\""; else - str += p.Val; + str += p.val; } return str + ")"; } @@ -204,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; } @@ -218,7 +291,7 @@ namespace M17N.Core public object Get (MSymbol key) { - return find (key).Val; + return find (key).val; } internal MPlist Assq (MSymbol key) @@ -251,7 +324,7 @@ namespace M17N.Core if (IsEmpty) Push (key, val); else - Val = val; + this.val = val; return this; } @@ -272,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; } @@ -288,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) @@ -314,10 +387,19 @@ 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; + key = MSymbol.nil; + val = null; next = null; return this; } @@ -363,220 +445,331 @@ namespace M17N.Core return (! current.IsEmpty); } } + } - private class MStreamReader : StreamReader - { - private static char[] escaped_char = new char[128]; - private static int[] hexadecimal = new int[128]; - - public MStreamReader (Stream stream) : base (stream) - { - } - - static MStreamReader () - { - for (int i = 0; i < 128; i++) - escaped_char[i] = (char) i; - escaped_char['e'] = (char) 27; - escaped_char['b'] = '\b'; - escaped_char['f'] = '\f'; - escaped_char['n'] = '\n'; - escaped_char['r'] = '\r'; - escaped_char['t'] = '\t'; - escaped_char['\\'] = '\\'; - for (int i = 0; i < 128; i++) - hexadecimal[i] = -1; - for (int i = '0'; i <= '9'; i++) - hexadecimal[i] = i - '0'; - for (int i = 'A'; i <= 'F'; i++) - hexadecimal[i] = hexadecimal[i + 'a' - 'A'] = i -'A' + 10; - } + public class MStreamReader : StreamReader + { + private static char[] escaped_char = new char[128]; + private static int[] hexadecimal = new int[128]; + private char comment_start; + private bool line_oriented; - private int PeekChar () + public MStreamReader (Stream stream) : base (stream) { - bool comment = false; - int c; - - while ((c = Peek ()) != -1) - { - if (comment) - { - if ((c = Read ()) == '\n') - comment = false; - } - else - { - if (c == ';') - comment = true; - else if (c != ' ' && c != '\t' && c != '\n') - return c; - Read (); - } - } - return c; + comment_start = ';'; + line_oriented = false; } - private int ReadHexadecimal () + public MStreamReader (Stream stream, char comment_start, + bool line_oriented) : base (stream) { - int i = 0, c; - - while ((c = Peek ()) >= 0 && c < 128 && (c = hexadecimal[c]) >= 0) - { - Read (); - i = (i * 16) + c; - } - return i; + this.comment_start = comment_start; + this.line_oriented = line_oriented; } - private int ReadInteger () + static MStreamReader () { - int i = 0, c; - - while ((c = Peek ()) >= '0' && c <= '9') - i = (i * 10) + (Read () - '0'); - return i; + 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['v'] = '\v'; + for (int i = 0; i < 128; i++) + hexadecimal[i] = -1; + for (int i = '0'; i <= '9'; i++) + hexadecimal[i] = i - '0'; + for (int i = 'A'; i <= 'F'; i++) + hexadecimal[i] = hexadecimal[i + 'a' - 'A'] = i -'A' + 10; } - private int ReadChar () - { - int c = Read (); + private int ReadHexadecimal (int max) + { + int i = 0, c; - if (c == '\\') - { - c = Read (); - if (c == -1) - return -1; - if (c == 'x' || c == 'u') - return ReadHexadecimal (); - if (c < 128) - c = escaped_char[c]; - } - return c; - } + while ((c = Peek ()) >= 0 && c < 128 && (c = hexadecimal[c]) >= 0) + { + if (max >= 0 && (i * 16) + c >= max) + break; + Read (); + i = (i * 16) + c; + } + return i; + } - private MText ReadMtext () - { - MText mt = new MText (); - int c; + public bool ForwardLine () + { + int c; + while ((c = Read ()) >=0 && c != '\n'); + return (c == '\n'); + } - while ((c = Peek ()) != -1 && c != '"') - { - if (c == '\\') - { - c = ReadChar (); - if (Peek () == '\n') - { - ReadChar (); - continue; - } - if (c == -1) - { - mt.Cat ('\\'); - break; - } - mt.Cat (c); - } - else - mt.Cat (Read ()); - } - if (c == '"') + 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) + { + 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 false; + } + + public bool ReadInteger (out int i) + { + int c = Peek (); + + i = 0; + if (c < 0) + return false; + if (c == '0') + { Read (); - return mt; - } + c = Peek (); + if (c == 'x') + { + Read (); + i = ReadHexadecimal (-1); + return true; + } + } + while ((c = Peek ()) >= '0' && c <= '9') + i = (i * 10) + (Read () - '0'); + return true; + } - private string ReadSymbolName () - { - int c = Peek (); + public bool ReadChar (out int c) + { + c = Read (); + if (c < 0 || (line_oriented && c == '\n')) + return false; + if (c == '\\') + { + c = Read (); + 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 true; + } - if (c == -1 || c == '(' || c == ')' || c == ' ' || c == '\n' || c == '"') - return ""; + private bool read_string (out string str, int prefix, bool for_symbol) + { + char[] buf = new char[256]; + int 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 (! ReadChar (out c)) + break; + if (c < 0x10000) + { + buf[i++] = (char) c; + } + else + { + 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 == '\"' && ! for_symbol) Read (); - if (c == '\\') - { - c = Read (); - if (c == -1) - c = '\\'; - } - return (char) c + ReadSymbolName (); - } + if (i > 0) + { + if (str == null) + str = new string (buf, 0, i); + else + str += new string (buf, 0, i); + } + return (str != null); + } - public bool ReadElement (out MSymbol key, out object val) - { - int c = PeekChar (); + public bool ReadString (out string str) + { + return read_string (out str, -1, false); + } - if (c == '(') - { - Read (); - val = new MPlist (this); - key = MSymbol.plist; - } - else if (c == '"') - { - Read (); - val = ReadMtext (); - key = MSymbol.mtext; - } - else if (c >= '0' && c <= '9') - { - int i = ReadInteger (); + public bool ReadMText (out MText mt) + { + int c = Peek (); - val = i; - key = MSymbol.integer; - } - else if (c == '-') - { - Read (); - c = Peek (); - if (c >= '0' && c <= '9') - { - int i = ReadInteger (); - val = - i; - key = MSymbol.integer; - } - else - { - string str = ReadSymbolName (); + if (c == '"') + { + string str; - val = MSymbol.Of ("-" + str); - key = MSymbol.symbol; - } - } - else if (c == '?') - { - Read (); - val = ReadChar (); - key = MSymbol.integer; - } - else if (c == '#') - { - Read (); - if ((c = Peek ()) == 'x' || c == 'u') - { - Read (); - val = ReadHexadecimal (); - key = MSymbol.integer; - } - else - { - val = MSymbol.Of ("#" + (char) c + ReadSymbolName ()); - key = MSymbol.symbol; - } - } - else if (c == -1 || c == ')') - { - if (c == ')') + Read (); + if (read_string (out str, -1, false)) + mt = new MText (str); + else + mt = new MText (); + return true; + } + mt = new MText (); + if (c == '\\') + { + while ((c = Peek ()) == '\\') + { Read (); - val = null; - key = MSymbol.nil; - return false; - } - else - { - val = MSymbol.Of (ReadSymbolName ()); - key = MSymbol.symbol; - } - return true; - } + 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; + } + sym = MSymbol.nil; + return false; + } + + internal bool ReadElement (out MSymbol key, out object val) + { + int c; + + if (! PeekChar (out c)) + { + val = null; + key = MSymbol.nil; + return false; + } + + if (c == '(') + { + Read (); + val = new MPlist (this); + key = MSymbol.plist; + } + else if (c == '"' || c == '\\') + { + MText mt; + ReadMText (out mt); + val = mt; + key = MSymbol.mtext; + } + else if (c >= '0' && c <= '9') + { + int i; + ReadInteger (out i); + val = i; + key = MSymbol.integer; + } + else if (c == '-') + { + Read (); + c = Peek (); + if (c >= '0' && c <= '9') + { + int i; + ReadInteger (out i); + val = - i; + key = MSymbol.integer; + } + else + { + MSymbol sym; + + ReadSymbol (out sym, '-'); + val = sym; + key = MSymbol.symbol; + } + } + else if (c == '?') + { + Read (); + if (ReadChar (out c)) + { + val = c; + key = MSymbol.integer; + } + else + { + val = null; + key = MSymbol.nil; + } + } + else if (c == '#') + { + Read (); + if ((c = Peek ()) == 'x' || c == 'u') + { + Read (); + val = ReadHexadecimal (-1); + key = MSymbol.integer; + } + else + { + MSymbol sym; + + ReadSymbol (out sym, '#'); + val = sym; + key = MSymbol.symbol; + } + } + else if (c == ')') + { + Read (); + val = null; + key = MSymbol.nil; + return false; + } + else + { + MSymbol sym; + + ReadSymbol (out sym, -1); + val = sym; + key = MSymbol.symbol; + } + return true; } } }