*** empty log message ***
authorhanda <handa>
Wed, 24 Feb 2010 12:53:11 +0000 (12:53 +0000)
committerhanda <handa>
Wed, 24 Feb 2010 12:53:11 +0000 (12:53 +0000)
xex.html
xex.js

index 20a7605..44ba89f 100644 (file)
--- a/xex.html
+++ b/xex.html
@@ -23,5 +23,5 @@
 <tr><th>down</th><td id="keydown">0</td><td id="status0"><td id="keymap0"></td><td id="preedit0"></td></tr>
 <tr><th>press</th><td id="keypress">0</td><td id="status1"><td id="keymap1"></td><td id="preedit1"></td></tr>
 </table>
-<textarea style="font-size: small; width:100%" rows="10"id="log"></textarea>
+<textarea style="font-size: small; width: 100%" rows="10"id="log"></textarea>
 </body>
diff --git a/xex.js b/xex.js
index 157f521..acae657 100644 (file)
--- a/xex.js
+++ b/xex.js
@@ -16,7 +16,8 @@ Xex.Error = {
 
   UnknownFunction: "unknown-function",
   MacroExpansionError: "macro-expansion-error",
-  NoVariableName: "no-variable-anme",
+  NoVariableName: "no-variable-name",
+  NoFunctionName: "no-funcion-name",
 
   // Run time errors.
   ArithmeticError: "arithmetic-error",
@@ -27,15 +28,18 @@ Xex.Error = {
   UncaughtThrow: "uncaught-throw"
 };
 
-Xex.Variable = function (domain, name, val)
+Xex.Variable = function (domain, name, desc, val, range)
 {
   this.domain = domain;
   this.name = name;
+  this.desc = desc;
   this.val = val;
+  this.range = range;
 }
 
 Xex.Variable.prototype.clone = function () {
-  return new Xex.Variable (this.domain, this.name, this.value);
+  return new Xex.Variable (this.domain, this.name, this.desc,
+                          this.val, this.range);
 }
     
 Xex.Variable.prototype.Equals = function (obj) {
@@ -343,26 +347,10 @@ Xex.Domain.prototype = {
       throw new Xex.ErrTerm (Xex.Error.UnknownFunction, fname);
     this.functions[alias] = func;
   },
-  Defvar: function (name)
+  Defvar: function (name, desc, val, range)
   {
-    if (name instanceof Xex.Variable)
-      {
-       name = name.Clone (this);
-       this.variables[name.name] = name;
-       return name;
-      }
-    var vari = this.variables[name];
-    if (vari)
-      {
-       if (vari.Typed)
-         throw new Xex.ErrTerm (Xex.Error.VariableTypeConflict,
-                              "Not a non-typed variable: " + name);
-      }
-    else
-      {
-       vari = new Xex.Variable (this, name, Xex.Zero);
-       this.variables[name] = vari;
-      }
+    var vari = new Xex.Variable (name, desc, val, range);
+    this.variables[name] = vari;
     return vari;
   },
   GetFunc: function (name)
@@ -388,7 +376,8 @@ Xex.Domain.prototype = {
   {
     var vari = this.variables[name];
     if (! vari)
-      vari = this.variables[name] = new Xex.Variable (this, name, Xex.Zero);
+      vari = this.variables[name] = new Xex.Variable (this, name, null,
+                                                     Xex.Zero, null);
     return vari;
   },
   GetVar: function (name) { return this.variables[name]; },
@@ -430,51 +419,177 @@ Xex.Term.prototype = {
   }
 };
 
-Xex.ParseTerm = function (domain, node)
+Node.prototype.firstElement = function ()
 {
-  var name = node.nodeName;
-  var parser = domain.termtypes[name];
-
-  if (parser)
-    return parser (domain, node);
-  if (name == 'defun' || name == 'defmacro')
-    {
-      name = parse_defun_head (domain, node);
-      parse_defun_body (domain, node);
-      return new Xex.StrTerm (name);
-    }
-  if (name == 'defvar')
-    {
-      name = parse_defvar (doamin, node);
-      return new Xex.StrTerm (nanme);
-    }
-
-  return new Xex.Funcall.prototype.Parser (domain, node);
+  for (var n = this.firstChild; n; n = n.nextSibling)
+    if (n.nodeType == 1)
+      return n;
+  return null;
 }
 
-Xex.ParseTermList = function (domain, node)
+Node.prototype.nextElement = function ()
 {
-  for (var n = node; n; n = n.nextSibling)
+  for (var n = this.nextSibling; n; n = n.nextSibling)
     if (n.nodeType == 1)
+      return n;
+  return null;
+};
+
+(function () {
+  function parse_defvar (domain, node)
+  {
+    var name = node.attributes['vname'].nodeValue;
+    if (! name)
+      throw new Xex.ErrTerm (Xex.Error.NoVariableName, node, '');
+    var vari = domain.variables['name'];
+    var desc, val, range;
+    if (vari)
+      {
+       desc = vari.description;
+       val = vari.val;
+       range = vari.range;
+      }
+    node = node.firstElement ();
+    if (node && node.nodeName == 'description')
+      {
+       desc = node.firstChild.nodeValue;
+       node = node.nextElement ();
+      }
+    if (node)
+      {
+       val = Xex.Term.Parse (domain, node);
+       node = node.nextElement ();
+       if (node && node.nodeName == 'possible-values')
+         for (node = node.firstElement (); node; node = node.nextElement ())
+           {
+             var pval;
+             if (node.nodeName == 'range')
+               {
+                 if (! val.IsInt)
+                   throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
+                                          'Range not allowed for ' + name);
+                 pval = new Array ();
+                 for (var n = node.firstElement (); n; n = n.nextElement ())
+                   {
+                     var v = Xex.Term.Parse (domain, n);
+                     if (! v.IsInt)
+                       throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
+                                              'Invalid range value: ' + val);
+                     pval.push (v);
+                   }
+                 }
+             else
+               {
+                 pval = Xex.Term.Parse (domain, node);
+                 if (val.type != pval.type)
+                   throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
+                                          'Invalid possible value: ' + pval);
+               }
+             if (! range)
+               range = new Array ();
+             range.push (pval);
+         }
+      }
+    if (! val)
+      val = Xex.Zero;
+    domain.Defvar (name, desc, val, range);
+    return name;
+  }
+
+  function parse_defun_head (domain, node)
+  {
+    var name = node.attributes['fname'].nodeValue;
+    if (! name)
+      throw new Xex.ErrTerm (Xex.Error.NoFunctionName, node, '');
+    var args = new Array ();
+    var nfixed = 0, noptional = 0, nrest = 0;
+
+    node = ndoe.firstElement ();
+    if (node && node.nodeName == 'args')
+      {
+       var n;
+       for (n = n.firstElement (); n; n = n.nextElement ())
+         {
+           if (n.nodeName == 'fixed')
+             nfixed++;
+           else if (n.nodeName == 'optional')
+             noptional++;
+           else if (n.nodeName == 'rest')
+             nrest++;
+           else
+             throw new Xex.ErrTerm (Xex.Error.WrongType, n, n.nodeName);
+         }
+       if (nrest > 1)
+         throw new Xex.ErrTerm (Xex.Error.WrongType, n, 'Too many <rest>');
+       for (n = node.firstElement (); n; n = n.nextElement ())
+         args.push (domain.DefVar (n.attributes['vname'].nodeValue));
+      }
+    args.min_args = nfixed;
+    args.max_args = nrest == 0 ? nfixed + noptional : -1;
+
+    if (node.nodeName == 'defun')
+      domain.Defun (name, args, null);
+    else
+      domain.Defmacor (name, args, null);
+    return name;
+  }
+
+  function parse_defun_body (domain, node)
+  {
+    var name = node.attributes['fname'].nodeValue;
+    var func = domain.GetFunc (name);
+    var body;
+    for (node = node.firstElement (); node; node = node.nextElement ())
+      if (node.nodeName != 'description' && node.nodeName != 'args')
+       break;
+    body = Xex.Term.Parse (domain, node, null);
+    func.SetBody (body);
+  }
+
+  Xex.Term.Parse = function (domain, node, stop)
+  {
+    if (arguments.length == 2)
+      {
+       var name = node.nodeName;
+       var parser = domain.termtypes[name];
+
+       if (parser)
+         return parser (domain, node);
+       if (name == 'defun' || name == 'defmacro')
+         {
+           name = parse_defun_head (domain, node);
+           parse_defun_body (domain, node);
+           return new Xex.StrTerm (name);
+         }
+       if (name == 'defvar')
+       {
+         name = parse_defvar (domain, node);
+         return new Xex.StrTerm (name);
+       }
+       return new Xex.Funcall.prototype.Parser (domain, node);
+      }
+    for (var n = node; n && n != stop; n = n.nextElement ())
       {
        if (n.nodeName == 'defun' || n.nodeName == 'defmacro')
          Xex.parse_defun_head (domain, n);
       }
-  var terms = false;
-  for (var n = node; n; n = n.nextSibling)
-    if (n.nodeType == 1)
+    var terms = null;
+    for (var n = node; n && n != stop; n = n.nextElement ())
       {
-       if (! terms)
-         terms = new Array ();
        if (n.nodeName == 'defun' || n.nodeName == 'defmacro')
          Xex.parse_defun_body (domain, n);
        else if (n.nodeName == 'defvar')
-         Xex.parse_defvar (domain, n);
+         parse_defvar (domain, n);
        else
-         terms.push (Xex.ParseTerm (domain, n));
+         {
+           if (! terms)
+             terms = new Array ();
+           terms.push (Xex.Term.Parse (domain, n));
+         }
       }
-  return terms;
-}
+    return terms;
+  }
+}) ();
 
 Xex.Varref = function (vname)
 {
@@ -523,7 +638,7 @@ Xex.Funcall = function (func, vari, args)
     var vari;
     attr = node.attributes['vname'];
     vari = attr != undefined ? domain.GetVarCreate (attr.nodeValue) : false;
-    var args = Xex.ParseTermList (domain, node.firstChild);
+    var args = Xex.Term.Parse (domain, node.firstElement (), null);
     return new Xex.Funcall (func, vari, args);
   }
 
