*** empty log message ***
authorhanda <handa>
Mon, 19 Oct 2009 14:05:53 +0000 (14:05 +0000)
committerhanda <handa>
Mon, 19 Oct 2009 14:05:53 +0000 (14:05 +0000)
MDatabase.cs
MInputMethod.cs
XmlExpr.cs
input.cs

index 6ac8291..01d5755 100644 (file)
@@ -968,12 +968,6 @@ namespace M17N.Core
 
     private FileStream get_stream ()
     {
-      if (loader != null
-         || (Info.Format != MSymbol.plist && Info.Format != Mxml))
-       {
-         LastLoadStatus = LoadStatus.InvalidLoadMethod;
-         return null;
-       }
       if (DBStatus != MDBStatus.READY)
        {
          LastLoadStatus = LoadStatus.NotAvailable;
@@ -989,8 +983,6 @@ namespace M17N.Core
       return stream;
     }
 
-    private NameTable name_table = new NameTable ();
-
     public MPlist Load ()
     {
       if (loader != null)
@@ -1013,138 +1005,163 @@ namespace M17N.Core
       return plist;
     }
 
-    public void Load (XmlDocument doc)
+    public MPlist Load (MSymbol key, MSymbol stop)
     {
-      if (Info.Format == Mxml)
-       throw new Exception ("Not an XML database");
-      try {
-       XmlTextReader reader
-         = new XmlTextReader (FileInfo.FullName, doc.NameTable);
-       doc.Load (reader);
-       LastLoaded = DateTime.Now;          
-      } catch (Exception e) {
-       Console.WriteLine (e);
-       LastLoadStatus = LoadStatus.InvalidContents;
-      }
-    }
+      if (loader != null)
+       throw new Exception ("Partial load is impossible");
+      if (Info.Format != MSymbol.plist)
+       throw new Exception ("Not a plist database");
 
-    public object Load (MSymbol key, MSymbol stop)
-    {
       FileStream stream = get_stream ();
-
       if (stream == null)
        return null;
-      if (Info.Format == Mxml)
-       {
-         XmlDocument doc = new XmlDocument (name_table);
-         XmlTextReader reader = new XmlTextReader (stream, name_table);
-
-         reader.WhitespaceHandling = WhitespaceHandling.None;
-         try {
-           reader.Read ();
-           while (reader.NodeType != XmlNodeType.Element)
-             reader.Read ();
-           doc.LoadXml ("<" + reader.Name + "></" + reader.Name + ">");
-           reader.Read ();
-           XmlNode node = doc.DocumentElement;
-           while (reader.NodeType == XmlNodeType.Element
-                  ? reader.Name != stop.Name
-                  : reader.NodeType != XmlNodeType.EndElement)
-             if (reader.NodeType == XmlNodeType.Element
-                 && reader.Name == key.Name)
-               node = doc.DocumentElement.InsertAfter (doc.ReadNode (reader),
-                                                       node);
-         } finally {
-           reader.Close ();
-           stream.Dispose ();
-         }
-         return doc;
-       }
-
-      MPlist plist = null;
       try {
-       plist = new MPlist (stream, key, stop);
+       MPlist plist = new MPlist (stream, key, stop);
        LastLoaded = DateTime.Now;
+       return plist;
       } catch {
        LastLoadStatus = LoadStatus.InvalidContents;
+       return null;
       } finally {
        stream.Dispose ();
       }
-      return plist;
     }
 
-    public object Load (MSymbol stop)
+    public MPlist Load (MSymbol stop)
     {
-      FileStream stream = get_stream ();
+      if (loader != null)
+       throw new Exception ("Partial load is impossible");
+      if (Info.Format != MSymbol.plist)
+       throw new Exception ("Not a plist database");
 
+      FileStream stream = get_stream ();
       if (stream == null)
        return null;
-      if (Info.Format == Mxml)
-       {
-         XmlDocument doc = new XmlDocument (name_table);
-         XmlTextReader reader = new XmlTextReader (stream, name_table);
-
-         reader.WhitespaceHandling = WhitespaceHandling.None;
-         try {
-           reader.Read ();
-           while (reader.NodeType != XmlNodeType.Element)
-             reader.Read ();
-           doc.LoadXml ("<" + reader.Name + "></" + reader.Name + ">");
-           reader.Read ();
-           XmlNode node = null;
-           while (reader.NodeType == XmlNodeType.Element
-                  ? reader.Name != stop.Name
-                  : reader.NodeType != XmlNodeType.EndElement)
-             if (reader.NodeType == XmlNodeType.Element)
-                 node = doc.DocumentElement.InsertAfter (doc.ReadNode (reader),
-                                                         node);
-         } catch (Exception e) {
-           Console.WriteLine (e);
-         } finally {
-           reader.Close ();
-           stream.Dispose ();
-         }
-         return doc;
-       }
-
-      MPlist plist = null;
       try {
-       plist = new MPlist (stream, stop);
+       MPlist plist = new MPlist (stream, stop);
        LastLoaded = DateTime.Now;
+       return plist;
       } catch (Exception e) {
        Console.WriteLine (e);
        LastLoadStatus = LoadStatus.InvalidContents;
+       return null;
       } finally {
        stream.Dispose ();
       }
-      return plist;
     }
 
-    public XmlNode Load (string id, params string[] nodes)
+    private XmlTextReader get_reader (XmlDocument doc)
+    {
+      XmlTextReader reader;
+
+      try {
+       if (doc.NameTable != null)
+         reader = new XmlTextReader (FileInfo.FullName, doc.NameTable);
+       else
+         reader = new XmlTextReader (FileInfo.FullName);
+       reader.WhitespaceHandling = WhitespaceHandling.None;
+      } catch {
+       LastLoadStatus = LoadStatus.NotReadable;
+       reader = null;
+      }
+      return reader;
+    }
+
+    public bool Load (XmlDocument doc)
     {
-      FileStream stream = get_stream ();
-      if (stream == null)
-       return null;
       if (Info.Format != Mxml)
-       throw new Exception ("Not an XML format");
+       throw new Exception ("Not an XML database");
+      XmlTextReader reader = get_reader (doc);
+      if (reader == null)
+       return false;
+      try {
+       doc.Load (reader);
+       LastLoaded = DateTime.Now;          
+       return true;
+      } catch (Exception e) {
+       Console.WriteLine (e);
+       LastLoadStatus = LoadStatus.InvalidContents;
+       return false;
+      } finally {
+       reader.Close ();
+      }
+    }
 
-      XmlDocument doc = new XmlDocument (name_table);
-      XmlTextReader reader = new XmlTextReader (stream, name_table);
-      int len = nodes.Length;
+    public bool Load (XmlDocument doc, MSymbol key, MSymbol stop)
+    {
+      if (Info.Format != Mxml)
+       throw new Exception ("Not an XML database");
+      XmlTextReader reader = get_reader (doc);
+      if (reader == null)
+       return false;
+      try {
+       reader.Read ();
+       while (reader.NodeType != XmlNodeType.Element)
+         reader.Read ();
+       doc.LoadXml ("<" + reader.Name + "></" + reader.Name + ">");
+       reader.Read ();
+       XmlNode node = doc.DocumentElement;
+       while (reader.NodeType == XmlNodeType.Element
+              ? reader.Name != stop.Name
+              : reader.NodeType != XmlNodeType.EndElement)
+         if (reader.NodeType == XmlNodeType.Element
+             && reader.Name == key.Name)
+           node = doc.DocumentElement.InsertAfter (doc.ReadNode (reader),
+                                                   node);
+       return true;
+      } catch (Exception e) {
+       Console.WriteLine (e);
+       return false;
+      } finally {
+       reader.Close ();
+      }
+    }
 
-      reader.WhitespaceHandling = WhitespaceHandling.None;
-      do {
+    public bool Load (XmlDocument doc, MSymbol stop)
+    {
+      if (Info.Format != Mxml)
+       throw new Exception ("Not an XML database");
+      XmlTextReader reader = get_reader (doc);
+      if (reader == null)
+       return false;
+      try {
        reader.Read ();
-      } while (reader.NodeType != XmlNodeType.Element);
+       while (reader.NodeType != XmlNodeType.Element)
+         reader.Read ();
+       doc.LoadXml ("<" + reader.Name + "></" + reader.Name + ">");
+       reader.Read ();
+       XmlNode node = doc.DocumentElement;
+       while (reader.NodeType == XmlNodeType.Element
+              ? reader.Name != stop.Name
+              : reader.NodeType != XmlNodeType.EndElement)
+         node = doc.DocumentElement.InsertAfter (doc.ReadNode (reader), node);
+       return true;
+      } catch (Exception e) {
+       Console.WriteLine (e);
+       return false;
+      } finally {
+       reader.Close ();
+      }
+    }
 
-      if (reader.Name != nodes[0])
+    public XmlNode Load (XmlDocument doc, string id, params string[] nodes)
+    {
+      if (Info.Format != Mxml)
+       throw new Exception ("Not an XML database");
+      XmlTextReader reader = get_reader (doc);
+      if (reader == null)
        return null;
-
-      string ns = reader.GetAttribute ("xmlns");
-      XmlNode top = doc.CreateNode (XmlNodeType.Element, nodes[0], ns);
-      XmlNode node = top;
-
       try {
+       int len = nodes.Length;
+       do {
+         reader.Read ();
+       } while (reader.NodeType != XmlNodeType.Element);
+       if (reader.Name != nodes[0])
+         return null;
+
+       string ns = reader.GetAttribute ("xmlns");
+       XmlNode top = doc.CreateNode (XmlNodeType.Element, nodes[0], ns);
+       XmlNode node = top;
        int i;
 
        for (i = 1; i + 1 < len; i++)
@@ -1170,14 +1187,13 @@ namespace M17N.Core
            else
              reader.Read ();
          }
-             
+       return top;
       } catch (Exception e) {
        Console.WriteLine (e);
+       return null;
       } finally {
        reader.Close ();
-       stream.Dispose ();
       }
-      return top;
     }
 
     /// <summary>Return a list of currently available database
