X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=XmlExpr.cs;h=18de2ec2dac4c13ccf9385f6f7d503980fd832bb;hb=ad9688b36b476f477e9a9aa6f2b3407b2c6b47bd;hp=56d229375c74699e18cf2686e4788d72a05b057c;hpb=e32a1b6c2d67ece78a78504b2f16814bee3da34a;p=m17n%2Fm17n-lib-cs.git diff --git a/XmlExpr.cs b/XmlExpr.cs index 56d2293..18de2ec 100644 --- a/XmlExpr.cs +++ b/XmlExpr.cs @@ -9,15 +9,14 @@ using System.Xml; namespace System.Xml { + /// + /// Static class to provide XmlExpression loader and evaluator. + /// public static class Xexpression { - private static int trace_depth = 0; - - public static int TraceDepth { - get { return trace_depth; } - set { trace_depth = value; } - } - + /// + /// Exception thrown while loading and evaluating XmlExpression. + /// public class Error : Exception { private readonly Symbol name; @@ -61,7 +60,7 @@ namespace System.Xml string str = (InnerException != null ? InnerException.ToString () : base.ToString ()) + "\n" + "Xexpression:" + name + "\n"; if (node != null) - str += " at " + node.ParentNode.OuterXml + "\n"; + str += " at " + node.OuterXml + "\n"; if (stack != null) { str += "Call stack: "; @@ -86,6 +85,7 @@ namespace System.Xml public static Symbol VariableRangeConflict = "variable-range-conflict"; public static Symbol VariableWrongRange = "variable-wrong-range"; public static Symbol VariableWrongValue = "variable-wrong-value"; + public static Symbol UnknownFunction = "unknown-function"; public static Symbol MacroExpansionError = "macro-expansion-error"; public static Symbol NoVariableName = "no-variable-anme"; @@ -739,11 +739,15 @@ namespace System.Xml internal void ThrowSymbol (Term tag) { + int i = catch_count; foreach (CatchTag elt in catch_stack) { - catch_count--; + i--; if (elt.Tag.Matches (tag)) - return; + { + catch_count = i; + return; + } } throw new Error (Error.UncaughtThrow, "No corresponding catch: {0}", tag); @@ -856,8 +860,20 @@ namespace System.Xml internal Variable Defvar (Symbol name) { - Variable vari = new Variable (this, name, Zero); - variables[name] = vari; + Variable vari; + + if (variables.TryGetValue (name, out vari)) + { + Variable.Typed typed = vari as Variable.Typed; + if (typed != null) + throw new Error (Error.VariableTypeConflict, + "Not a non-typed variable: {0}", name); + } + else + { + vari = new Variable (this, name, Zero); + variables[name] = vari; + } return vari; } @@ -971,7 +987,7 @@ namespace System.Xml domain.functions[kv.Key] = kv.Value; } - public Variable GetVar (Symbol name) + public Variable GetVarCreate (Symbol name) { Variable vari; @@ -980,6 +996,15 @@ namespace System.Xml return vari; } + public Variable GetVar (Symbol name) + { + Variable vari; + + if (! variables.TryGetValue (name, out vari)) + return null; + return vari; + } + public override string ToString () { string str = "<(functions"; @@ -1381,16 +1406,26 @@ namespace System.Xml private static Term Fand (Domain domain, Variable vari, Term[] args) { foreach (Term arg in args) - if (! arg.Eval (domain).IsTrue) - return Zero; + { + Term result = arg.Eval (domain); + if (domain.Thrown ()) + result; + if (! result.IsTrue) + return Zero; + } return One; } private static Term For (Domain domain, Variable vari, Term[] args) { foreach (Term arg in args) - if (arg.Eval (domain).IsTrue) - return One; + { + Term result = arg.Eval (domain); + if (domain.Thrown ()) + return result; + if (result.IsTrue) + return One; + } return Zero; } @@ -1404,13 +1439,21 @@ namespace System.Xml Term result = One; foreach (Term arg in args) - result = arg.Eval (domain); + { + result = arg.Eval (domain); + if (domain.Thrown ()) + return result; + } return result; } private static Term Fif (Domain domain, Variable vari, Term[] args) { - if (args[0].Eval (domain).IsTrue) + Term result = args[0].Eval (domain); + + if (domain.Thrown) + return result; + if (result.IsTrue) return args[1].Eval (domain); if (args.Length == 2) return Zero; @@ -1419,11 +1462,19 @@ namespace System.Xml private static Term Fwhen (Domain domain, Variable vari, Term[] args) { - if (! args[0].Eval (domain).IsTrue) + Term result = args[0].Eval (domain); + + if (domain.Thrown) + return result; + if (! result.IsTrue) return Zero; - Term result = One; + result = One; for (int i = 1; i < args.Length; i++) - result = args[i].Eval (domain); + { + result = args[i].Eval (domain); + if (domain.Thrown) + return result; + } return result; } @@ -1556,7 +1607,7 @@ namespace System.Xml { result = terms[i].Eval (domain); if (domain.Thrown (out caught)) - break; + return result; } return result; } @@ -1633,7 +1684,7 @@ namespace System.Xml public virtual bool Matches (TermValue other) { return Equals (other); } public override abstract bool Equals (object obj); public override abstract int GetHashCode (); - public abstract string ToString (bool detail); + public virtual string ToString (bool detail) { return ToString (); } } private class Varref : TermValue @@ -1649,7 +1700,7 @@ namespace System.Xml public override Term Eval (Domain domain) { if (vari == null || vari.domain != domain) - vari = domain.GetVar (vname); + vari = domain.GetVarCreate (vname); return vari.Value; } @@ -1681,6 +1732,7 @@ namespace System.Xml { private static Symbol name = "funcall"; public static Symbol Name { get { return name; } } + private static Term[] null_args = new Term[0]; internal Function func; internal Variable vari; @@ -1688,8 +1740,9 @@ namespace System.Xml public Funcall (Function func, Variable vari, Term[] args) { + if (args == null) + args = null_args; int nargs = args.Length; - if (nargs < func.min_args || (func.max_args >= 0 && nargs > func.max_args)) throw new Error (Error.WrongArgument, @@ -1714,7 +1767,7 @@ namespace System.Xml Function func = domain.GetFunc (fname); Variable vari; attr = node.Attributes[Qvname]; - vari = attr == null ? null : domain.GetVar (attr.Value); + vari = attr == null ? null : domain.GetVarCreate (attr.Value); XmlNodeList nlist = node.ChildNodes; int nargs = nlist.Count; Term[] args = new Term[nargs]; @@ -1917,37 +1970,93 @@ namespace System.Xml public override string ToString () { return str; } } + /// Structure of term object. public struct Term { - public int intval; - public object objval; + internal int intval; + internal object objval; - // ... + /// Create an integer term. + /// Integer value of the term. + /// An integer term. + /// Create an integer term that has the integer value + /// specified by . This is an constant + /// term; i.e. the integer value never changes. public Term (int i) { intval = i; objval = null; } - // ... + + /// Create a symbol term. + /// Symbol value of the term. + /// A symbol term. + /// Create a symbol term that has the symbol value + /// specified by . This is an constant + /// term; i.e. the symbol value never changes. It is evaluated + /// to itself. public Term (Symbol name) { intval = 0; objval = name; } - // ... + + /// Create a string term. + /// String value of the term. + /// A string term. + /// Create a string term that has the string value + /// specified by . It is evaluated to + /// itself. The string value can be modified by "ins", "del", + /// and "concat" functions. public Term (string str) { intval = 0; objval = new Str (str); } // ... + + /// Create a list term. + /// List value of the term. + /// A list term. + /// Create a list term that has the list value + /// specified by . It is evaluated to + /// itself. The list value can be modified by "ins", "del", and + /// "append" functions. public Term (List list) { intval = 0; objval = list; } // ERROR-MESSASGE + + /// Create an error term. + /// Name of the error. + /// Error message. + /// An error term. + /// Create an error term whose error name is and error message is . It is evaluated to itself. public Term (Symbol name, string message) { intval = 0; objval = new ErrorTerm (name, message); } - public Term (Str str) { intval = 0; objval = str; } - public Term (TermValue obj) { intval = 0; objval = obj; } + /// Create a term of a specific value + /// Value of the term. + /// A term. + /// Create a term whose value is . + /// It is evaluated to a term that is returned by "Eval" method + /// of . + public Term (TermValue val) { intval = 0; objval = val; } + + internal Term (Str str) { intval = 0; objval = str; } - // + /// Create a varref term. + /// Domain to create the term in. + /// Name of the referred variable. + /// A varref term. + /// Create a varref term that is evaluated to the value + /// of the referring variable. public Term (Domain domain, Symbol vname) { intval = 0; objval = new Varref (vname); } - // ... + /// Create a funcall term. + /// Domain to create the term in. + /// Name of the calling function. + /// Array of terms that are given to the + /// function as arguments. + /// A funcall term. + /// Create a funcall term that is evaluated to a term + /// returned by the function when called + /// with . public Term (Domain domain, Symbol fname, Term[] args) : this (domain, fname, Qnull, args) { } @@ -1957,7 +2066,7 @@ namespace System.Xml intval = 0; Function func = domain.GetFunc (fname); - Variable vari = vname == Qnull ? null : domain.GetVar (vname); + Variable vari = vname == Qnull ? null : domain.GetVarCreate(vname); Funcall funcall = new Funcall (func, vari, args); if (func is Function.Macro) { @@ -2323,7 +2432,7 @@ namespace System.Xml return args; } - public static Symbol parse_defun_head (Domain domain, XmlNode node) + private static Symbol parse_defun_head (Domain domain, XmlNode node) { Symbol name = node.Attributes[Qfname].Value; int min_args, max_args; @@ -2337,16 +2446,17 @@ namespace System.Xml return name; } - public static void parse_defun_body (Domain domain, XmlNode node) + private static void parse_defun_body (Domain domain, XmlNode node) { bool is_defun = node.Name == Qdefun; Symbol name = node.Attributes[Qfname].Value; Function func = domain.GetFunc (name); for (node = node.FirstChild; node != null; node = node.NextSibling) - if (node.Name != Qdescription - && node.Name != Qargs) + if (node.Name != Qdescription && node.Name != Qargs) break; + Console.WriteLine ("found body " + node.Name); + Term[] body = Parse (domain, node, null); if (is_defun) ((Function.Lambda) func).SetBody (body); @@ -2404,17 +2514,17 @@ namespace System.Xml } } - private static bool default_stop (XmlNode n) { return n == null; } - - public delegate bool ParseStop (XmlNode node); + /// Parse a node and the following siblings as "term"s in a + /// specific domain. + /// + /// + /// + /// Array of terms. - public static Term[] Parse (Domain domain, XmlNode node, ParseStop stop) + public static Term[] Parse (Domain domain, XmlNode start, XmlNode stop) { - if (stop == null) - stop = default_stop; - XmlNode n; - for (n = node; ! stop (n); n = n.NextSibling) + for (n = start; n != stop && n != null; n = n.NextSibling) if (n.NodeType == XmlNodeType.Element && (n.Name == Qdefun || n.Name == Qdefmacro)) { @@ -2422,30 +2532,30 @@ namespace System.Xml parse_defun_head (domain, n); } catch (Error e) { if (e.Node == null) - e.Node = node; + e.Node = n; throw e; } catch (Exception e) { - throw new Error (Error.UnknownError, node, e, "Parsing error"); + throw new Error (Error.UnknownError, n, e, "Parsing error"); } } List terms = new List (); - for (; node != n; node = node.NextSibling) - if (node.NodeType == XmlNodeType.Element) + for (; start != n; start = start.NextSibling) + if (start.NodeType == XmlNodeType.Element) { try { - if (node.Name == Qdefun || node.Name == Qdefmacro) - parse_defun_body (domain, node); - else if (node.Name == Qdefvar) - parse_defvar (domain, node); + if (start.Name == Qdefun || start.Name == Qdefmacro) + parse_defun_body (domain, start); + else if (start.Name == Qdefvar) + parse_defvar (domain, start); else - terms.Add (Parse (domain, node)); + terms.Add (Parse (domain, start)); } catch (Error e) { if (e.Node == null) - e.Node = node; + e.Node = start; throw e; } catch (Exception e) { - throw new Error (Error.UnknownError, node, e, "Parsing error"); + throw new Error (Error.UnknownError, start, e, "Parsing error"); } } return terms.ToArray (); @@ -2456,8 +2566,9 @@ namespace System.Xml XmlDocument doc = new XmlDocument (Symbol.NameTable); XmlNode node; - using (XmlTextReader reader = new XmlTextReader (url, doc.NameTable)) + using (XmlTextReader reader = new XmlTextReader (url, Symbol.NameTable)) { + reader.WhitespaceHandling = WhitespaceHandling.None; do { reader.Read (); } while (reader.NodeType != XmlNodeType.None @@ -2470,6 +2581,21 @@ namespace System.Xml return Parse (domain, node.FirstChild, null); } + /// Evaluate a term in a specific domain. + /// Domain to evaluate the term in. + /// The term to evaluate. + /// The result of evaluating the . + public static Term Eval (Domain domain, Term term) + { + return Eval (domain, new Term[] { term }); + } + + /// Evaluate terms in a specific domain. + /// Domain to evaluate terms in. + /// Array of terms to evaluate. + /// The result of evaluating the last term of . public static Term Eval (Domain domain, Term[] terms) { Term result = Zero; @@ -2488,5 +2614,16 @@ namespace System.Xml throw new Error (Error.UnknownError, null, e, "Runtime error"); } } + + // TRACING + + private static int trace_depth = 0; + + /// TraceDepth specifies the minimum depth of call stack + /// to suppress tracing. 0 means no tracing. + public static int TraceDepth { + get { return trace_depth; } + set { trace_depth = value; } + } } }