@@ -680,7 +795,7 @@ Xex.LstTerm = function (list) { this.val = list; };
 
   proto.Parser = function (domain, node)
   {
-    var list = Xex.ParseTermList (domain, node.firstChild);
+    var list = Xex.Term.Parse (domain, node.firstElement (), null);
     return new Xex.LstTerm (list);
   }
 
@@ -890,8 +1005,10 @@ var MIM = {
   enabled: true,
   // Boolean flag to tell if MIM is running in debug mode or not.
   debug: false,
-  // List of registered input methods.
-  im_list: {},
+  // List of main input methods.
+  imlist: {},
+  // List of extra input methods;
+  imextra: {},
   // Global input method data
   im_global: null,
   // Currently selected input method.
@@ -1044,7 +1161,7 @@ var MIM = {
     for (node = node.firstChild; node; node = node.nextSibling)
       if (node.nodeType == 1)
        {
-         var term = Xex.ParseTerm (domain, node);
+         var term = Xex.Term.Parse (domain, node);
          return new MIM.KeySeq (term);
        }
     throw new Xex.ErrTerm (MIM.Error.ParseError, "Invalid keyseq");
@@ -1176,6 +1293,7 @@ MIM.Selector = function (name)
   this.val = name;
 }
 MIM.Selector.prototype = new Xex.Term ('selector');
+
 (function () {
   var selectors = {};
   selectors["@<"] = selectors["@first"] = new MIM.Selector ('@<');
@@ -1211,10 +1329,10 @@ MIM.Rule.prototype.Parser = function (domain, node)
   for (n = node.firstChild; n && n.nodeType != 1; n = n.nextSibling);
   if (! n)
     throw new Xex.ErrTerm (MIM.Error.ParseError, "invalid rule:" + node);
-  var keyseq = Xex.ParseTerm (domain, n);
+  var keyseq = Xex.Term.Parse (domain, n);
   if (keyseq.type != 'keyseq')
     throw new Xex.ErrTerm (MIM.Error.ParseError, "invalid rule:" + node);
-  var actions = Xex.ParseTermList (domain, n.nextSibling);
+  var actions = Xex.Term.Parse (domain, n.nextElement (), null);
   return new MIM.Rule (keyseq, actions);
 }
 MIM.Rule.prototype.toString = function ()
@@ -1227,6 +1345,7 @@ MIM.Map = function (name)
   this.name = name;
   this.rules = new Array ();
 };
+
 (function () {
   var proto = new Xex.Term ('map');
 
@@ -1238,7 +1357,7 @@ MIM.Map = function (name)
     var map = new MIM.Map (name);
     for (var n = node.firstChild; n; n = n.nextSibling)
       if (n.nodeType == 1)
-       map.rules.push (Xex.ParseTerm (domain, n));
+       map.rules.push (Xex.Term.Parse (domain, n));
     return map;
   }
 
@@ -1282,6 +1401,7 @@ MIM.Keymap = function ()
   this.submaps = null;
   this.actions = null;
 };
+
 (function () {
   var proto = {};
 
@@ -1338,6 +1458,7 @@ MIM.State = function (name)
   this.name = name;
   this.keymap = new MIM.Keymap ();
 };
+
 (function () {
   var proto = new Xex.Term ('state');
 
@@ -1348,21 +1469,23 @@ MIM.State = function (name)
     if (! name)
       throw new Xex.ErrTerm (MIM.Error.ParseError, "invalid map");
     var state = new MIM.State (name);
-    for (node = node.firstChild; node; node = node.nextSibling)
+    for (node = node.firstElement (); node; node = node.nextElement ())
       {
-       if (node.nodeType != 1)
-         continue;
-       if (node.nodeName == 'branch')
+       if (node.nodeName == 'title')
+         state.title = node.firstChild.nodeValue;
+       else
          {
-           state.keymap.Add (map_list[node.attributes['mname'].nodeValue]);
-           state.keymap.actions = Xex.ParseTermList (domain, node.firstChild);
+           var n = node.firstElement ();
+           if (node.nodeName == 'branch')
+           {
+             state.keymap.Add (map_list[node.attributes['mname'].nodeValue]);
+             state.keymap.actions = Xex.Term.Parse (domain, n, null);
+           }
+           else if (node.nodeName == 'state-hook')
+             state.enter_actions = Xex.Term.Parse (domain, n, null);
+           else if (node.nodeName == 'catch-all-branch')
+             state.fallback_actions = Xex.Term.Parse (domain, n, null);
          }
-       else if (node.nodeName == 'state-hook')
-         state.enter_actions = Xex.ParseTermList (domain, node.firstChild);
-       else if (node.nodeName == 'catch-all-branch')
-         state.fallback_actions = Xex.ParseTermList (domain, node.firstChild);
-       else if (node.nodeName == 'title')
-         state.title = node.firstChild.nodeValue;
       }
     return state;
   }
@@ -1405,25 +1528,52 @@ MIM.im_domain.DefType (MIM.State.prototype);
   }
 
   im_domain.DefSubr (Finsert, "insert", false, 1, 1);
+  im_domain.DefSubr (Finsert_candidates, "insert-candidates", false, 1, 1);
 }) ();
 
 (function () {
+  function get_global_var (vname)
+  {
+    if (MIM.im_global.load_status == MIM.LoadStatus.NotLoaded)
+      MIM.im_global.Load ()
+    return MIM.im_global.domain.variables[vname];
+  }
+
   var parsers = { };
+
   parsers['description'] = function (node)
   {
     this.description = node.firstChild.nodeValue;
   }
-  parses['variable-list'] = function (node)
+  parsers['variable-list'] = function (node)
   {
-    for (node = node.firstChild; node; node = node.nextSibling)
+    for (node = node.firstElement (); node; node = node.nextElement ())
       {
-       if (node.nodeType != 1)
-         continue;
-       var name = node.attributes['vname'].nodeValue;
-       var vari = get_global_bar (name);
-       if (vari != null)
-         domain.Defvar (name);
-       Xex.Parse (domain, node);
+       var vname = node.attributes['vname'].nodeValue;
+       if (this != MIM.im_global)
+         {
+           var vari = get_global_var (vname);
+           if (vari != null)
+             this.domain.Defvar (vname);
+         }
+       Xex.Term.Parse (this.domain, node);
+      }
+  }
+  parsers['command-list'] = function (node)
+  {
+  }
+  parsers['macro-list'] = function (node)
+  {
+    for (node = node.firstElement (); node; node = node.nextElement ())
+      {
+       if (node.nodeName == 'xi:include')
+         {
+           var im = include (node);
+           if (! im)
+             continue;
+           for (var macro in im.domain.functions)
+             im.domain.CopyFunc (this.domain, macro);
+         }
       }
   }
   parsers['title'] = function (node)
@@ -1436,7 +1586,7 @@ MIM.im_domain.DefType (MIM.State.prototype);
       {
        if (node.nodeType != 1 || node.nodeName != 'map')
          continue;
-       var map = Xex.ParseTerm (this.domain, node);
+       var map = Xex.Term.Parse (this.domain, node);
        this.map_list[map.name] = map;
       }
   }
@@ -1447,7 +1597,7 @@ MIM.im_domain.DefType (MIM.State.prototype);
       {
        if (node.nodeType != 1 || node.nodeName != 'state')
          continue;
-       var state = Xex.ParseTerm (this.domain, node);
+       var state = Xex.Term.Parse (this.domain, node);
        if (! state.title)
          state.title = this.title;
        if (! this.initial_state)
@@ -1464,7 +1614,9 @@ MIM.im_domain.DefType (MIM.State.prototype);
     this.extra_id = extra_id;
     this.file = file;
     this.load_status = MIM.LoadStatus.NotLoaded;
-    this.domain = new Xex.Domain (this.lang + '-' + this.name,
+    this.domain = new Xex.Domain (this.lang + '-'
+                                 + (this.name != 'nil'
+                                    ? this.name : this.extra_id),
                                  MIM.im_domain, null);
   }
 
@@ -1480,10 +1632,8 @@ MIM.im_domain.DefType (MIM.State.prototype);
       this.map_list = {};
       this.initial_state = null;
       this.state_list = {};
-      for (node = node.firstChild; node; node = node.nextSibling)
+      for (node = node.firstElement (); node; node = node.nextElement ())
         {
-         if (node.nodeType != 1)
-           continue;
          var name = node.nodeName;
          var parser = parsers[name];
          if (parser)
@@ -1650,7 +1800,7 @@ MIM.im_domain.DefType (MIM.State.prototype);
     return b.get (this.index - b.Index);
   }
 
-  Candidates.prototype.PrevGroup ()
+  Candidates.prototype.PrevGroup = function ()
   {
     var col = this.Column ();
     var nitems;
@@ -1766,12 +1916,13 @@ MIM.im_domain.DefType (MIM.State.prototype);
            this.index += this.column - this.Column () + 1;
            while (b.Index + b.Count () <= this.index)
              b = this.blocks[++this.row];
+         }
       }
     else
       this.index = b.Index + b.Count () - 1;
   }
 