index 60e48d0..c535112 100644 (file)
@@ -41,6 +41,7 @@ namespace M17N.Input
     internal static MSymbol Mcandidates = "candidates";
     private static MSymbol Mat_minus_zero = "@-0";
 
+    private static Xex.Symbol Qxi_include = "xi:include";
     private static Xex.Symbol Qmap = "map";
     private static Xex.Symbol Qrule = "rule";
     private static Xex.Symbol Qkeyseq = "keyseq";
@@ -591,10 +592,7 @@ namespace M17N.Input
        {
         char tag;
 
-        public Predefined (MSymbol name) : base (name)
-          {
-            tag = ((string) name)[1];
-          }
+        public Predefined (char tag) : base ("@" + tag) { this.tag = tag; }
 
         public override int Position (Context ic)
         {
@@ -671,15 +669,20 @@ namespace M17N.Input
           }
        }
 
-       static internal Dictionary<MSymbol,Predefined> predefined_markers;
+       static internal Dictionary<MSymbol,Predefined> predefineds;
 
        static Marker ()
-       {
-        predefined_markers = new Dictionary<MSymbol, Predefined> ();
-        MSymbol[] symlist = new MSymbol[] {"@<", "@>", "@-", "@+", "@[", "@]" };
-        foreach (MSymbol s in symlist)
-          predefined_markers[s] = new Predefined (s);
-       }
+        {
+          predefineds = new Dictionary<MSymbol, Predefined> ();
+          predefineds ["@<"] = predefineds["@first"] = new Predefined ('<');
+          predefineds ["@>"] = predefineds["@last"] = new Predefined ('>');
+          predefineds ["@-"] = predefineds["@previous"] = new Predefined ('-');
+          predefineds ["@+"] = predefineds["@next"] = new Predefined ('+');
+          predefineds ["@["] = predefineds["@previous-candidate-change"]
+            = new Predefined ('[');
+          predefineds ["@]"] = predefineds["@next-candidate-change"]
+            = new Predefined (']');
+        }
 
        public static Marker Get (MSymbol name)
        {
@@ -687,7 +690,7 @@ namespace M17N.Input
         if (str[0] == '@')
           {
             Predefined pred;
-            if (predefined_markers.TryGetValue (name, out pred))
+            if (predefineds.TryGetValue (name, out pred))
               return pred;
             if (str.Length == 1)
               throw new Exception ("Invalid marker name: " + name);
@@ -1342,15 +1345,14 @@ namespace M17N.Input
       mdb = MDatabase.Find (tag);
       if (mdb == null)
        return false;
-      mdb.name_table = Xex.Symbol.Table;
       try {
-       MSymbol format = mdb.Format;
-
-       if (format == MSymbol.plist)
-         load ((MPlist) mdb.Load (Mmap), false);
+       if (mdb.Format == MSymbol.plist)
+         load (mdb.Load (Mmap), false);
        else
          {
-           XmlDocument doc = (XmlDocument) mdb.Load (Mmap_list);
+           XmlDocument doc = new XmlDocument (Xex.Symbol.NameTable);
+           if (! mdb.Load (doc, Mmap_list))
+             throw new Exception ("Load error" + mdb.tag);
            load (doc.DocumentElement, false);
          }
       } catch (Exception e) {
@@ -1367,13 +1369,16 @@ namespace M17N.Input
       mdb = MDatabase.Find (tag);
       if (mdb == null)
        return false;
-      mdb.name_table = Xex.Symbol.Table;
       try {
-       object obj = mdb.Load ();
-       if (obj is MPlist)
-         load ((MPlist) obj, true);
+       if (mdb.Format == MSymbol.plist)
+         load (mdb.Load (), true);
        else
-         load ((XmlDocument) obj, true);
+         {
+           XmlDocument doc = new XmlDocument (Xex.Symbol.NameTable);
+           if (! mdb.Load (doc))
+             throw new Exception ("Load error" + mdb.tag);
+           load (doc.DocumentElement, true);
+         }
       } catch (Exception e) {
        Console.WriteLine (e);
        load_status = LoadStatus.Error;
@@ -1457,6 +1462,7 @@ namespace M17N.Input
        node = node.NextSibling;
       for (node = node.FirstChild; node != null; node = node.NextSibling)
        {
+         Console.WriteLine (this.tag + node.Name);
          if (node.NodeType != XmlNodeType.Element)
            continue;
          if (! skip_header)
@@ -1470,7 +1476,7 @@ namespace M17N.Input
              else if (node.Name == "command-list")
                parse_commands (node);
            }
-         else if (full)
+         if (full)
            {
              if (node.Name == "module-list")
                parse_plugins (node);
@@ -1520,110 +1526,12 @@ namespace M17N.Input
       return node.InnerText;
     }
 
-    private void new_variable (Xex.Symbol name, string desc, int val,
-                              MPlist pl, Xex.Variable vari)
-    {
-      int[] range;
-
-      if (pl.IsEmpty)
-       range = null;
-      else
-       {
-         int nrange = pl.Count;
-         range = new int[nrange * 2];
-         for (int i = 0; i < nrange; i++)
-           {
-             if (pl.IsPlist)
-               {
-                 MPlist p = pl.Plist;
-
-                 if (! p.IsInteger || ! p.next.IsInteger)
-                   throw new Exception ("Invalid range: " + p);
-                 range[i * 2] = p.Integer;
-                 range[i * 2 + 1] = p.next.Integer;
-               }
-             else if (pl.IsInteger)
-               range[i * 2] = range[i * 2 + 1] = pl.Integer;
-             else
-               throw new Exception ("Invalid range: " + pl);
-           }
-       }
-      if (vari == null)
-       domain.Defvar (new Xex.Variable.Int (domain, name, desc, val, range));
-      else
-       {
-         Xex.Term term = new Xex.Term (val);
-         vari.Value = term;
-         vari.DefaultValue = term;
-         vari.Range = range;
-       }
-    }
-
-    private void new_variable (Xex.Symbol name, string desc, MText val,
-                              MPlist pl, Xex.Variable vari)
-    {
-      string[] range;
-
-      if (pl.IsEmpty)
-       range = null;
-      else
-       {
-         range = new string[pl.Count * 2];
-         for (int i = 0; i < range.Length; i++)
-           {
-             if (pl.IsMText)
-               range[i] = (string) pl.Text;
-             else
-               throw new Exception ("Invalid range: " + pl);
-           }
-       }
-      if (vari == null)
-       domain.Defvar (new Xex.Variable.Str (domain, name, desc, (string) val, range));
-      else
-       {
-         Xex.Term term = new Xex.Term ((string) val);
-         vari.Value = term;
-         vari.DefaultValue = term;
-         vari.Range = range;
-       }
-    }
-
-    private void new_variable (Xex.Symbol name, string desc, MSymbol val,
-                              MPlist pl, Xex.Variable vari)
-    {
-      Xex.Symbol[] range;
-      Xex.Symbol sym = val.Name;
-
-      if (pl.IsEmpty)
-       range = null;
-      else
-       {
-         range = new Xex.Symbol[pl.Count * 2];
-         for (int i = 0; i < range.Length; i++)
-           {
-             if (pl.IsSymbol)
-               range[i] = pl.Symbol.Name;
-             else
-               throw new Exception ("Invalid range: " + pl);
-           }
-       }
-      if (vari == null)
-       domain.Defvar (new Xex.Variable.Sym (domain, name, desc, sym, range));
-      else
-       {
-         Xex.Term term = new Xex.Term (sym);
-         vari.Value = term;
-         vari.DefaultValue = term;
-         vari.Range = range;
-       }
-    }
-
     private Xex.Variable get_global_var (Xex.Symbol name)
     {
       if (im_global == null || this != im_global)
        {
-         tag = new MDatabase.Tag (Minput_method, MSymbol.t, MSymbol.nil,
-                                  "global");
+         MDatabase.Tag tag =
+           new MDatabase.Tag (Minput_method, MSymbol.t, MSymbol.nil, "global");
          im_global = im_table[tag];
          if (! im_global.Open ())
            throw new Exception ("Failed to load global"); 
@@ -1645,22 +1553,82 @@ namespace M17N.Input
          var_names[i] = name;
          p = p.next;
          string desc = (string) parse_description (p);
+         if (desc != null)
+           p = p.next;
          Xex.Variable vari = get_global_var (name);
          if (vari != null)
            domain.Defvar (vari);
-         if (desc != null)
-           p = p.next;
-         if (! p.IsEmpty)
+         if (p.IsInteger)
+           {
+             int n = p.Integer;
+             int[] range = null;
+
+             p = p.Next;
+             if (! p.IsEmpty)
+               {
+                 int nrange = p.Count;
+                 range = new int[nrange * 2];
+                 for (int j = 0; j < nrange; j++)
+                   {
+                     if (p.IsPlist)
+                       {
+                         MPlist p0 = p.Plist;
+
+                         if (! p0.IsInteger || ! p0.next.IsInteger)
+                           throw new Exception ("Invalid range: " + p0);
+                         range[j * 2] = p0.Integer;
+                         range[j * 2 + 1] = p0.next.Integer;
+                       }
+                     else if (p.IsInteger)
+                       range[j * 2] = range[j * 2 + 1] = p.Integer;
+                     else
+                       throw new Exception ("Invalid range: " + p);
+                   }
+               }
+             domain.DefvarInt (name, n, desc, range);
+           }
+         else if (p.IsMText)
            {
-             if (p.IsInteger)
-               new_variable (name, desc, p.Integer, p.next, vari);
-             else if (p.IsMText)
-               new_variable (name, desc, p.Text, p.next, vari);
-             else if (p.IsSymbol)
-               new_variable (name, desc, p.Symbol, p.next, vari);
+             string str = (string) p.Text;
+             string[] range = null;
+
+             p = p.next;
+             if (! p.IsEmpty)
+               {
+                 range = new string[p.Count];
+                 for (int j = 0; j < range.Length; j++)
+                   {
+                     if (p.IsMText)
+                       range[j] = (string) p.Text;
+                     else
+                       throw new Exception ("Invalid range: " + p);
+                   }
+               }
+             domain.DefvarStr (name, str, desc, range);
+           }
+         else if (p.IsSymbol)
+           {
+             Xex.Symbol sym = p.Symbol.Name;
+             Xex.Symbol[] range;
+
+             p = p.next;
+             if (p.IsEmpty)
+               range = null;
              else
-               throw new Exception ("Invalid variable type: " + p.val);
+               {
+                 range = new Xex.Symbol[p.Count];
+                 for (int j = 0; j < range.Length; j++)
+                   {
+                     if (p.IsSymbol)
+                       range[j] = p.Symbol.Name;
+                     else
+                       throw new Exception ("Invalid range: " + p);
+                   }
+               }
+             domain.DefvarSym (name, sym, desc, range);
            }
+         else if (! p.IsEmpty)
+           throw new Exception ("Invalid variable type: " + p.val);
        }
     }
 
@@ -1735,35 +1703,71 @@ namespace M17N.Input
        }
     }
 
+    private void parse_include (XmlNode node)
+    {
+      XmlNode n;
+      MSymbol language, name, subname;
+      MSymbol part, section;
+      node = node.FirstChild;
+      n = node.FirstChild;
+      language = n.InnerText;
+      n = n.NextSibling;
+      name = n.InnerText;
+      n = n.NextSibling;      
+      if (n != null)
+       subname = n.InnerText;
+      else
+       subname = MSymbol.nil;
+      node = node.NextSibling;
+      part = node.InnerText;
+      node = node.NextSibling;
+      if (node != null)
+       section = node.InnerText;
+      else
+       section = MSymbol.nil;
+      include_part (language, name, subname, part, section);
+    }
+
     private void parse_macros (XmlNode node)
     {
       for (XmlNode nn = node.FirstChild; nn != null; nn = nn.NextSibling)
        if (nn.NodeType == XmlNodeType.Element)
-         domain.Defun (nn, true);
+       {
+         if (nn.Name == Xex.Qdefun)
+           domain.Defun (nn, true);
+         else if (nn.Name == Qxi_include)
+           parse_include (nn);
+       }
       for (XmlNode nn = node.FirstChild; nn != null; nn = nn.NextSibling)
-       if (nn.NodeType == XmlNodeType.Element)
+       if (nn.NodeType == XmlNodeType.Element
+           && nn.Name == Xex.Qdefun)
          domain.Defun (nn, false);
     }
 
     private void parse_maps (XmlNode node)
     {
       for (node = node.FirstChild; node != null; node = node.NextSibling)
-       if (node.Name == Qmap)
-         {
-           MSymbol name = node.Attributes[0].Value;
-           Map map = new Map (name);
-           maps[name] = map;
-           for (XmlNode nd = node.FirstChild; nd != null; nd = nd.NextSibling)
-             if (nd.Name == Qrule)
-               {
-                 XmlNode n = nd.FirstChild;
-                 if (n.Name != Qkeyseq)
-                   continue;
-                 KeySeq keyseq = (KeySeq) KeySeq.parser (domain, n);
-                 Xex.Term[] actions = Xex.ParseTerms (domain, n.NextSibling);
-                 map.entries.Add (new Map.Entry (domain, keyseq, actions));
-               }
-         }
+       {
+         if (node.Name == Qmap)
+           {
+             MSymbol name = node.Attributes[0].Value;
+             Map map = new Map (name);
+             maps[name] = map;
+             for (XmlNode nd = node.FirstChild; nd != null;
+                  nd = nd.NextSibling)
+               if (nd.Name == Qrule)
+                 {
+                   XmlNode n = nd.FirstChild;
+                   if (n.Name != Qkeyseq)
+                     continue;
+                   KeySeq keyseq = (KeySeq) KeySeq.parser (domain, n);
+                   Xex.Term[] actions = Xex.ParseTerms (domain, n.NextSibling);
+                   map.entries.Add (new Map.Entry (domain, keyseq, actions));
+                 }
+           }
+         else if (node.Name == Qxi_include)
+           parse_include (node);
+       }
     }
 
     private void parse_states (MPlist plist)
@@ -1781,58 +1785,40 @@ namespace M17N.Input
     private void parse_states (XmlNode node)
     {
       for (node = node.FirstChild; node != null; node = node.NextSibling)
-       if (node.Name == Qstate)
-         {
-           State state = new State (this, node);
-           states[state.name] = state;
-           if (initial_state == null)
-             initial_state = state;
-         }
+       {
+         if (node.Name == Qstate)
+           {
+             State state = new State (this, node);
+             states[state.name] = state;
+             if (initial_state == null)
+               initial_state = state;
+           }
+         else if (node.Name == Qxi_include)
+           parse_include (node);
+       }
     }
 
-    private void parse_include (MPlist plist)
+    private void include_part (MSymbol language, MSymbol name, MSymbol subname,
+                              MSymbol part, MSymbol section)
     {
-      if (! plist.IsPlist)
-       return;
-      MPlist p = plist.Plist;
-      MSymbol language, name, subname;
-      language = p.Symbol;
-      p = p.next;
-      if (! p.IsSymbol)
-       name = subname = MSymbol.nil;
-      else
-       {
-         name = p.Symbol;
-         p = p.next;
-         if (! p.IsSymbol)
-           subname = MSymbol.nil;
-         else
-           subname = p.Symbol;
-       }
+      Console.WriteLine ("including {0}:{1}:{2}:{3}:{4}",
+                        language, name, subname, part, section);
 
       MInputMethod im = MInputMethod.Find (language, name, subname);
       if (im == null)
        return;
       if (! im.Open ())
        return;
-      plist = plist.next;
-      if (! plist.IsSymbol)
-       return;
-      MSymbol target_type = plist.Symbol;
-      plist = plist.next;
-      MSymbol target_name = MSymbol.nil;
-      if (plist.IsSymbol)
-       target_name = plist.Symbol;
-      if (target_type == Mmacro)
+      if (part == Mmacro)
        {
-         if (target_name == MSymbol.nil)
+         if (section == MSymbol.nil)
            im.domain.CopyFunc (domain);
          else
-           im.domain.CopyFunc (domain, (Xex.Symbol) target_name.Name);
+           im.domain.CopyFunc (domain, (Xex.Symbol) section.Name);
        }
-      else if (target_type == Mmap)
+      else if (part == Mmap)
        {
-         if (target_name == MSymbol.nil)
+         if (section == MSymbol.nil)
            {
              foreach (KeyValuePair<MSymbol, Map> kv in im.maps)
                maps[kv.Key] = kv.Value;
@@ -1840,20 +1826,20 @@ namespace M17N.Input
          else
            {
              Map map;
-             if (im.maps.TryGetValue (target_name, out map))
-               maps[target_name] = map;
+             if (im.maps.TryGetValue (section, out map))
+               maps[section] = map;
            }
        }
-      else if (target_type == Mstate)
+      else if (part == Mstate)
        {
-         if (target_name == MSymbol.nil)
+         if (section == MSymbol.nil)
            {
              foreach (KeyValuePair<Xex.Symbol, State> kv in im.states)
                states[kv.Key] = kv.Value;
            }
          else
            {
-             Xex.Symbol state_name = target_name.Name;
+             Xex.Symbol state_name = section.Name;
              State state;
              if (im.states.TryGetValue (state_name, out state))
                states[state_name] = state;
@@ -1861,6 +1847,36 @@ namespace M17N.Input
        }
     }
 
+    private void parse_include (MPlist plist)
+    {
+      if (! plist.IsPlist)
+       return;
+      MPlist p = plist.Plist;
+      MSymbol language, name, subname;
+      language = p.Symbol;
+      p = p.next;
+      if (! p.IsSymbol)
+       name = subname = MSymbol.nil;
+      else
+       {
+         name = p.Symbol;
+         p = p.next;
+         if (! p.IsSymbol)
+           subname = MSymbol.nil;
+         else
+           subname = p.Symbol;
+       }
+      plist = plist.next;
+      if (! plist.IsSymbol)
+       return;
+      MSymbol part = plist.Symbol;
+      plist = plist.next;
+      MSymbol section = MSymbol.nil;
+      if (plist.IsSymbol)
+       section = plist.Symbol;
+      include_part (language, name, subname, part, section);
+    }
+
     private Xex.Term parse_cond (MPlist plist)
     {
       Xex.Term[] args = new Xex.Term[plist.Count];
@@ -2040,7 +2056,6 @@ namespace M17N.Input
        if (pl.IsPlist)
          {
            MPlist p = pl.Plist;
-
            if (! p.IsSymbol)
              continue;
            domain.Defun ((Xex.Symbol) p.Symbol.Name, null, null, true);
index bcd05c9..23ffd80 100644 (file)
@@ -14,22 +14,16 @@ namespace System.Xml.Expression
     {
       private static NameTable nt = new NameTable ();
 
-      internal string name;
+      private string name;
 
-      public Symbol (string str)
-       {
-         name = nt.Add (str);
-       }
+      public Symbol (string str) { name = nt.Add (str); }
 
       public static implicit operator Symbol (string str)
       {
        return new Symbol (str);
       }
 
-      public static implicit operator string (Symbol name)
-      {
-       return name.name;
-      }
+      public static implicit operator string (Symbol sym) { return sym.name; }
 
       public static bool operator== (Symbol n1, Symbol n2)
        {
@@ -76,7 +70,7 @@ namespace System.Xml.Expression
        return name.GetHashCode ();
       }
 
-      public static NameTable Table { get { return nt; } }
+      public static NameTable NameTable { get { return nt; } }
 
       public override string ToString () { return name; }
     }
@@ -90,15 +84,15 @@ namespace System.Xml.Expression
     private static Symbol Qsymbol = "symbol";
     private static Symbol Qlist = "list";
 
-    private static Symbol Qdefun = "defun";
-    private static Symbol Qdefmacro = "defmacro";
+    public static Symbol Qdefun = "defun";
+    public static Symbol Qdefmacro = "defmacro";
     private static Symbol Qfname = "fname";
     private static Symbol Qargs = "args";
     private static Symbol Qfixed = "fixed";
     private static Symbol Qoptional = "optional";
     private static Symbol Qrest = "rest";
 
-    private static Symbol Qdefvar = "defvar";
+    public static Symbol Qdefvar = "defvar";
     private static Symbol Qvname = "vname";
     private static Symbol Qdescription = "description";
     private static Symbol Qrange = "range";
@@ -377,30 +371,26 @@ namespace System.Xml.Expression
     {
       public Domain domain;
       public readonly Symbol name;
-      public string desc;
-      protected Term default_val;
       protected Term val;
-      object range;
 
       public Variable (Domain domain, Symbol name, Term val)
       {
        this.domain = domain;
        this.name = name;
        this.val = val;
-       default_val = Zero;
       }
 
       public virtual bool ValueP (Term val) { return true; }
 
-      public Variable Clone (Domain domain)
+      public virtual Variable Clone (Domain domain)
       {
-       Variable v = new Variable (domain, name, val);
-       v.desc = desc;
-       v.default_val = default_val;
-       v.range = range;
-       return v;
+       return new Variable (domain, name, val);
       }
 
+      public virtual void Reset () { val = Zero; }
+
+      public virtual string Description { get { return null; } }
+
       public Term Value
       {
        get { return val; }
@@ -424,193 +414,174 @@ namespace System.Xml.Expression
        return val;
       }
 
-      public Term DefaultValue
-      {
-       get { return default_val; }
-       set {
-         if (! ValueP (value))
-           throw new Exception ("Invalid value: " + value);
-         default_val = value;
-       }
-      }
+      public override string ToString () { return name + "(" + val + ")"; }
 
-      public virtual object Range
+      public abstract class Typed : Variable
       {
-       get { return range; }
-       set { range = value; }
-      }
+       protected string desc;
+       private Term default_val;
 
-      public override string ToString () { return name + "(" + val + ")"; }
+       protected Typed (Domain domain, Symbol name, Term val, string desc)
+         : base (domain, name, val)
+         {
+           this.desc = desc;
+           default_val = val;
+         }
+
+       public override void Reset () { val = default_val; }
+
+       public override string Description { get { return desc; } }
+      }
 
-      public class Int : Variable
+      public class Int : Typed
       {
-       public int[] range;
+       private int[] range;
 
-       private static bool SubsetP (int[] r1, int[] r2)
+       public bool IsSubrange (int[] r)
          {
-           if (r2 == null)
+           if (range == null)
              return true;
-           for (int i = 0; i < r1.Length; i += 2)
+           for (int i = 0; i < r.Length; i += 2)
              {
                int j;
-               for (j = 0; j < r2.Length; j += 2)
-                 if (r2[j] <= r1[i] && r2[j + 1] >= r1[i + 1])
+               for (j = 0; j < range.Length; j += 2)
+                 if (range[j] <= r[i] && range[j + 1] >= r[i + 1])
                    break;
-               if (j >= r2.Length)
+               if (j >= range.Length)
                  return false;
              }
            return true;
          }
 
-       private static bool SubsetP (int val, int[] r)
+       public Int (Domain domain, Symbol name, int n, string desc, int[] range)
+         : base (domain, name, new Term (n), desc)
          {
-           if (r == null)
-             return true;
-           for (int i = 0; i < r.Length; i += 2)
-             if (r[i] <= val && r[i + 1] >= val)
-               return true;
-           return false;
-         }
-
-       public Int (Domain domain, Symbol name, string description,
-                   int value, int[] range)
-         : base (domain, name, new Term (value))
-         {
-           if (! SubsetP (value, range))
-             throw new Exception ("Invalid value: " + value);
-           desc = description;
-           default_val = val;
+           if (range != null && range.Length % 2 == 1)
+             throw new Exception ("Invalid range length: " + range.Length);
            this.range = range;
+           if (! ValueP (val))
+             throw new Exception ("Invalid integer value: " + val);
          }
 
        public override bool ValueP (Term term)
        {
          if (! term.IsInt)
            return false;
-         return SubsetP (term.Intval, range);
+         if (range == null)
+           return true;
+         int n = term.Intval;
+         for (int i = 0; i < range.Length; i += 2)
+           if (range[i] <= n && range[i + 1] >= n)
+             return true;
+         return false;
        }
 
-       public override object Range {
-         get { return range; }
-         set {
-           int[] r = (int[]) value;
-           if (! SubsetP (r, range)
-               || ! SubsetP (val.Intval, r)
-               || ! SubsetP (default_val.Intval, r))
-             throw new Exception ("Invalid range");
-           range = r;
-         }
+       public override Variable Clone (Domain domain)
+       {
+         return new Int (domain, name, val.Intval, desc, range);
        }
+
+       public int[] Range { get { return range; } set { range = value; } }
       }
 
-      public class Str : Variable
+      public class Str : Typed
       {
-       public string[] range;
+       private string[] range;
 
-       private static bool SubsetP (string[] r1, string[] r2)
+       public bool IsSubrange (string[] r)
          {
-           if (r2 == null)
+           if (range == null)
              return true;
-           foreach (string s in r1)
-             if (! SubsetP (s, r2))
-               return false;
+           for (int i = 0; i < r.Length; i++)
+             {
+               int j;
+               for (j = 0; j < range.Length; j++)
+                 if (range[j] == r[i])
+                   break;
+               if (j >= range.Length)
+                 return false;
+             }
            return true;
          }
 
-       private static bool SubsetP (string str, string[] r)
-         {
-           if (r == null)
-             return true;
-           foreach (string s in r)
-             if (str == s)
-               return true;
-           return false;
-       }
-
-       public Str (Domain domain, Symbol name, string description,
-                   string value, string[] range)
-         : base (domain, name, new Term (value))
+       public Str (Domain domain, Symbol name, string str, string desc,
+                   string[] range)
+         : base (domain, name, new Term (str), desc)
          {
-           if (! SubsetP (value, range))
-             throw new Exception ("Invalid value: " + value);
-           desc = description;
-           default_val = val;
            this.range = range;
+           if (! ValueP (val))
+             throw new Exception ("Invalid string value: " + val);
          }
 
        public override bool ValueP (Term term)
        {
-         if (! (term.objval is string))
+         if (! term.IsStr)
            return false;
-         return SubsetP (term.Strval, range);
+         if (range == null)
+           return true;
+         string str = term.Strval;
+         foreach (string s in range)
+           if (str == s)
+             return true;
+         return false;
        }
 
-       public override object Range {
-         get { return range; }
-         set {
-           string[] r = (string[]) value;
-           if (! SubsetP (r, range)
-               || ! SubsetP (val.Strval, r)
-               || ! SubsetP (default_val.Strval, r))
-             throw new Exception ("Invalid range");
-           range = r;
-         }
+       public override Variable Clone (Domain domain)
+       {
+         return new Str (domain, name, val.Strval, desc, range);
        }
+
+       public string[] Range { get { return range; } set { range = value; } }
       }
 
-      public class Sym : Variable
+      public class Sym : Typed
       {
        public Symbol[] range;
 
-       private static bool SubsetP (Symbol[] r1, Symbol[] r2)
+       public bool IsSubrange (Symbol[] r)
          {
-           if (r2 == null)
+           if (range == null)
              return true;
-           foreach (Symbol n in r1)
-             if (! SubsetP (n, r2))
-               return false;
+           for (int i = 0; i < r.Length; i++)
+             {
+               int j;
+               for (j = 0; j < range.Length; j++)
+                 if (range[j] == r[i])
+                   break;
+               if (j >= range.Length)
+                 return false;
+             }
            return true;
          }
 
-       private static bool SubsetP (Symbol name, Symbol[] r)
-         {
-           if (r == null)
-             return true;
-           foreach (Symbol n in r)
-             if (name == n)
-               return true;
-           return false;
-       }
-
-       public Sym (Domain domain, Symbol name, string description,
-                   Symbol value, Symbol[] range)
-         : base (domain, name, new Term (value))
+       public Sym (Domain domain, Symbol name, Symbol sym, string desc,
+                   Symbol[] range)
+         : base (domain, name, new Term (sym), desc)
          {
-           if (! SubsetP (value, range))
-             throw new Exception ("Invalid value: " + value);
-           desc = description;
-           default_val = val;
            this.range = range;
+           if (! ValueP (val))
+             throw new Exception ("Invalid symbol value: " + val);
          }
 
        public override bool ValueP (Term term)
        {
-         if (! (term.objval is Symbol))
+         if (! term.IsSymbol)
            return false;
-         return SubsetP (term.Symval, range);
+         if (range == null)
+           return true;
+         Symbol name = term.Symval;
+         foreach (Symbol n in range)
+           if (name == n)
+             return true;
+         return false;
        }
 
-       public override object Range {
-         get { return range; }
-         set {
-           Symbol[] r = (Symbol[]) value;
-           if (! SubsetP (r, range)
-               || ! SubsetP (val.Symval, r)
-               || ! SubsetP (default_val.Symval, r))
-             throw new Exception ("Invalid range");
-           range = r;
-         }
+       public override Variable Clone (Domain domain)
+       {
+         return new Sym (domain, name, val.Symval, desc, range);
        }
+
+       public Symbol[] Range { get { return range; } set { range = value; } }
       }
     }
 
@@ -669,7 +640,7 @@ namespace System.Xml.Expression
     {
       private object val;
 
-      public CatchTag (Symbol name) { val = name.name; }
+      public CatchTag (Symbol sym) { val = (string) sym; }
       private CatchTag (int i) { val = i; }
 
       public static CatchTag Return = new CatchTag (0);
@@ -894,43 +865,30 @@ namespace System.Xml.Expression
 
            if (type == Qinteger)
              {
-               int intval = parse_integer (val);
+               int n = parse_integer (val);
                int[] range = null;
                if (range_list != null)
                  {
                    range = new int[nranges * 2];
                    for (int i = 0; i < nranges; i++)
                      {
-                       XmlNode n = range_list[i];
-                       if (n.Name == Qrange)
+                       XmlNode nd = range_list[i];
+                       if (nd.Name == Qrange)
                          {
                            range[i * 2]
-                             = parse_integer (n.FirstChild.InnerText);
+                             = parse_integer (nd.FirstChild.InnerText);
                            range[i * 2 + 1]
-                             = parse_integer (n.LastChild.InnerText);
+                             = parse_integer (nd.LastChild.InnerText);
                          }
                        else
                          {
                            range[i * 2]
                              = range[i * 2 + 1]
-                             = parse_integer (n.FirstChild.InnerText);
+                             = parse_integer (nd.FirstChild.InnerText);
                          }
                      }
                  }
-
-               if (variables.TryGetValue (name, out vari))
-                 {
-                   if (! (vari is Variable.Int))
-                     throw new Exception ("Inalid value");
-                   vari = (Variable) vari.Clone (this);
-                   Term v = new Term (intval);
-                   vari.Value = v;
-                   vari.DefaultValue = v;
-                   if (range != null)
-                     vari.Range = range;
-                 }
-               else
-                 vari = new Variable.Int (this, name, desc, intval, range);
+               vari = DefvarInt (name, n, desc, range);
              }
            else if (type == Qstring)
              {
@@ -941,20 +899,7 @@ namespace System.Xml.Expression
                    for (int i = 0; i < nranges; i++)
                      range[i] = range_list[i].FirstChild.InnerText;
                  }
-
-               if (variables.TryGetValue (name, out vari))
-                 {
-                   if (! (vari is Variable.Str))
-                     throw new Exception ("Invalid value");
-                   vari = (Variable) vari.Clone (this);
-                   Term v = new Term (val);
-                   vari.Value = v;
-                   vari.DefaultValue = v;
-                   if (range != null)
-                     vari.Range = range;
-                 }
-               else
-                 vari = new Variable.Str (this, name, desc, val, range);
+               vari = DefvarStr (name, val, desc, range);
              }
            else if (type == Qsymbol)
              {
@@ -965,20 +910,7 @@ namespace System.Xml.Expression
                    for (int i = 0; i < nranges; i++)
                      range[i] = range_list[i].FirstChild.InnerText;
                  }
-
-               if (variables.TryGetValue (name, out vari))
-                 {
-                   if (! (vari is Variable.Sym))
-                     throw new Exception ("Invalid value");
-                   vari = (Variable) vari.Clone (this);
-                   Term v = new Term (val);
-                   vari.Value = v;
-                   vari.DefaultValue = v;
-                   if (range != null)
-                     vari.Range = range;
-                 }
-               else
-                 vari = new Variable.Sym (this, name, desc, val, range);
+               vari = DefvarSym (name, (Symbol) val, desc, range);
              }
            else
              throw new Exception ("Unknown type: " + type);
@@ -986,11 +918,12 @@ namespace System.Xml.Expression
        else
          {
            if (variables.TryGetValue (name, out vari))
-             vari = (Variable) vari.Clone (this);
+             vari = vari.Clone (this);
            else
              vari = new Variable (this, name, Zero);
+           variables[name] = vari;
          }
-       variables[name] = vari;
+       Console.WriteLine (vari);
        return vari;
       }
 
@@ -1008,6 +941,71 @@ namespace System.Xml.Expression
        return vari;
       }
 
+      public Variable DefvarInt (Symbol name, int n, string desc, int[] range)
+      {
+       Variable vari;
+
+       if (variables.TryGetValue (name, out vari))
+         {
+           Variable.Int intvari = vari as Variable.Int;
+           if (intvari == null)
+             throw new Exception ("Variable type mismatch");
+           if (range == null)
+             range = intvari.Range;
+           else if (! intvari.IsSubrange (range))
+             throw new Exception ("Variable range mismatch");
+           if (desc == null)
+             desc = vari.Description;
+         }
+       vari = new Variable.Int (this, name, n, desc, range);
+       variables[name] = vari;
+       return vari;
+      }
+
+      public Variable DefvarStr (Symbol name, string str, string desc,
+                                string[] range)
+      {
+       Variable vari;
+
+       if (variables.TryGetValue (name, out vari))
+         {
+           Variable.Str strvari = vari as Variable.Str;
+           if (strvari == null)
+             throw new Exception ("Variable type mismatch");
+           if (range == null)
+             range = strvari.Range;
+           else if (! strvari.IsSubrange (range))
+             throw new Exception ("Variable range mismatch");
+           if (desc == null)
+             desc = vari.Description;
+         }
+       vari = new Variable.Str (this, name, str, desc, range);
+       variables[name] = vari;
+       return vari;
+      }
+
+      public Variable DefvarSym (Symbol name, Symbol sym, string desc,
+                                Symbol[] range)
+      {
+       Variable vari;
+
+       if (variables.TryGetValue (name, out vari))
+         {
+           Variable.Sym symvari = vari as Variable.Sym;
+           if (symvari == null)
+             throw new Exception ("Variable type mismatch");
+           if (range == null)
+             range = symvari.Range;
+           else if (! symvari.IsSubrange (range))
+             throw new Exception ("Variable range mismatch");
+           if (desc == null)
+             desc = vari.Description;
+         }
+       vari = new Variable.Sym (this, name, sym, desc, range);
+       variables[name] = vari;
+       return vari;
+      }
+
       internal Function GetFunc (Symbol name)
       {
        Function func;
@@ -2056,10 +2054,10 @@ namespace System.Xml.Expression
 
     public Xexpression (Domain domain, string url)
     {
-      XmlDocument doc = new XmlDocument (Symbol.Table);
+      XmlDocument doc = new XmlDocument (Symbol.NameTable);
       XmlNode node;
 
-      using (XmlTextReader reader = new XmlTextReader (url, Symbol.Table))
+      using (XmlTextReader reader = new XmlTextReader (url, doc.NameTable))
        {
          do {
            reader.Read ();
index 735febc..e888cca 100644 (file)
--- a/input.cs
+++ b/input.cs
@@ -15,8 +15,7 @@ public class Test
     //M17n.debug = true;
     Xex.debug_level = 10;
     MDatabase.ApplicationDir = "/usr/local/share/m17n-xml";
-    MInputMethod im = MInputMethod.Find ("vi", "telex");
-    Console.WriteLine (im);
+    MInputMethod im = MInputMethod.Find ("zh", "py-b5");
     MInputMethod.Context ic = new MInputMethod.Context (im);
     MText str = args[0];
     for (int i = 0; i < str.Length; i++)