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; }
+ }
}
}