-  Candidates.prototype.Select = funciton (selector)
+  Candidates.prototype.Select = function (selector)
   {
     if (selector instanceof MIM.Selector)
       {
@@ -2189,7 +2340,7 @@ MIM.im_domain.DefType (MIM.State.prototype);
   for (node = node.firstChild; node; node = node.nextSibling)
     if (node.nodeName == 'input-method')
       {
-       var lang, name, extra_id, file;
+       var lang = null, name = null, extra_id = null, file = null;
 
        for (var n = node.firstChild; n; n = n.nextSibling)
          {
@@ -2202,10 +2353,26 @@ MIM.im_domain.DefType (MIM.State.prototype);
            else if (n.nodeName == 'filename')
              file = n.firstChild.nodeValue;
          }
-       if (! MIM.im_list[lang])
-         MIM.im_list[lang] = {};
-       MIM.im_list[lang][name] = new MIM.IM (lang, name, extra_id, file);
+       if (name && name != 'nil')
+         {
+           if (! MIM.imlist[lang])
+             MIM.imlist[lang] = {};
+           MIM.imlist[lang][name] = new MIM.IM (lang, name, extra_id, file);
+         }
+       else if (extra_id && extra_id != 'nil')
+         {
+           if (! MIM.imextra[lang])
+             MIM.imextra[lang] = {};
+           MIM.imextra[lang][extra_id] = new MIM.IM (lang, name, extra_id, file);
+         }
       }
+  if (MIM.imextra.t && MIM.imextra.t.global)
+    MIM.im_global = MIM.imextra.t.global;
+  else
+    {
+      MIM.im_global = new MIM.IM ('t', 'nil', 'global', null);
+      MIM.im_global.load_status = MIM.LoadStatus.Error;
+    }
   node = undefined;
 }) ();
 
