From de0ed92ff41426bd1cd968128588998127f11786 Mon Sep 17 00:00:00 2001 From: handa Date: Wed, 24 Feb 2010 12:53:11 +0000 Subject: [PATCH] *** empty log message *** --- xex.html | 2 +- xex.js | 373 +++++++++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 271 insertions(+), 104 deletions(-) diff --git a/xex.html b/xex.html index 20a7605..44ba89f 100644 --- a/xex.html +++ b/xex.html @@ -23,5 +23,5 @@ down0 press0 - + diff --git a/xex.js b/xex.js index 157f521..acae657 100644 --- 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 '); + 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 () -- 1.7.10.4