From: handa Date: Thu, 24 Sep 2009 00:08:28 +0000 (+0000) Subject: *** empty log message *** X-Git-Url: http://git.chise.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=31b2c4af4ae5abdd1d6aba6b17c1d088459aefee;p=m17n%2Fm17n-lib-cs.git *** empty log message *** --- diff --git a/MInputMethod.cs b/MInputMethod.cs index 5bba7b2..6c73951 100644 --- a/MInputMethod.cs +++ b/MInputMethod.cs @@ -11,6 +11,8 @@ using M17N.Input; namespace M17N.Input { + using Xex = System.Xml.Expression.Xexpression; + public class MInputMethod { // Delegaes @@ -26,7 +28,7 @@ namespace M17N.Input public static Callback GetSurroundingText; public static Callback DeleteSurroundingText; - internal static MExpression.Domain domain = new MExpression.Domain (null); + internal static Xex.Domain im_domain = new Xex.Domain (null); private static MSymbol Minput_method = "input-method"; private static MSymbol Mdescription = "description"; private static MSymbol Mvariable = "variable"; @@ -304,20 +306,22 @@ namespace M17N.Input } } - public class KeySeq : List + public class KeySeq : Xex.Object { - public KeySeq () : base () { } + List keyseq = new List (); + + public KeySeq () { } - public KeySeq (MPlist plist) : base () + public KeySeq (MPlist plist) { foreach (MPlist p in plist) { if (p.IsSymbol) - this.Add (new Key (p.Symbol)); + keyseq.Add (new Key (p.Symbol)); else if (p.IsInteger) - this.Add (new Key ((char) p.Integer)); + keyseq.Add (new Key ((char) p.Integer)); else if (p.IsPlist) - this.Add (new Key (p.Plist)); + keyseq.Add (new Key (p.Plist)); else throw new Exception ("Invalid Key Sequence: " + plist); } @@ -326,7 +330,7 @@ namespace M17N.Input public KeySeq (MText mt) : base () { for (int i = 0; i < mt.Length; i++) - this.Add (new Key ((uint) mt[i])); + keyseq.Add (new Key ((uint) mt[i])); } private static uint parse_integer (string str) @@ -357,7 +361,7 @@ namespace M17N.Input return 0; } - public KeySeq (XmlNode node) : base () + public KeySeq (XmlNode node) { XmlAttributeCollection acol = node.Attributes; XmlNode n; @@ -365,15 +369,26 @@ namespace M17N.Input if (acol != null && (n = acol["keys"]) != null) { foreach (char c in n.Value) - this.Add (new Key ((uint) c)); + keyseq.Add (new Key ((uint) c)); } for (node = node.FirstChild; node != null; node = node.NextSibling) { if (node.Name == "key-event") - this.Add (new Key ((MSymbol) node.InnerText)); + keyseq.Add (new Key ((MSymbol) node.InnerText)); else - this.Add (new Key (parse_integer (node.InnerText))); + keyseq.Add (new Key (parse_integer (node.InnerText))); + } + } + + public KeySeq (List list) + { + foreach (Xex.Term term in list) + { + if (term.IsName) + keyseq.Add (new Key ((MSymbol) term.Nameval.name)); + else + keyseq.Add (new Key (term.Strval)); } } @@ -552,9 +567,9 @@ namespace M17N.Input { public MSymbol name; public Dictionary submaps; - public MExpression actions; + public Xex actions; - public void Add (KeySeq keys, int index, MExpression actions) + public void Add (KeySeq keys, int index, Xex actions) { Map sub = null; @@ -573,7 +588,7 @@ namespace M17N.Input this.actions = actions; } - public MExpression Lookup (KeySeq keys, int index) + public Xex Lookup (KeySeq keys, int index) { Map sub; @@ -631,13 +646,13 @@ namespace M17N.Input if (title != null) mt.Cat (" \"" + title + "\""); for (MPlist p = branches; ! p.IsEmpty; p = p.next) - mt.Cat (" (" + p.Key + " " + (MExpression) p.Val + ")"); + mt.Cat (" (" + p.Key + " " + (Xex) p.Val + ")"); return (string) mt + ")"; } } // Instance members - internal MExpression.Domain local_domain; + internal Xex.Domain domain; private LoadStatus load_status = LoadStatus.None; private MDatabase.Tag tag; @@ -646,33 +661,31 @@ namespace M17N.Input private MText description; internal MText title; internal Command[] commands; - internal Variable[] variables; + internal Xex.Name[] var_names; internal Dictionary plugins; - internal MPlist bindings; internal Dictionary maps; internal MPlist states; static MInputMethod () { - domain.Defun ("insert", insert, 1, 1); - domain.Defun ("candidates", insert_candidates, 1, -1); - domain.Defun ("delete", delete, 1, 1); - domain.Defun ("select", select, 1, 1); - domain.Defun ("show", show, 0, 0); - domain.Defun ("hide", hide, 0, 0); - domain.Defun ("move", move, 1, 1); - domain.Defun ("mark", mark, 1, 1, true); - domain.Defun ("pushback", pushback, 1, 1); - domain.Defun ("pop", pop, 0, 0); - domain.Defun ("undo", undo, 0, 1); - domain.Defun ("commit", commit, 0, 0); - domain.Defun ("unhandle", unhandle, 0, 0); - domain.Defun ("shift", shift, 1, 1, true); - domain.Defun ("call", call, 2, -1, true); - // Pseudo functions to make arguments of special objects. - domain.Defun ("marker", marker, 1, 1, true); - domain.Defun ("char-at", char_at, 1, 1, true); - domain.Defun ("keyseq", keyseq, 1, -1, true); + im_domain.DefSubr (Finsert, "insert", true, 1, 1); + im_domain.DefSubr (Finsert_candidates, "candidates", true, 1, -1); + im_domain.DefSubr (Fdelete, "delete", true, 1, 1); + im_domain.DefSubr (Fselect, "select", true, 1, 1); + im_domain.DefSubr (Fshow, "show", true, 0, 0); + im_domain.DefSubr (Fhide, "hide", true, 0, 0); + im_domain.DefSubr (Fmove, "move", true, 1, 1); + im_domain.DefSubr (Fmark, "mark", true, 1, 1); + im_domain.DefSubr (Fpushback, "pushback", true, 1, 1); + im_domain.DefSubr (Fpop, "pop", true, 0, 0); + im_domain.DefSubr (Fundo, "undo", true, 0, 1); + im_domain.DefSubr (Fcommit, "commit", true, 0, 0); + im_domain.DefSubr (Funhandle, "unhandle", true, 0, 0); + im_domain.DefSubr (Fshift, "shift", true, 1, 1); + im_domain.DefSubr (Fcall, "call", true, 2, -1); + im_domain.DefSubr (Fmarker, "marker", true, 1, 1); + im_domain.DefSubr (Fchar_at, "char-at", true, 1, 1); + im_domain.DefSubr (Fkeyseq, "keyseq", true, 1, -1); MDatabase.Tag tag = new MDatabase.Tag (Minput_method, "*", "*", "*"); List list = MDatabase.List (tag); @@ -692,8 +705,10 @@ namespace M17N.Input public MSymbol Name { get { return tag[2]; } } public MSymbol SubName { get { return tag[3]; } } - public bool Info (out MText description, out MText title, - out Variable[] variables, out Command[] commands) + public bool Info (out MText description, + out MText title, + out Xex.Variable[] variables, + out Command[] commands) { if ((load_status & LoadStatus.Header) != LoadStatus.Header && ! load_header ()) @@ -706,7 +721,10 @@ namespace M17N.Input } description = this.description; title = this.title; - variables = this.variables; + variables = new Xex.Variable[var_names.Length]; + int i = 0; + foreach (Xex.Name name in var_names) + variables[i++] = domain.GetVar (name); commands = this.commands; return true; } @@ -767,7 +785,7 @@ namespace M17N.Input private bool load_body () { - local_domain = new MExpression.Domain (domain, null); + domain = new Xex.Domain (domain, null); mdb = MDatabase.Find (tag); if (mdb == null) return false; @@ -845,7 +863,7 @@ namespace M17N.Input State state = new State ((MSymbol) "init"); plist = new MPlist (); foreach (KeyValuePairkv in maps) - state.branches.Add (kv.Key, new MExpression (plist, local_domain)); + state.branches.Add (kv.Key, new Xex (plist, domain)); states.Add (state.name, state); } } @@ -903,7 +921,7 @@ namespace M17N.Input State state = new State ((MSymbol) "init"); MPlist plist = new MPlist (); foreach (KeyValuePairkv in maps) - state.branches.Add (kv.Key, new MExpression (plist, local_domain)); + state.branches.Add (kv.Key, new Xex (plist, domain)); states.Add (state.name, state); } } @@ -1054,13 +1072,132 @@ namespace M17N.Input return node.InnerText; } + private void new_variable (Xex.Name name, string desc, int val, + MPlist pl, Xex.Variable vari) + { + Xex.Term term = new Xex.Term (val); + int[] range; + + if (pl.IsEmpty) + range = null; + else + { + range = new int[pl.Count * 2]; + for (int i = 0; i < range.Length; 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: " + p); + } + } + if (vari == null) + domain.Defvar (new Xex.Variable.Int (name, desc, term, range)); + else + { + vari.Value = term; + vari.DefaultValue = term; + vari.Range = range; + } + } + + private void new_variable (Xex.Name name, string desc, MText val, + MPlist pl, Xex.Variable vari) + { + Xex.Term term = new Xex.Term ((string) val); + 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] = pl.Text; + else + throw new Exception ("Invalid range: " + p); + } + } + if (vari == null) + domain.Defvar (new Xex.Variable.Str (name, desc, term, range)); + else + { + vari.Value = term; + vari.DefaultValue = term; + vari.Range = range; + } + } + + private void new_variable (Xex.Name name, string desc, MSymbol val, + MPlist pl, Xex.Variable vari) + { + Xex.Term term = new Xex.Term ((Xex.Name) val.name); + Xex.Name[] range; + + if (pl.IsEmpty) + range = null; + else + { + range = new Xex.Name[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: " + p); + } + } + if (vari == null) + domain.Defvar (new Xex.Variable.Sym (name, desc, term, range)); + else + { + vari.Value = term; + vari.DefaultValue = term; + vari.Range = range; + } + } + private void parse_variables (MPlist plist) { variables = new Variable[plist.Count]; for (int i = 0; ! plist.IsEmpty; plist = plist.next) if (plist.IsPlist && plist.Plist.IsSymbol) - variables[i++] = new Variable (plist.Plist); + { + MPlist p = plist.Plist; + Xex.Name name = (Name) p.Symbol.name; + p = p.next; + string desc = parse_description (p); + Xex.Variable vari = null; + Xex.Term val; + + if (im_global.domain.GetVar (name, out vari)) + domain.Defvar (vari); + if (desc != null) + p = p.next; + if (! p.IsEmpty) + { + 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); + else + throw new Exception ("Unknown type: " + p.val); + } + } } private void parse_variables (XmlNode node) @@ -1149,18 +1286,18 @@ namespace M17N.Input if (im == null || ! im.Open ()) continue; if (id == MSymbol.nil) - im.local_domain.CopyFunc (local_domain); + im.domain.CopyFunc (domain); else - im.local_domain.CopyFunc (local_domain, id); + im.domain.CopyFunc (domain, id); } for (XmlNode nn = node.FirstChild; nn != null; nn = nn.NextSibling) if (nn.NodeType == XmlNodeType.Element && nn.Name != "xi:include") - local_domain.Defun ((MSymbol) node.GetAttribute ("id")); + domain.Defun ((MSymbol) node.GetAttribute ("id")); for (XmlNode nn = node.FirstChild; nn != null; nn = nn.NextSibling) if (nn.NodeType == XmlNodeType.Element && nn.Name != "xi:include") - local_domain.Defun ((MSymbol) node.GetAttribute ("id"), null, + domain.Defun ((MSymbol) node.GetAttribute ("id"), null, nn.FirstChild); } @@ -1208,9 +1345,9 @@ namespace M17N.Input if (target_type == Mmacro) { if (target_name == MSymbol.nil) - im.local_domain.CopyFunc (local_domain); + im.domain.CopyFunc (domain); else - im.local_domain.CopyFunc (local_domain, target_name); + im.domain.CopyFunc (domain, target_name); } else if (target_type == Mmap) { @@ -1251,7 +1388,7 @@ namespace M17N.Input if (! p.IsSymbol) continue; - local_domain.Defun (p.Symbol, null, null); + domain.Defun (p.Symbol, null, null); } for (MPlist pl = plist; ! pl.IsEmpty; pl = pl.next) if (pl.IsPlist) @@ -1261,7 +1398,7 @@ namespace M17N.Input if (! p.IsSymbol) continue; transform (p.next); - local_domain.Defun (p.Symbol, null, p.next); + domain.Defun (p.Symbol, null, p.next); } } @@ -1293,7 +1430,7 @@ namespace M17N.Input if (p.IsEmpty) continue; transform (p); - MExpression expr = new MExpression (p, local_domain); + MXex expr = new MXex (p, domain); map.Add (keys, 0, expr); } } @@ -1331,147 +1468,144 @@ namespace M17N.Input p = p.next; transform (p); state.branches.Add (map_name, - new MExpression (p, local_domain)); + new MXex (p, domain)); } } } - private static object insert (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Finsert (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { - ((MInputContext) domain.context).insert (args[0].Val); - - return true; + ((MInputContext) domain.context).insert (args[0]); + return args[0]; } - private static object insert_candidates (MExpression[] args, - MExpression.Domain domain) + private static Xex.Term Finsert_candidates (Xex.Domain domain, + Xex.Variable vari, + Xex.Term[] args) { - ((MInputContext) domain.context).insert_candidates ((MPlist) args[0].Val); - - return true; + ((MInputContext) domain.context).insert_candidates (args[0]); + return args[0]; } - private static object marker (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Fmarker (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { MSymbol sym = (MSymbol) args[0].Args[0].Val; return ((MInputContext) domain.context).marker (sym); } - private static object char_at (MExpression[] args, - MExpression.Domain domain) + private static Xex.Term char_at (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { return ((MInputContext) domain.context).char_at ((int) args[0].Val); } - private static object delete (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Fdelete (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { - ((MInputContext) domain.context).delete ((int) args[0].Val); + ((MInputContext) domain.context).delete ((int) args[0].Intval); return true; } - private static object select (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Fselect (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { MInputContext ic = (MInputContext) domain.context; - object val = args[0].Val; - if (val is int) - ic.select ((int) val); + if (args[0].IsInt) + ic.select (args[0].Intval); else - ic.select ((MSymbol) val); - return true; + ic.select ((MSYmbol) ((string) args[0].Nameval)); + return args[0]; } - private static object show (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Fshow (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { ((MInputContext) domain.context).show (); - - return true; + return Xex.Zero; } - private static object hide (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Fhide (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { ((MInputContext) domain.context).hide (); - - return true; + return Xex.Zero; } - private static object move (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Fmove (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { - ((MInputContext) domain.context).move ((int) args[0].Val); - - return true; + ((MInputContext) domain.context).move (args[0].Intval); + return args[0]; } - private static object mark (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Fmark (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { - MSymbol sym = (MSymbol) args[0].Val; - - ((MInputContext) domain.context).mark (sym); - return true; + ((MInputContext) domain.context).mark (args[0]); + return args[0]; } - private static object keyseq (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Fkeyseq (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { - MPlist p = new MPlist (); - - for (int i = 0; i < args.Length; i++) - p.Add (MSymbol.symbol, (MSymbol) args[i].Val); - return new KeySeq (p); + return new KeySeq (args[0].Listval); } - private static object pushback (MExpression[] args, - MExpression.Domain domain) + private static Xex.Term Fpushback (Xex.Domain domain, Xex.Variable vari, + Xex[] args) { MInputContext ic = (MInputContext) domain.context; - object val = args[0].Val; - - if (val is int) - ic.pushback ((int) val); - else if (val is MText) - ic.pushback (new KeySeq ((MText) val)); - else if (val is KeySeq) - ic.pushback ((KeySeq) val); + + if (args[0].IsInt) + ic.pushback (args[0].Intval); + else if (args[0].IsStr) + ic.pushback (new KeySeq (args[0].Strval)); else - throw new Exception ("Invalid keyseq: " + val); - return true; + ic.pushback ((KeySeq) args[0].Objval); + return args[0]; } - private static object pop (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Fpop (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { ((MInputContext) domain.context).pop (); - return true; + return Xex.Zero; } - private static object undo (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Fundo (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { - int n = args.Length == 0 ? -2 : (int) args[0].Val; + int n = args.Length == 0 ? -2 : args[0].Intval; ((MInputContext) domain.context).undo (n); - return true; + return Xex.Zero; } - private static object commit (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Fcommit (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { ((MInputContext) domain.context).commit (); - return true; + return Xex.Zero; } - private static object unhandle (MExpression[] args, - MExpression.Domain domain) + private static Xex.Term Funhandle (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { ((MInputContext) domain.context).commit (); - return false; + return Xex.Zero; } - private static object shift (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Fshift (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) { - MSymbol sym = (MSymbol) args[0].Args[0].Val; - - ((MInputContext) domain.context).shift (sym); - return true; + ((MInputContext) domain.context).shift (args[0].Symval); + return args[0]; } - private static object call (MExpression[] args, MExpression.Domain domain) + private static Xex.Term Fcall (Xex.Domain domain, Xex.Variable vari, Xex.Term[] args) { MSymbol module = (MSymbol) args[0].Args[0].Val; MSymbol method = (MSymbol) args[1].Args[0].Val; @@ -1571,12 +1705,12 @@ namespace M17N.Input internal MText following_text = new MText (); private bool key_unhandled; - internal MExpression.Domain domain; + internal Xex.Domain domain; public MInputContext (MInputMethod im) { this.im = im; - domain = new MExpression.Domain (im.local_domain, this); + domain = new Xex.Domain (im.domain, this); states = new Stack (); states.Push ((MInputMethod.State) im.states.val); keys = new MInputMethod.KeySeq (); @@ -1619,12 +1753,12 @@ namespace M17N.Input adjust_markers (from, to, mt); } - internal void insert (object arg) + internal void insert (Xex.Term arg) { - if (arg is int) - preedit_replace (cursor_pos, cursor_pos, (int) arg); + if (arg.IsInt is int) + preedit_replace (cursor_pos, cursor_pos, arg.Intval); else - preedit_replace (cursor_pos, cursor_pos, (MText) arg); + preedit_replace (cursor_pos, cursor_pos, new MText (arg.Strval)); preedit_changed = true; cursor_pos_changed = true; } @@ -1714,6 +1848,17 @@ namespace M17N.Input group = new object[column]; } + public Candidates (List list, int column) + { + int nblocks = list.Count; + + blocks = new Block[nblocks]; + for (int i = 0, start = 0; i < nblocks; i++) + start += (blocks[i] = new Block (index, list[i])).Count; + if (column > 0) + group = new object[column]; + } + public static void Detach (MInputContext ic) { ic.preedit.PopProp (0, ic.preedit.Length, MInputMethod.Mcandidates); @@ -1878,7 +2023,7 @@ namespace M17N.Input candidate_changed = true; } - internal void insert_candidates (MPlist list) + internal void insert_candidates (Xex.Term arg) { int column = 0; @@ -1888,7 +2033,7 @@ namespace M17N.Input if (val is int) column = (int) val; } - candidates = new Candidates (list, column); + candidates = new Candidates (arg.Listval, column); candidate_from = candidate_to = cursor_pos; update_candidate (); } @@ -2145,8 +2290,8 @@ namespace M17N.Input if (status == null) status = im.title; status_changed = true; - MExpression on_entry - = (MExpression) state.branches.Get (MSymbol.t); + Xex on_entry + = (Xex) state.branches.Get (MSymbol.t); if (on_entry != null) on_entry.Eval (domain); } @@ -2182,7 +2327,7 @@ namespace M17N.Input if (! result) return false; if (! arglist.IsEmpty) - (new MExpression (arglist, domain)).Eval (domain); + (new Xex (arglist, domain)).Eval (domain); return true; } diff --git a/Makefile b/Makefile index 71478bd..3837632 100644 --- a/Makefile +++ b/Makefile @@ -6,12 +6,11 @@ RUNCS = ${CS} ${DEBUG_FLAG} -codepage:${CODEPAGE} M17N_SRC = M17N.cs CORE_SRC = MSymbol.cs MPlist.cs MCharTable.cs MText.cs MDatabase.cs -EXPR_SRC = MExpression.cs INPUT_SRC = MInputMethod.cs XEX_SRC = XmlExpr.cs -DLL = M17N.dll M17NCore.dll M17NExpr.dll M17NIM.dll XmlExpr.dll +DLL = M17N.dll M17NCore.dll M17NIM.dll XmlExpr.dll EXAMPLE = symbol.exe plist.exe chartab.exe text.exe textprop.exe database.exe \ - expr.exe + xex.exe TEST = rearsticky.exe frontsticky.exe bothsticky.exe \ sensitive.exe frontsensitive.exe rearsensitive.exe @@ -21,19 +20,16 @@ M17N.dll: ${M17N_SRC} $(RUNCS) -out:$@ -t:library ${M17N_SRC} M17NCore.dll: M17N.dll ${CORE_SRC} - $(RUNCS) -out:$@ -t:library -r:M17N.dll -r:Mvp.Xml-bin-2.0/Mvp.Xml.dll ${CORE_SRC} + $(RUNCS) -out:$@ -t:library -r:M17N.dll ${CORE_SRC} -M17NExpr.dll: M17N.dll M17NCore.dll ${EXPR_SRC} - $(RUNCS) -out:$@ -t:library -r:M17N.dll -r:M17NCore.dll ${EXPR_SRC} - -M17NIM.dll: ${INPUT_SRC} M17N.dll M17NCore.dll M17NExpr.dll - $(RUNCS) -out:$@ -t:library -r:M17N.dll -r:M17NCore.dll -r:M17NExpr.dll ${INPUT_SRC} +M17NIM.dll: ${INPUT_SRC} M17N.dll M17NCore.dll XmlExpr.dll + $(RUNCS) -out:$@ -t:library -r:M17N.dll -r:M17NCore.dll -r:XmlExpr.dll ${INPUT_SRC} XmlExpr.dll: ${XEX_SRC} $(RUNCS) -out:$@ -t:library ${XEX_SRC} -input.exe: input.cs ${DLL} - $(RUNCS) -r:M17N.dll -r:M17NCore -r:M17NExpr -r:M17NIM.dll $< +input.exe: input.cs M17NIM.dll + $(RUNCS) -r:M17N.dll -r:M17NCore -r:XmlExpr -r:M17NIM.dll $< expr.exe: expr.cs $(RUNCS) -r:M17N.dll -r:M17NCore -r:M17NExpr $< diff --git a/XmlExpr.cs b/XmlExpr.cs index 806ccc0..f88d2e7 100644 --- a/XmlExpr.cs +++ b/XmlExpr.cs @@ -14,7 +14,7 @@ namespace System.Xml.Expression { private static NameTable nt = new NameTable (); - private string name; + internal string name; public Name (string str) { @@ -103,9 +103,6 @@ namespace System.Xml.Expression private static Name Ndescription = "description"; private static Name Nrange = "range"; - private static Name Nbreak = "break"; - private static Name Nreturn = "return"; - internal abstract class Function { public Name name; @@ -253,7 +250,7 @@ namespace System.Xml.Expression { try { if (args_evalled) - domain.Catch (Nreturn); + domain.Catch (CatchTag.Return); foreach (Term term in body) { result = term.Eval (domain); @@ -276,75 +273,216 @@ namespace System.Xml.Expression public class Variable : Object { public readonly Name name; + public string desc; + internal Term default_val; internal Term val; + object range; - public Variable (Name name, Term term) + public Variable (Name name, Term value) { this.name = name; - val = term; + val = value; + default_val = Zero; + } + + public virtual bool ValueP (Term val) { return true; } + + public Variable Clone () + { + Variable v = new Variable (name, val); + v.desc = desc; + v.default_val = default_val; + v.range = range; + return v; } - public virtual Term Value + public Term Value { get { return val; } - set - { - if (! ValueP (value)) - throw new Exception ("Invalid value of " + name + ": " + value); - val = value; - } + set { + if (! ValueP (value)) + throw new Exception ("Invalid value: " + value); + val = value; + } } - public override Term Eval (Domain domain) { return val; } + public Term DefaultValue + { + get { return default_val; } + set { + if (! ValueP (value)) + throw new Exception ("Invalid value: " + value); + default_val = value; + } + } - public virtual bool ValueP (Term term) { return true; } + public virtual object Range + { + get { return range; } + set { range = value; } + } + + public override Term Eval (Domain domain) { return val; } public override string ToString () { return name + "(" + val + ")"; } - internal class Int : Variable + public class Int : Variable { - public struct Range - { - public int from, to; - } + public int[] range; + + private static bool SubsetP (int[] r1, int[] r2) + { + if (r2 == null) + return true; + for (int i = 0; i < r1.Length; i += 2) + { + int j; + for (j = 0; j < r2.Length; j += 2) + if (r2[j] <= r1[i] && r2[j + 1] >= r1[i + 1]) + break; + if (j >= r2.Length) + return false; + } + return true; + } - public Range[] ranges; + private static bool SubsetP (int val, int[] r) + { + 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 (Name name, int i) : base (name, new Term (i)) { } + public Int (Name name, string description, int value, int[] range) + : base (name, new Term (value)) + { + if (! SubsetP (value, range)) + throw new Exception ("Invalid value: " + value); + desc = description; + default_val = val; + this.range = range; + } public override bool ValueP (Term term) { - int i; - - if (term.objval != null) + if (! term.IsInt) return false; - if (ranges == null) - return true; - i = term.intval; - foreach (Range r in ranges) - if (i >= r.from && i <= r.to) - return true; - return false; + return SubsetP (term.Intval, range); + } + + 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; + } } } internal class Str : Variable { - public string[] ranges; + public string[] range; + + private static bool SubsetP (string[] r1, string[] r2) + { + foreach (string s in r1) + if (! SubsetP (s, r2)) + return false; + return true; + } + + private static bool SubsetP (string str, string[] r) + { + foreach (string s in r) + if (str == s) + return true; + return false; + } - public Str (Name name, string str) : base (name, new Term (str)) { } + public Str (Name name, string description, string value, string[] range) + : base (name, new Term (value)) + { + if (! SubsetP (value, range)) + throw new Exception ("Invalid value: " + value); + desc = description; + default_val = val; + this.range = range; + } public override bool ValueP (Term term) { if (! (term.objval is string)) return false; - if (ranges == null) + return SubsetP (term.Strval, range); + } + + 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; + } + } + } + + internal class Sym : Variable + { + public Name[] range; + + private static bool SubsetP (Name[] r1, Name[] r2) + { + foreach (Name n in r1) + if (! SubsetP (n, r2)) + return false; return true; - string str = (string) term.objval; - foreach (string s in ranges) - if (s == str) - return true; - return false; + } + + private static bool SubsetP (Name name, Name[] r) + { + foreach (Name n in r) + if (name == n) + return true; + return false; + } + + public Sym (Name name, string description, Name value, Name[] range) + : base (name, new Term (value)) + { + if (! SubsetP (value, range)) + throw new Exception ("Invalid value: " + value); + desc = description; + default_val = val; + this.range = range; + } + + public override bool ValueP (Term term) + { + if (! (term.objval is Name)) + return false; + return SubsetP (term.Nameval, range); + } + + public override object Range { + get { return range; } + set { + Name[] r = (Name[]) value; + if (! SubsetP (r, range) + || ! SubsetP (val.Nameval, r) + || ! SubsetP (default_val.Nameval, r)) + throw new Exception ("Invalid range"); + range = r; + } } } } @@ -400,15 +538,39 @@ namespace System.Xml.Expression } #endif + internal class CatchTag : IEquatable + { + private object val; + + public CatchTag (Name name) { val = name.name; } + private CatchTag (int i) { val = i; } + + public static CatchTag Return = new CatchTag (0); + public static CatchTag Break = new CatchTag (1); + + public static bool operator== (CatchTag t1, CatchTag t2) + { return t1.val == t2.val; } + + public static bool operator!= (CatchTag t1, CatchTag t2) + { return t1.val != t2.val; } + + public bool Equals (CatchTag tag) { return this.val == tag.val; } + public override bool Equals (object val) { return this.val == val; } + + public override int GetHashCode () { return val.GetHashCode (); } + } + public class Domain { public object context; public int depth = 0; internal Dictionary functions; + internal Dictionary> + modules = new Dictionary> (); internal Dictionary variables; internal Bindings bindings; - private Stack catch_stack = new Stack (); + private Stack catch_stack = new Stack (); private int catch_count = 0; internal Domain () @@ -439,9 +601,9 @@ namespace System.Xml.Expression bindings = bindings.UnboundTo (boundary); } - internal void Catch (Name name) + internal void Catch (CatchTag tag) { - catch_stack.Push (name); + catch_stack.Push (tag); catch_count++; } @@ -458,21 +620,31 @@ namespace System.Xml.Expression internal void ThrowReturn () { - foreach (Name tag in catch_stack) + foreach (CatchTag tag in catch_stack) { catch_count--; - if (tag == Nreturn) + if (tag == CatchTag.Return) break; } } internal void ThrowBreak () { - if (catch_stack.Peek () != Nbreak) + if (catch_stack.Peek () != CatchTag.Break) throw new Exception ("No outer loop to break"); catch_count--; } + internal void ThrowTag (CatchTag tag) + { + foreach (CatchTag elt in catch_stack) + { + catch_count--; + if (elt == tag) + break; + } + } + public void DefSubr (Builtin builtin, string str, bool setvar, int min_arg, int max_arg, params string[] aliases) { @@ -509,7 +681,7 @@ namespace System.Xml.Expression return lambda; } - internal Function Defun (XmlNode node) + public void Defun (XmlNode node) { Name name = node.Attributes[Nfname].Value; Function func; @@ -517,17 +689,22 @@ namespace System.Xml.Expression if (! functions.TryGetValue (name, out func)) func = RegisterFunction (node); ((Function.Lambda) func).SetBody (node, this); - return func; } public void Defvar (XmlNode node) { Name name = node.Attributes[0].Value; + String desc; Variable vari; node = node.FirstChild; if (node.Name == Ndescription) - node = node.NextSibling; + { + desc = node.InnerText; + node = node.NextSibling; + } + else + desc = null; if (node != null) { Name type = node.Name; @@ -544,48 +721,110 @@ namespace System.Xml.Expression if (type == Ninteger) { - Variable.Int vi = new Variable.Int (name, parse_integer (val)); + int intval = parse_integer (val); + int[] range = null; if (range_list != null) { - vi.ranges = new Variable.Int.Range[nranges]; - + range = new int[nranges * 2]; for (int i = 0; i < nranges; i++) { XmlNode n = range_list[i]; - if (n.Name == Nrange) { - vi.ranges[i].from = - parse_integer (n.FirstChild.InnerText); - vi.ranges[i].to = - parse_integer (n.LastChild.InnerText); + range[i * 2] + = parse_integer (n.FirstChild.InnerText); + range[i * 2 + 1] + = parse_integer (n.LastChild.InnerText); } else { - int num = parse_integer (n.InnerText); - vi.ranges[i].from = vi.ranges[i].to = num; + range[i * 2] + = range[i * 2 + 1] + = parse_integer (n.InnerText); } } } - vari = vi; + + if (variables.TryGetValue (name, out vari)) + { + if (! (vari is Variable.Int)) + throw new Exception ("Inalid value"); + vari = vari.Clone (); + Term v = new Term (intval); + vari.Value = v; + vari.DefaultValue = v; + if (range != null) + vari.Range = range; + } + else + vari = new Variable.Int (name, desc, intval, range); } else if (type == Nstring) { - Variable.Str vs = new Variable.Str (name, val); + string[] range = null; + if (range_list != null) + { + range = new string[nranges]; + for (int i = 0; i < nranges; i++) + range[i] = range_list[i].InnerText; + } + + if (variables.TryGetValue (name, out vari)) + { + if (! (vari is Variable.Str)) + throw new Exception ("Invalid value"); + vari = vari.Clone (); + Term v = new Term (val); + vari.Value = v; + vari.DefaultValue = v; + if (range != null) + vari.Range = range; + } + else + vari = new Variable.Str (name, desc, val, range); + } + else if (type == Nsymbol) + { + Name[] range = null; if (range_list != null) - vs.ranges = new string[nranges]; - for (int i = 0; i < nranges; i++) - vs.ranges[i] = range_list[i].Value; - vari = vs; + { + range = new Name[nranges]; + for (int i = 0; i < nranges; i++) + range[i] = range_list[i].InnerText; + } + + if (variables.TryGetValue (name, out vari)) + { + if (! (vari is Variable.Sym)) + throw new Exception ("Invalid value"); + vari = vari.Clone (); + Term v = new Term (val); + vari.Value = v; + vari.DefaultValue = v; + if (range != null) + vari.Range = range; + } + else + vari = new Variable.Sym (name, desc, val, range); } else throw new Exception ("Unknown type: " + type); } else - vari = new Variable (name, Zero); + { + if (variables.TryGetValue (name, out vari)) + vari = vari.Clone (); + else + vari = new Variable (name, Zero); + } variables[name] = vari; } + public void Defvar (Variable vari) + { + variables[vari.name] = vari; + } + internal Variable Defvar (Name name) { Variable vari = new Variable (name, Zero); @@ -616,7 +855,7 @@ namespace System.Xml.Expression domain.functions[kv.Key] = kv.Value; } - internal Variable GetVar (Name name) + public Variable GetVar (Name name) { Variable vari; @@ -700,6 +939,8 @@ namespace System.Xml.Expression basic.DefSpecial (Fforeach, "foreach", 2, -1); basic.DefSpecial (Fquote, "quote", 1, 1); basic.DefSpecial (Ftype, "type", 1, 1); + basic.DefSpecial (Fcatch, "catch", 2, 2); + basic.DefSpecial (Fthrow, "throw", 1, 2); } private static Term Fset (Domain domain, Variable vari, Term[] args) @@ -1090,7 +1331,7 @@ namespace System.Xml.Expression { Term result = Zero; try { - domain.Catch (Nbreak); + domain.Catch (CatchTag.Break); while (! domain.Thrown) foreach (Term arg in args) { @@ -1108,7 +1349,7 @@ namespace System.Xml.Expression { Term result = Zero; try { - domain.Catch (Nbreak); + domain.Catch (CatchTag.Break); while (! domain.Thrown && args[0].Eval (domain).IsTrue) for (int i = 1; i < args.Length; i++) { @@ -1149,7 +1390,7 @@ namespace System.Xml.Expression Bindings current = domain.bindings; try { - domain.Catch (Nbreak); + domain.Catch (CatchTag.Break); foreach (Term term in list) { domain.Bind (vari, term); @@ -1188,9 +1429,27 @@ namespace System.Xml.Expression return TermTerm; } - public abstract class Object + private static Term Fcatch (Domain domain, Variable vari, Term[] args) { - public abstract Term Eval (Domain domain); + Term result = Zero; + try { + domain.Catch (new CatchTag (args[0].Nameval)); + result = args[1].Eval (domain); + } finally { + domain.Uncatch (); + } + return result; + } + + private static Term Fthrow (Domain domain, Variable vari, Term[] args) + { + domain.ThrowTag (new CatchTag (args[0].Nameval)); + return (args.Length == 1 ? Zero : args[1]); + } + + public class Object + { + public virtual Term Eval (Domain domain) { return new Term (this); } } private class Funcall : Object @@ -1199,12 +1458,34 @@ namespace System.Xml.Expression internal Variable vari; internal Term[] args; - public Funcall (Function func, Variable vari, Term[] args) - { - this.func = func; - this.vari = vari; - this.args = args; - } + public Funcall (XmlNode node, Domain domain) + { + vari = null; + Name name = node.Name; + + if (name == Nfuncall) + name = node.Attributes[0].Value; + else if (node.Attributes[Nvname] != null) + vari = domain.GetVar (node.Attributes[Nvname].Value); + func = domain.GetFunc (name); + XmlNodeList nlist = node.ChildNodes; + int nargs = nlist.Count; + + if (nargs < func.min_arg + || (func.max_arg >= 0 && nargs > func.max_arg)) + throw new Exception ("Invalid number of arguments to: " + + name + " " + nargs); + args = new Term[nargs]; + for (int i = 0; i < nlist.Count; i++) + args[i] = new Term (nlist[i], domain); + } + + public Funcall (Domain domain, Name fname, Name vname, Term[] args) + { + func = domain.GetFunc (fname); + vari = domain.GetVar (vname); + this.args = args; + } public override Term Eval (Domain domain) { @@ -1240,7 +1521,7 @@ namespace System.Xml.Expression public Term (Name name) { intval = 0; objval = name; } public Term (string str) { intval = 0; objval = str; } public Term (List list) { intval = 0; objval = list; } - public Term (Term term) { intval = 0; objval = term; } + public Term (Term term) { intval = term.intval; objval = term.objval; } public Term (Object obj) { intval = 0; objval = obj; } public Term (XmlNode node, Domain domain) @@ -1270,31 +1551,18 @@ namespace System.Xml.Expression objval = list; } else - { - Function func; - Variable vari = null; - Term[] args; - - if (name == Nfuncall) - name = node.Attributes[0].Value; - else if (node.Attributes[Nvname] != null) - vari = domain.GetVar (node.Attributes[Nvname].Value); - func = domain.GetFunc (name); - XmlNodeList nlist = node.ChildNodes; - int nargs = nlist.Count; - - if (nargs < func.min_arg - || (func.max_arg >= 0 && nargs > func.max_arg)) - throw new Exception ("Invalid number of arguments to: " - + name + " " + nargs); - args = new Term[nargs]; - for (int i = 0; i < nlist.Count; i++) - args[i] = new Term (nlist[i], domain); - objval = new Funcall (func, vari, args); - } + objval = new Funcall (node, domain); } } + public int Objval { + get { + if (objval == null) + throw new Exception ("term is an integer: " + this); + return objval; + } + } + public int Intval { get { if (objval != null) @@ -1311,6 +1579,14 @@ namespace System.Xml.Expression } } + public string Nameval { + get { + if (! IsName) + throw new Exception ("term is not symbol: " + this); + return (Name) objval; + } + } + public List Listval { get { if (! IsList) @@ -1333,6 +1609,12 @@ namespace System.Xml.Expression public bool IsName { get { return (objval is Name); } } public bool IsList { get { return (objval is List); } } + public bool IsType (Type type) + { + return (objval == null ? type == typeof (int) + : type == objval.GetType ()); + } + public Term Eval (Domain domain) { if (objval == null || objval is Name || objval is string) @@ -1341,10 +1623,6 @@ namespace System.Xml.Expression return new Term ((List) objval); if (objval is Object) return ((Object) objval).Eval (domain); - if (objval is Variable) - return ((Variable) objval).val; - if (objval is Term) - return (Term) objval; throw new Exception ("invalid Term object: " + objval); } @@ -1394,13 +1672,13 @@ namespace System.Xml.Expression } } - static Term Zero = new Term (0); - static Term One = new Term (1); - static Term TermInt = new Term (Ninteger); - static Term TermStr = new Term (Nstring); - static Term TermName = new Term (Nsymbol); - static Term TermList = new Term (Nlist); - static Term TermTerm = new Term ((Name) "term"); + static private Term Zero = new Term (0); + static private Term One = new Term (1); + static private Term TermInt = new Term (Ninteger); + static private Term TermStr = new Term (Nstring); + static private Term TermName = new Term (Nsymbol); + static private Term TermList = new Term (Nlist); + static private Term TermTerm = new Term ((Name) "term"); internal static int parse_integer (string str) { @@ -1415,7 +1693,7 @@ namespace System.Xml.Expression if (c == '?') return str[1]; - if (c == '0' && str[1] == 'x') + if ((c == '0' || c == '#') && str[1] == 'x') { i = 0; for (int idx = 2; idx < len; idx++) @@ -1453,25 +1731,10 @@ namespace System.Xml.Expression private Term[] terms; - public Xexpression (string url, Domain domain) + private void parse_terms (Domain domain, XmlNode node) { - XmlDocument doc = new XmlDocument (Name.Table); - XmlNode node; - - using (XmlTextReader reader = new XmlTextReader (url, Name.Table)) - { - do { - reader.Read (); - } while (reader.NodeType != XmlNodeType.None - && (reader.NodeType != XmlNodeType.Element - || reader.Name != Nexpr)); - if (reader.NodeType == XmlNodeType.None) - throw new Exception ("Node not found"); - node = doc.ReadNode (reader); - } - int nterms = 0; - for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling) + for (XmlNode n = node; n != null; n = n.NextSibling) if (n.NodeType == XmlNodeType.Element) { if (n.Name == Ndefun) @@ -1484,7 +1747,7 @@ namespace System.Xml.Expression terms = new Term[nterms]; int i = 0; - for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling) + for (XmlNode n = node; n != null; n = n.NextSibling) if (n.NodeType == XmlNodeType.Element) { if (n.Name == Ndefun) @@ -1494,13 +1757,37 @@ namespace System.Xml.Expression } } + public Xexpression (Domain domain, XmlNode node) + { + parse_terms (domain, node); + } + + public Xexpression (Domain domain, string url) + { + XmlDocument doc = new XmlDocument (Name.Table); + XmlNode node; + + using (XmlTextReader reader = new XmlTextReader (url, Name.Table)) + { + do { + reader.Read (); + } while (reader.NodeType != XmlNodeType.None + && (reader.NodeType != XmlNodeType.Element + || reader.Name != Nexpr)); + if (reader.NodeType == XmlNodeType.None) + throw new Exception ("Node not found"); + node = doc.ReadNode (reader); + } + parse_terms (domain, node.FirstChild); + } + public Term Eval (Domain domain) { Term result = Zero; domain.depth = 0; try { - domain.Catch (Nreturn); + domain.Catch (CatchTag.Return); foreach (Term term in terms) { result = term.Eval (domain); diff --git a/xex.cs b/xex.cs index 1ea49e0..a6190f2 100644 --- a/xex.cs +++ b/xex.cs @@ -2,16 +2,17 @@ using System; using System.Collections.Generic; using System.IO; using System.Xml; -using System.Xml.Expression; +using Xex = System.Xml.Expression.Xexpression; public class Test { - public static void Main() + public static void Main(params string[] args) { - Xexpression.Domain domain = new Xexpression.Domain (null); - Xexpression xex = new Xexpression ("xex.xml", domain); + Xex.Domain domain = new Xex.Domain (null); + Xex xex = new Xex (domain, "xex.xml"); - Xexpression.debug_level = 10; + if (args.Length >= 2 && args[0] == "-d") + Xex.debug_level = int.Parse (args[1]); Console.WriteLine (xex); Console.WriteLine (xex.Eval (domain)); } diff --git a/xex.txt b/xex.txt index fce2ebd..5426526 100644 --- a/xex.txt +++ b/xex.txt @@ -22,7 +22,7 @@ OPTIONAL = REST = '' VAR '' -DEFVAR = DEFVAR-INT DEFVAR-STR +DEFVAR = DEFVAR-INT DEFVAR-STR DEFVAR-SYM DEFVAR-INT = '' @@ -38,6 +38,13 @@ DEFVAR-STR = STR * '' +DEFVAR-SYM = + '' + DESCRIPTION ? + SYMBOL ? + SYMBOL * + '' + DESCRIPTION = '' [ TEXT | GETTEXT ] '' @@ -67,9 +74,9 @@ PREDEFINED = | 'lt' | 'le' | 'eq' | 'ge' | 'gt' | 'noteq' | 'add' | 'sub' | 'mul' | 'div' | 'mod' | 'logand' | 'logior' | 'logxor' | 'lsh' - | 'append' | 'concat' | 'nth' | 'copy' | 'ins' | 'del' + | 'append' | 'concat' | 'length' | 'nth' | 'copy' | 'ins' | 'del' | 'progn' | 'if' | 'when' | 'cond' - | 'loop' | 'break' | 'while' | 'foreach' + | 'loop' | 'while' | 'foreach' | 'break' | 'return' | 'quote' | 'eval' | 'type' ;; TERM has a value, and is evaluated to a TERM as below. @@ -117,6 +124,7 @@ ANYTERM = TERM '' INTTERM INTTERM '' '' ANYTERM + '' '' [ INTTERM | STRTERM | LISTTERM ] + '' +'' [ STRTERM | LISTTERM ] '' '' INTTERM [ STRTERM | LISTTERM ] '' '' LISTTERM '' '' INTTERM [ STRTERM | LISTTERM ] '' @@ -131,6 +139,8 @@ ANYTERM = TERM '' TERM + '' '' TERM + '' '' TERM + '' +'' ANYTERM ? '' +'' ANYTERM ? '' '' TERM '' '' TERM '' '' ANYTERM '' diff --git a/xex.xml b/xex.xml index 95511b0..47115fa 100644 --- a/xex.xml +++ b/xex.xml @@ -23,23 +23,28 @@ - - - - + + + + + + + looptest-finished - - - 0 - returned - 1 - - - 10 ABC + tag + + + 0 + tagreturned + 1 + + + + 1123 24 @@ -60,5 +65,7 @@ 1 + ?a?b + 1