@@ -2444,11 +2611,11 @@ MIM.select_im = function (event)
     target = target.parentNode;
   var idx = 0;
   var im = false;
-  for (var lang in MIM.im_list)
-    for (var name in MIM.im_list[lang])
+  for (var lang in MIM.imlist)
+    for (var name in MIM.imlist[lang])
       if (idx++ == target.selectedIndex)
        {
-         im = MIM.im_list[lang][name];
+         im = MIM.imlist[lang][name];
          break;
        }
   document.getElementsByTagName ('body')[0].removeChild (target);
@@ -2482,15 +2649,15 @@ MIM.select_menu = function (event)
   sel.style.top = (event.clientY - 10) + "px";
   sel.target = target;
   var idx = 0;
-  for (var lang in MIM.im_list)
-    for (var name in MIM.im_list[lang])
+  for (var lang in MIM.imlist)
+    for (var name in MIM.imlist[lang])
       {
        var option = document.createElement ('option');
        var imname = lang + "-" + name;
        option.appendChild (document.createTextNode (imname));
        option.value = imname;
        sel.appendChild (option);
-       if (MIM.im_list[lang][name] == MIM.current)
+       if (MIM.imlist[lang][name] == MIM.current)
          sel.selectedIndex = idx;
        idx++;
       }
@@ -2500,7 +2667,7 @@ MIM.select_menu = function (event)
 
 MIM.test = function ()
 {
-  var im = MIM.im_list['t']['latn-post'];
+  var im = MIM.imlist['t']['latn-post'];
   var ic = new MIM.IC (im);
 
   ic.Filter (new MIM.Key ('a'));
@@ -2511,7 +2678,7 @@ MIM.test = function ()
   else {
     try {
       document.getElementById ('text').value
-       = Xex.ParseTerm (domain, body).Eval (domain).toString ();
+       = Xex.Term.Parse (domain, body).Eval (domain).toString ();
     } catch (e) {
       if (e instanceof Xex.ErrTerm)
        alert (e);
@@ -2528,7 +2695,7 @@ MIM.init = function ()
   MIM.add_event_listener (window, 'mousedown', MIM.select_menu);
   if (window.location == 'http://localhost/mim/index.html')
     MIM.server = 'http://localhost/mim';
-  MIM.current = MIM.im_list['vi']['telex'];
+  MIM.current = MIM.imlist['vi']['telex'];
 };
 
 MIM.init_debug = function ()